4 A Programmer's Text Editor
8 Copyright (C) 1991-2007 Angel Ortega <angel@triptico.com>
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 http://www.triptico.com
28 /* main TUI namspace */
33 mp.colors.menu = { 'text' => [ 'white', 'blue' ], 'flags' => [ 'bright' ] };
37 sub mp.tui.prompt(prompt)
38 /* draw a prompt on screen */
40 /* delete all possible newlines */
41 prompt = sregex("/\n/g", prompt, ' ');
43 mp.tui.attr(mp.colors.normal.attr);
44 mp.tui.move(0, mp.window.ty - 1, 1);
45 mp.tui.addstr(prompt);
50 sub mp.tui.readline(prompt, history, default, flags)
51 /* the readline function, with special functionality in 'flags' */
55 mp.tui.prompt(prompt ~ ' ');
59 /* get the history stack */
60 h = mp.get_history(history);
62 /* create the clipping regular expression */
63 v = '/.{1,' ~ (mp.window.tx - c[0] - 1) ~ '}$/';
71 /* builds the string */
72 s = regex(v, r) || '';
74 /* if it's a password, change everything to asterisks */
76 s = sregex('/./g', s, flags.password);
78 /* draws the string */
79 mp.tui.move(c[0], c[1], 1);
84 if(k eq 'enter') break;
86 if(k eq 'escape') { r = NULL; break; }
88 if(k eq 'backspace') r = sregex('/.$/', r);
90 if(k eq 'ctrl-u') r = '';
92 if(k eq 'space') r = r ~ ' ';
94 if(k eq 'cursor-up' && size(h)) { i--; r = h[i % size(h)]; }
96 if(k eq 'cursor-down' && size(h)) { i++; r = h[i % size(h)]; }
102 /* if a string was accepted, store in the history */
103 if(h != NULL && size(r) && h[-1] ne r)
110 sub mp.tui.list(prompt, data, pos)
111 /* select from a list */
115 mp.tui.move(0, 0, 1);
116 mp.tui.addstr(prompt);
119 ty = mp.window.ty - 1;
122 r = '/^.{1,' ~ (mp.window.tx) ~ '}/';
124 if(pos == NULL) pos = 0;
132 if(pos >= size(data)) pos = size(data) - 1;
135 if(pos < vy) vy = pos;
136 if(vy + ty <= pos) vy = pos - ty + 1;
138 /* draw all the lines */
142 local l = data[n + vy];
147 mp.tui.move(0, n + 1, 1);
150 mp.tui.attr(mp.colors.cursor.attr);
152 mp.tui.attr(mp.colors.normal.attr);
154 mp.tui.addstr(regex(r,
155 sprintf("%-" ~ mp.window.tx ~ "s", l)));
160 /* clean the rest of lines */
163 mp.tui.move(0, n + 1, 1);
169 if(k eq 'cursor-up') pos--;
171 if(k eq 'cursor-down') pos++;
173 if(k eq 'page-up') pos -= ty;
175 if(k eq 'page-down') pos += ty;
177 if(k eq 'home') pos = 0;
179 if(k eq 'end') pos = size(data) - 1;
181 if(k eq 'enter') break;
183 if(k eq 'escape') { pos = NULL; break; }
192 sub mp.drv.alert(msg)
194 mp.tui.prompt(msg ~ L(" [ENTER]"));
196 while(mp.tui.getkey() ne 'enter');
200 sub mp.drv.confirm(msg, def)
205 /* get the initials for localized 'Yes' and 'No' */
206 y = regex('/^./', L("Yes"));
207 n = regex('/^./', L("No"));
210 msg = msg ~ ' (' ~ y ~ '/' ~ n ~ ')';
213 /* a default option? add to prompt */
214 msg = msg ~ ' [' ~ (def && y || n) ~ ']';
221 local k = mp.tui.getkey();
223 if (regex('/^' ~ y ~ '$/i', k)) ret = 1;
224 if (regex('/^' ~ n ~ '$/i', k)) ret = 2;
225 if (k eq 'escape') ret = 0;
226 if (k eq 'enter') ret = (def && 1 || 2);
232 sub mp.drv.openfile(prompt)
234 mp.tui.readline(prompt, 'openfile');
238 sub mp.drv.savefile(prompt)
240 mp.tui.readline(prompt, 'savefile');
244 sub mp.drv.form(widgets)
248 foreach(local w, widgets)
253 r1 = mp.tui.readline(w.label, w.history, w.value);
255 if(w.type eq 'password')
256 r1 = mp.tui.readline(w.label, NULL, NULL,
257 { 'password' => '*' });
259 if(w.type eq 'checkbox')
261 /* return value conversion */
262 local c = [ NULL, 1, 0 ];
264 r1 = c[mp.drv.confirm(w.label, w.value)];
268 r1 = mp.tui.list(w.label, w.list, w.value);
291 while(action == NULL && key ne 'escape')
297 if(mx < 0) mx = size(mp.menu) - 1;
298 if(mx >= size(mp.menu)) mx = 0;
300 /* draw the menu bar */
301 mp.tui.attr(mp.colors.menu.attr);
302 mp.tui.move(0, 0, 1);
304 while(n < size(mp.menu))
307 local l = L(mp.menu[n][0]);
309 /* strip (by now) the & */
310 l = sregex('/&/g', l, NULL);
312 mp.tui.attr(mp.colors.menu.attr);
317 pos = mp.tui.getxy();
318 mp.tui.attr(mp.colors.cursor.attr);
326 /* get the menu options */
329 /* calculate panel optimal dimensions */
334 local l = mp.menu_label(n);
340 /* if the panel will surpass the right margin,
342 if(pos[0] + pos[2] > mp.window.tx)
343 pos[0] = pos[2] - mp.window.tx;
346 mp.tui.attr(mp.colors.menu.attr);
347 mp.tui.openpanel(pos[0], 1, pos[2] + 2, size(mo) + 2);
351 while(key ne 'escape')
353 /* draw the options */
357 local l = mp.menu_label(mo[n]);
361 mp.tui.attr(mp.colors.cursor.attr);
363 mp.tui.attr(mp.colors.menu.attr);
367 mp.tui.move(1, 1 + n);
368 mp.tui.addstr(sprintf("%-" ~ pos[2] ~ "s", l));
374 /* move the hw cursor to the selected option */
375 mp.tui.move(1, 1 + my);
379 key = mp.tui.getkey();
381 if(key eq 'cursor-up')
383 /* move up avoiding separators */
389 if(mo[my] ne '-') break;
393 if(key eq 'cursor-down')
395 /* move down avoiding separators */
401 if(mo[my] ne '-') break;
405 if(key eq 'cursor-right') { mx++; break; }
407 if(key eq 'cursor-left') { mx--; break; }
409 if(key eq 'enter') { action = mo[my]; break; }
415 mp.tui.attr(mp.color.normal.attr);
418 mp.process_action(action);
424 sub mp.drv.busy(onoff)
426 mp.tui.prompt(onoff && L("Please, wait...") || '');
430 /* returns the main namespace */