We need klibc-1.4.26 for getopt_long() to actually work.
[syslinux.git] / menu / libmenu / tui.c
blobcb8c1936659c6ffddca480dbf6f1b32592a916a3
1 /* -*- c -*- ------------------------------------------------------------- *
3 * Copyright 2004-2006 Murali Krishnan Ganapathy - All Rights Reserved
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 * Boston MA 02111-1307, USA; either version 2 of the License, or
9 * (at your option) any later version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
13 #include "tui.h"
14 #include <string.h>
15 #include <com32.h>
16 #include <stdlib.h>
18 com32sys_t inreg,outreg; // Global register sets for use
20 char bkspstr[] = " \b$";
21 char eolstr[] = "\n$";
22 #define GETSTRATTR 0x07
24 // Reads a line of input from stdin. Replace CR with NUL byte
25 // password <> 0 implies not echoed on screen
26 // showoldvalue <> 0 implies currentvalue displayed first
27 // If showoldvalue <> 0 then caller responsibility to ensure that
28 // str is NULL terminated.
29 void getuserinput(char *stra, unsigned int size, unsigned int password,
30 unsigned int showoldvalue)
32 unsigned char c,scan;
33 char *p,*q; // p = current char of string, q = tmp
34 char *last; // The current last char of string
35 char *str; // pointer to string which is going to be allocated
36 char page;
37 char row,col;
38 char start,end; // Cursor shape
39 char fudge; // How many chars should be removed from output
40 char insmode; // Are we in insert or overwrite
42 page = getdisppage();
43 getpos(&row,&col,page); // Get current position
44 getcursorshape(&start,&end);
45 insmode = 1;
47 str = (char *)malloc(size+1); // Allocate memory to store user input
48 memset(str,0,size+1); // Zero it out
49 if (password != 0) showoldvalue = 0; // Password's never displayed
51 if (showoldvalue != 0) strcpy(str,stra); // If show old value copy current value
53 last = str;
54 while (*last) {last++;} // Find the terminating null byte
55 p = str+ strlen(str);
57 if (insmode == 0)
58 setcursorshape(1,7); // Block cursor
59 else setcursorshape(6,7); // Normal cursor
61 // Invariants: p is the current char
62 // col is the corresponding column on the screen
63 if (password == 0) // Not a password, print initial value
65 gotoxy(row,col,page);
66 csprint(str,GETSTRATTR);
68 while (1) { // Do forever
69 c = inputc(&scan);
70 if (c == '\r') break; // User hit Enter getout of loop
71 if (scan == ESCAPE) // User hit escape getout and nullify string
72 { *str = 0;
73 break;
75 fudge = 0;
76 // if scan code is regognized do something
77 // else if char code is recognized do something
78 // else ignore
79 switch(scan) {
80 case HOMEKEY:
81 p = str;
82 break;
83 case ENDKEY:
84 p = last;
85 break;
86 case LTARROW:
87 if (p > str) p--;
88 break;
89 case CTRLLT:
90 if (p==str) break;
91 if (*p == ' ')
92 while ((p > str) && (*p == ' ')) p--;
93 else {
94 if (*(p-1) == ' ') {
95 p--;
96 while ((p > str) && (*p == ' ')) p--;
99 while ((p > str) && ((*p == ' ') || (*(p-1) != ' '))) p--;
100 break;
101 case RTARROW:
102 if (p < last) p++;
103 break;
104 case CTRLRT:
105 if (*p==0) break; // At end of string
106 if (*p != ' ')
107 while ((*p!=0) && (*p != ' ')) p++;
108 while ((*p!=0) && ((*p == ' ') && (*(p+1) != ' '))) p++;
109 if (*p==' ') p++;
110 break;
111 case DELETE:
112 q = p;
113 while (*(q+1)) {*q = *(q+1); q++; }
114 if (last > str) last--;
115 fudge = 1;
116 break;
117 case INSERT:
118 insmode = 1-insmode; // Switch mode
119 if (insmode == 0)
120 setcursorshape(1,7); // Block cursor
121 else setcursorshape(6,7); // Normal cursor
122 break;
124 default: // Unrecognized scan code, look at the ascii value
125 switch (c) {
126 case '\b': // Move over by one
127 q=p;
128 while ( q <= last ) { *(q-1)=*q; q++;}
129 if (last > str) last--;
130 if (p > str) p--;
131 fudge = 1;
132 break;
133 case '\x15': /* Ctrl-U: kill input */
134 fudge = last-str;
135 while ( p > str ) *p--=0;
136 p = str; *p=0; last = str;
137 break;
138 default: // Handle insert and overwrite mode
139 if ((c >= ' ') && (c < 128) &&
140 ((unsigned int)(p-str) < size-1) ) {
141 if (insmode == 0) { // Overwrite mode
142 if (p==last) last++;
143 *last = 0;
144 *p++ = c;
145 } else { // Insert mode
146 if (p==last) { // last char
147 last++;
148 *last=0;
149 *p++=c;
150 } else { // Non-last char
151 q=last++;
152 while (q >= p) { *q=*(q-1); q--;}
153 *p++=c;
157 else beep();
159 break;
161 // Now the string has been modified, print it
162 if (password == 0) {
163 gotoxy(row,col,page);
164 csprint(str,GETSTRATTR);
165 if (fudge > 0) cprint(' ',GETSTRATTR,fudge,page);
166 gotoxy(row,col+(p-str),page);
169 *p = '\0';
170 if (password == 0) csprint("\r\n",GETSTRATTR);
171 setcursorshape(start,end); // Block cursor
172 // If user hit ESCAPE so return without any changes
173 if (scan != ESCAPE) strcpy(stra,str);
174 free(str);
177 /* Print a C string (NUL-terminated) */
178 void cswprint(const char *str,char attr,char left)
180 char page = getdisppage();
181 char newattr=0,cha,chb;
182 char row,col;
183 char nr,nc;
185 nr = getnumrows();
186 nc = getnumcols();
187 getpos(&row,&col,page);
188 while ( *str ) {
189 switch (*str)
191 case '\b':
192 --col;
193 break;
194 case '\n':
195 ++row;
196 col = left;
197 break;
198 case '\r':
199 //col=left;
200 break;
201 case BELL: // Bell Char
202 beep();
203 break;
204 case CHRELATTR: // change attribute (relatively)
205 case CHABSATTR: // change attribute (absolute)
206 cha = *(str+1);
207 chb = *(str+2);
208 if ((((cha >= '0') && (cha <= '9')) ||
209 ((cha >= 'A') && (cha <= 'F'))) &&
210 (((chb >= '0') && (chb <= '9')) ||
211 ((chb >= 'A') && (chb <= 'F')))) // Next two chars are legal
213 if ((cha >= 'A') && (cha <= 'F'))
214 cha = cha - 'A'+10;
215 else cha = cha - '0';
216 if ((chb >= 'A') && (chb <= 'F'))
217 chb = chb - 'A'+10;
218 else chb = chb - '0';
219 newattr = (cha << 4) + chb;
220 attr = (*str == CHABSATTR ? newattr : attr ^ newattr);
221 str += 2; // Will be incremented again later
223 break;
224 default:
225 putch(*str, attr, page);
226 ++col;
228 if (col >= nc)
230 ++row;
231 col=left;
233 if (row > nr)
235 scrollup();
236 row= nr;
238 gotoxy(row,col,page);
239 str++;
243 void clearwindow(char top, char left, char bot, char right, char page, char fillchar, char fillattr)
245 char x;
246 for (x=top; x < bot+1; x++)
248 gotoxy(x,left,page);
249 cprint(fillchar,fillattr,right-left+1,page);
253 void cls(void)
255 unsigned char dp = getdisppage();
256 gotoxy(0,0,dp);
257 cprint(' ',GETSTRATTR,(1+getnumrows())*getnumcols(),dp);
260 //////////////////////////////Box Stuff
262 // This order of numbers must match
263 // the values of BOX_TOPLEFT,... in the header file
265 unsigned char SINSIN_CHARS[] = {218,192,191,217, //Corners
266 196,179, // Horiz and Vertical
267 195,180,194,193,197}; // Connectors & Middle
269 unsigned char DBLDBL_CHARS[] = {201,200,187,188, // Corners
270 205,186, // Horiz and Vertical
271 199,182,203,202,206}; // Connectors & Middle
273 unsigned char SINDBL_CHARS[] = {214,211,183,189, // Corners
274 196,186, // Horiz & Vert
275 199,182,210,208,215}; // Connectors & Middle
277 unsigned char DBLSIN_CHARS[] = {213,212,184,190, // Corners
278 205,179, // Horiz & Vert
279 198,181,209,207,216}; // Connectors & Middle
281 unsigned char * getboxchars(boxtype bt)
283 switch (bt)
285 case BOX_SINSIN:
286 return SINSIN_CHARS;
287 break;
288 case BOX_DBLDBL:
289 return DBLDBL_CHARS;
290 break;
291 case BOX_SINDBL:
292 return SINDBL_CHARS;
293 break;
294 case BOX_DBLSIN:
295 return DBLSIN_CHARS;
296 break;
297 default:
298 return SINSIN_CHARS;
299 break;
301 return SINSIN_CHARS;
304 // Draw box and lines
305 void drawbox(char top,char left,char bot, char right,
306 char page, char attr,boxtype bt)
308 unsigned char *box_chars; // pointer to array of box chars
309 unsigned char x;
311 box_chars = getboxchars(bt);
312 // Top border
313 gotoxy(top,left,page);
314 cprint(box_chars[BOX_TOPLEFT],attr,1,page);
315 gotoxy(top,left+1,page);
316 cprint(box_chars[BOX_TOP],attr,right-left,page);
317 gotoxy(top,right,page);
318 cprint(box_chars[BOX_TOPRIGHT],attr,1,page);
319 // Bottom border
320 gotoxy(bot,left,page);
321 cprint(box_chars[BOX_BOTLEFT],attr,1,page);
322 gotoxy(bot,left+1,page);
323 cprint(box_chars[BOX_BOT],attr,right-left,page);
324 gotoxy(bot,right,page);
325 cprint(box_chars[BOX_BOTRIGHT],attr,1,page);
326 // Left & right borders
327 for (x=top+1; x < bot; x++)
329 gotoxy(x,left,page);
330 cprint(box_chars[BOX_LEFT],attr,1,page);
331 gotoxy(x,right,page);
332 cprint(box_chars[BOX_RIGHT],attr,1,page);
336 void drawhorizline(char top, char left, char right, char page, char attr,
337 boxtype bt, char dumb)
339 unsigned char start,end;
340 unsigned char *box_chars = getboxchars(bt);
341 if (dumb==0) {
342 start = left+1;
343 end = right-1;
344 } else {
345 start = left;
346 end = right;
348 gotoxy(top,start,page);
349 cprint(box_chars[BOX_HORIZ],attr,end-start+1,page);
350 if (dumb == 0)
352 gotoxy(top,left,page);
353 cprint(box_chars[BOX_LTRT],attr,1,page);
354 gotoxy(top,right,page);
355 cprint(box_chars[BOX_RTLT],attr,1,page);