1 module dcc.curses.uput; 2 3 private import std.string; 4 private import std.utf : count; 5 private import std.conv : to; 6 7 private import deimos.ncurses.ncurses; 8 9 int _uput_default_exit; 10 string uput(WINDOW* w, int y, int x, int length, string str, string prompt, out int exit = _uput_default_exit) { 11 /* 12 +------------------------[ WHAT YOU PUT IN ]-------------------------------+ 13 |UPUT(y, x, length, fg, bg, str, exit) | 14 +--------------------------------------------------------------------------+ 15 |y -> Row where INPUT will start | 16 |x -> Column where INPUT will start | 17 |length -> Maximum length of INPUT | 18 |str -> String to be edited | 19 +---------------------[ WHAT YOU GET BACK ]--------------------------------+ 20 | | 21 | If UPUT is exited by the user pressing ESCAPE, then the FUNCTION will | 22 | return the original string it was given (ie: no changes are made). If | 23 | UPUT is exited any other way (TAB, SHIFT-TAB, UP, DOWN, ENTER), then | 24 | the edited string is returned. | 25 | | 26 | In either case, the SHARED variable "keyflag%" is returned with a value | 27 | which is dependent on HOW UPUT was exited, following the chart below | 28 | +-----------------------------------+ 29 | ESCAPE -> keyflag = 5 |The values are based on the KEYPAD!| 30 | ENTER -> keyflag = 0 +--------------+--------+-----------+ 31 | UP ARROW -> keyflag = 8 | (7) | UP(8) | (9) | 32 | DOWN ARROW -> keyflag = 2 +--------------+--------+-----------+ 33 | TAB -> keyflag = 6 | SHFT-TAB(4)| ESC(5) |TAB(6) | 34 | SHIFT-TAB -> keyflag = 4 +--------------+--------+-----------+ 35 | | (1) | DOWN(2)| (3) | 36 | +--------------+--------+-----------| 37 | | ENTER(0) | | 38 +--------------------------------------+-----------------------------------+ 39 */ 40 int exitflag = 0, curspos = cast(int)str.count, counter; 41 dchar ky; 42 string original = cast(string)str.dup; 43 44 string display = str; 45 if (display.length > length) { 46 display = display[0 .. length]; 47 } 48 49 int original_x = x; 50 x += prompt.count; 51 52 keypad(w, true); 53 54 void fill(char c) { 55 wmove(w, y, original_x); 56 for (counter=0; counter < length; counter++) { 57 waddch(w, ' '); 58 } 59 wmove(w, y, x); 60 } 61 62 void print(string str, int offset = -1) { 63 mvwprintw(w, y, original_x, "%s", prompt.toStringz()); 64 65 if (offset >= 0) { 66 wmove(w, y, x + offset); 67 } 68 69 waddstr(w, str.toStringz()); 70 } 71 72 void move(int offset) { 73 wmove(w, y, x + offset); 74 } 75 76 int scroll_offset = 0; 77 78 do { 79 fill(' '); 80 print(display); 81 82 move(curspos); 83 84 curs_set(2); 85 86 wrefresh(w); 87 wget_wch(w, &ky); 88 89 switch (ky) { 90 case KEY_LEFT: 91 if (curspos > 0) { 92 curspos--; 93 } else if (scroll_offset > 0) { 94 scroll_offset--; 95 } 96 97 break; 98 case KEY_RIGHT: 99 if (curspos < length - 1) { 100 curspos++; 101 } else if (str.count > length && scroll_offset + length <= str.count) { 102 scroll_offset++; 103 } 104 break; 105 case KEY_HOME: 106 //case KEY_A1: =KEY_HOME on Linux so not required 107 curspos = 0; 108 scroll_offset = 0; 109 break; 110 case KEY_END: 111 //case KEY_C1: =KEY_END on Linux so not required 112 str = str.stripRight(); 113 curspos = cast(int)str.count; 114 if (curspos > length) { 115 curspos = length - 1; 116 scroll_offset = curspos - length + 1; 117 } 118 break; 119 case KEY_DC: //delete key 120 if (curspos > str.count - 1) { 121 break; 122 } 123 124 dstring utf32 = to!dstring(str.dup); 125 str = to!string(utf32[0 .. curspos] ~ utf32[curspos + 1 .. $]); 126 break; 127 case 127: 128 case KEY_BACKSPACE: 129 if (curspos > 0) { 130 dstring utf32 = to!dstring(str.dup); 131 str = to!string(utf32[0 .. curspos - 1] ~ utf32[curspos .. $]); 132 curspos--; 133 134 if (scroll_offset > 0) { 135 scroll_offset--; 136 } 137 } 138 break; 139 case 10: // enter 140 exitflag = 10; 141 break; 142 case KEY_UP: // up-arrow 143 exitflag = 8; 144 break; 145 case KEY_DOWN: // down-arrow 146 exitflag = 2; 147 break; 148 case 9: // tab 149 exitflag = 6; 150 break; 151 case KEY_BTAB: // shift-tab 152 exitflag = 4; 153 break; 154 case 27: //esc 155 str = original; 156 exitflag = 5; 157 break; 158 default: 159 if (curspos < str.count) { 160 dstring utf32 = to!dstring(str.dup); 161 ulong pos = curspos; 162 str = to!string(utf32[0 .. pos] ~ ky ~ utf32[pos .. $]); 163 } else { 164 str ~= ky; 165 } 166 167 curspos++; 168 169 if (curspos >= length - 1) { 170 scroll_offset++; 171 } 172 } 173 174 dstring utf32 = to!dstring(str.dup); 175 auto end = utf32.length < scroll_offset + length - 1 ? utf32.length : scroll_offset + length - 1; 176 display = to!string(utf32[scroll_offset .. end]); 177 } while (!exitflag); 178 179 exit = exitflag; 180 return str.stripRight(); 181 }