drivers/wifi: Remove unnecessary data structure copy
[coreboot2.git] / payloads / libpayload / curses / PDCurses / demos / tui.c
blob41f34ba41047699f1e80e032b95a63be8ebc14e2
1 /********************************* tui.c ************************************/
2 /*
3 * 'textual user interface'
5 * $Id: tui.c,v 1.34 2008/07/14 12:35:23 wmcbrine Exp $
7 * Author : P.J. Kunst <kunst@prl.philips.nl>
8 * Date : 25-02-93
9 */
11 #include <ctype.h>
12 #include <curses.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <time.h>
17 #include "tui.h"
19 void statusmsg(char *);
20 int waitforkey(void);
21 void rmerror(void);
23 #if defined(__unix) && !defined(__DJGPP__)
24 #include <unistd.h>
25 #endif
27 #ifdef A_COLOR
28 # define TITLECOLOR 1 /* color pair indices */
29 # define MAINMENUCOLOR (2 | A_BOLD)
30 # define MAINMENUREVCOLOR (3 | A_BOLD | A_REVERSE)
31 # define SUBMENUCOLOR (4 | A_BOLD)
32 # define SUBMENUREVCOLOR (5 | A_BOLD | A_REVERSE)
33 # define BODYCOLOR 6
34 # define STATUSCOLOR (7 | A_BOLD)
35 # define INPUTBOXCOLOR 8
36 # define EDITBOXCOLOR (9 | A_BOLD | A_REVERSE)
37 #else
38 # define TITLECOLOR 0 /* color pair indices */
39 # define MAINMENUCOLOR (A_BOLD)
40 # define MAINMENUREVCOLOR (A_BOLD | A_REVERSE)
41 # define SUBMENUCOLOR (A_BOLD)
42 # define SUBMENUREVCOLOR (A_BOLD | A_REVERSE)
43 # define BODYCOLOR 0
44 # define STATUSCOLOR (A_BOLD)
45 # define INPUTBOXCOLOR 0
46 # define EDITBOXCOLOR (A_BOLD | A_REVERSE)
47 #endif
49 #define th 1 /* title window height */
50 #define mh 1 /* main menu height */
51 #define sh 2 /* status window height */
52 #define bh (LINES - th - mh - sh) /* body window height */
53 #define bw COLS /* body window width */
55 /******************************* STATIC ************************************/
57 static WINDOW *wtitl, *wmain, *wbody, *wstat; /* title, menu, body, status win*/
58 static int nexty, nextx;
59 static int key = ERR, ch = ERR;
60 static bool quit = FALSE;
61 static bool incurses = FALSE;
63 #ifndef PDCURSES
64 static char wordchar(void)
66 return 0x17; /* ^W */
68 #endif
70 static char *padstr(char *s, int length)
72 static char buf[MAXSTRLEN];
73 char fmt[10];
75 sprintf(fmt, (int)strlen(s) > length ? "%%.%ds" : "%%-%ds", length);
76 sprintf(buf, fmt, s);
78 return buf;
81 static char *prepad(char *s, int length)
83 int i;
84 char *p = s;
86 if (length > 0)
88 memmove((void *)(s + length), (const void *)s, strlen(s) + 1);
90 for (i = 0; i < length; i++)
91 *p++ = ' ';
94 return s;
97 static void rmline(WINDOW *win, int nr) /* keeps box lines intact */
99 mvwaddstr(win, nr, 1, padstr(" ", bw - 2));
100 wrefresh(win);
103 static void initcolor(void)
105 #ifdef A_COLOR
106 if (has_colors())
107 start_color();
109 /* foreground, background */
111 init_pair(TITLECOLOR & ~A_ATTR, COLOR_BLACK, COLOR_CYAN);
112 init_pair(MAINMENUCOLOR & ~A_ATTR, COLOR_WHITE, COLOR_CYAN);
113 init_pair(MAINMENUREVCOLOR & ~A_ATTR, COLOR_WHITE, COLOR_BLACK);
114 init_pair(SUBMENUCOLOR & ~A_ATTR, COLOR_WHITE, COLOR_CYAN);
115 init_pair(SUBMENUREVCOLOR & ~A_ATTR, COLOR_WHITE, COLOR_BLACK);
116 init_pair(BODYCOLOR & ~A_ATTR, COLOR_WHITE, COLOR_BLUE);
117 init_pair(STATUSCOLOR & ~A_ATTR, COLOR_WHITE, COLOR_CYAN);
118 init_pair(INPUTBOXCOLOR & ~A_ATTR, COLOR_BLACK, COLOR_CYAN);
119 init_pair(EDITBOXCOLOR & ~A_ATTR, COLOR_WHITE, COLOR_BLACK);
120 #endif
123 static void setcolor(WINDOW *win, chtype color)
125 chtype attr = color & A_ATTR; /* extract Bold, Reverse, Blink bits */
127 #ifdef A_COLOR
128 attr &= ~A_REVERSE; /* ignore reverse, use colors instead! */
129 wattrset(win, COLOR_PAIR(color & A_CHARTEXT) | attr);
130 #else
131 attr &= ~A_BOLD; /* ignore bold, gives messy display on HP-UX */
132 wattrset(win, attr);
133 #endif
136 static void colorbox(WINDOW *win, chtype color, int hasbox)
138 int maxy;
139 #ifndef PDCURSES
140 int maxx;
141 #endif
142 chtype attr = color & A_ATTR; /* extract Bold, Reverse, Blink bits */
144 setcolor(win, color);
146 #ifdef A_COLOR
147 if (has_colors())
148 wbkgd(win, COLOR_PAIR(color & A_CHARTEXT) | (attr & ~A_REVERSE));
149 else
150 #endif
151 wbkgd(win, attr);
153 werase(win);
155 #ifdef PDCURSES
156 maxy = getmaxy(win);
157 #else
158 getmaxyx(win, maxy, maxx);
159 #endif
160 if (hasbox && (maxy > 2))
161 box(win, 0, 0);
163 touchwin(win);
164 wrefresh(win);
167 static void idle(void)
169 char buf[MAXSTRLEN];
170 time_t t;
171 struct tm *tp;
173 if (time (&t) == -1)
174 return; /* time not available */
176 tp = localtime(&t);
177 sprintf(buf, " %.2d-%.2d-%.4d %.2d:%.2d:%.2d",
178 tp->tm_mday, tp->tm_mon + 1, tp->tm_year + 1900,
179 tp->tm_hour, tp->tm_min, tp->tm_sec);
181 mvwaddstr(wtitl, 0, bw - strlen(buf) - 2, buf);
182 wrefresh(wtitl);
185 static void menudim(menu *mp, int *lines, int *columns)
187 int n, l, mmax = 0;
189 for (n=0; mp->func; n++, mp++)
190 if ((l = strlen(mp->name)) > mmax) mmax = l;
192 *lines = n;
193 *columns = mmax + 2;
196 static void setmenupos(int y, int x)
198 nexty = y;
199 nextx = x;
202 static void getmenupos(int *y, int *x)
204 *y = nexty;
205 *x = nextx;
208 static int hotkey(const char *s)
210 int c0 = *s; /* if no upper case found, return first char */
212 for (; *s; s++)
213 if (isupper((unsigned char)*s))
214 break;
216 return *s ? *s : c0;
219 static void repaintmenu(WINDOW *wmenu, menu *mp)
221 int i;
222 menu *p = mp;
224 for (i = 0; p->func; i++, p++)
225 mvwaddstr(wmenu, i + 1, 2, p->name);
227 touchwin(wmenu);
228 wrefresh(wmenu);
231 static void repaintmainmenu(int width, menu *mp)
233 int i;
234 menu *p = mp;
236 for (i = 0; p->func; i++, p++)
237 mvwaddstr(wmain, 0, i * width, prepad(padstr(p->name, width - 1), 1));
239 touchwin(wmain);
240 wrefresh(wmain);
243 static void mainhelp(void)
245 #ifdef ALT_X
246 statusmsg("Use arrow keys and Enter to select (Alt-X to quit)");
247 #else
248 statusmsg("Use arrow keys and Enter to select");
249 #endif
252 static void mainmenu(menu *mp)
254 int nitems, barlen, old = -1, cur = 0, c, cur0;
256 menudim(mp, &nitems, &barlen);
257 repaintmainmenu(barlen, mp);
259 while (!quit)
261 if (cur != old)
263 if (old != -1)
265 mvwaddstr(wmain, 0, old * barlen,
266 prepad(padstr(mp[old].name, barlen - 1), 1));
268 statusmsg(mp[cur].desc);
270 else
271 mainhelp();
273 setcolor(wmain, MAINMENUREVCOLOR);
275 mvwaddstr(wmain, 0, cur * barlen,
276 prepad(padstr(mp[cur].name, barlen - 1), 1));
278 setcolor(wmain, MAINMENUCOLOR);
279 old = cur;
280 wrefresh(wmain);
283 switch (c = (key != ERR ? key : waitforkey()))
285 case KEY_DOWN:
286 case '\n': /* menu item selected */
287 touchwin(wbody);
288 wrefresh(wbody);
289 rmerror();
290 setmenupos(th + mh, cur * barlen);
291 curs_set(1);
292 (mp[cur].func)(); /* perform function */
293 curs_set(0);
295 switch (key)
297 case KEY_LEFT:
298 cur = (cur + nitems - 1) % nitems;
299 key = '\n';
300 break;
302 case KEY_RIGHT:
303 cur = (cur + 1) % nitems;
304 key = '\n';
305 break;
307 default:
308 key = ERR;
311 repaintmainmenu(barlen, mp);
312 old = -1;
313 break;
315 case KEY_LEFT:
316 cur = (cur + nitems - 1) % nitems;
317 break;
319 case KEY_RIGHT:
320 cur = (cur + 1) % nitems;
321 break;
323 case KEY_ESC:
324 mainhelp();
325 break;
327 default:
328 cur0 = cur;
332 cur = (cur + 1) % nitems;
334 } while ((cur != cur0) && (hotkey(mp[cur].name) != toupper(c)));
336 if (hotkey(mp[cur].name) == toupper(c))
337 key = '\n';
342 rmerror();
343 touchwin(wbody);
344 wrefresh(wbody);
347 static void cleanup(void) /* cleanup curses settings */
349 if (incurses)
351 delwin(wtitl);
352 delwin(wmain);
353 delwin(wbody);
354 delwin(wstat);
355 curs_set(1);
356 endwin();
357 incurses = FALSE;
361 /******************************* EXTERNAL **********************************/
363 void clsbody(void)
365 werase(wbody);
366 wmove(wbody, 0, 0);
369 int bodylen(void)
371 #ifdef PDCURSES
372 return getmaxy(wbody);
373 #else
374 int maxy, maxx;
376 getmaxyx(wbody, maxy, maxx);
377 return maxy;
378 #endif
381 WINDOW *bodywin(void)
383 return wbody;
386 void rmerror(void)
388 rmline(wstat, 0);
391 void rmstatus(void)
393 rmline(wstat, 1);
396 void titlemsg(char *msg)
398 mvwaddstr(wtitl, 0, 2, padstr(msg, bw - 3));
399 wrefresh(wtitl);
402 void bodymsg(char *msg)
404 waddstr(wbody, msg);
405 wrefresh(wbody);
408 void errormsg(char *msg)
410 beep();
411 mvwaddstr(wstat, 0, 2, padstr(msg, bw - 3));
412 wrefresh(wstat);
415 void statusmsg(char *msg)
417 mvwaddstr(wstat, 1, 2, padstr(msg, bw - 3));
418 wrefresh(wstat);
421 bool keypressed(void)
423 ch = wgetch(wbody);
425 return ch != ERR;
428 int getkey(void)
430 int c = ch;
432 ch = ERR;
433 #ifdef ALT_X
434 quit = (c == ALT_X); /* PC only ! */
435 #endif
436 return c;
439 int waitforkey(void)
441 do idle(); while (!keypressed());
442 return getkey();
445 void DoExit(void) /* terminate program */
447 quit = TRUE;
450 void domenu(menu *mp)
452 int y, x, nitems, barlen, mheight, mw, old = -1, cur = 0, cur0;
453 bool stop = FALSE;
454 WINDOW *wmenu;
456 curs_set(0);
457 getmenupos(&y, &x);
458 menudim(mp, &nitems, &barlen);
459 mheight = nitems + 2;
460 mw = barlen + 2;
461 wmenu = newwin(mheight, mw, y, x);
462 colorbox(wmenu, SUBMENUCOLOR, 1);
463 repaintmenu(wmenu, mp);
465 key = ERR;
467 while (!stop && !quit)
469 if (cur != old)
471 if (old != -1)
472 mvwaddstr(wmenu, old + 1, 1,
473 prepad(padstr(mp[old].name, barlen - 1), 1));
475 setcolor(wmenu, SUBMENUREVCOLOR);
476 mvwaddstr(wmenu, cur + 1, 1,
477 prepad(padstr(mp[cur].name, barlen - 1), 1));
479 setcolor(wmenu, SUBMENUCOLOR);
480 statusmsg(mp[cur].desc);
482 old = cur;
483 wrefresh(wmenu);
486 switch (key = ((key != ERR) ? key : waitforkey()))
488 case '\n': /* menu item selected */
489 touchwin(wbody);
490 wrefresh(wbody);
491 setmenupos(y + 1, x + 1);
492 rmerror();
494 key = ERR;
495 curs_set(1);
496 (mp[cur].func)(); /* perform function */
497 curs_set(0);
499 repaintmenu(wmenu, mp);
501 old = -1;
502 break;
504 case KEY_UP:
505 cur = (cur + nitems - 1) % nitems;
506 key = ERR;
507 break;
509 case KEY_DOWN:
510 cur = (cur + 1) % nitems;
511 key = ERR;
512 break;
514 case KEY_ESC:
515 case KEY_LEFT:
516 case KEY_RIGHT:
517 if (key == KEY_ESC)
518 key = ERR; /* return to prev submenu */
520 stop = TRUE;
521 break;
523 default:
524 cur0 = cur;
528 cur = (cur + 1) % nitems;
530 } while ((cur != cur0) &&
531 (hotkey(mp[cur].name) != toupper((int)key)));
533 key = (hotkey(mp[cur].name) == toupper((int)key)) ? '\n' : ERR;
538 rmerror();
539 delwin(wmenu);
540 touchwin(wbody);
541 wrefresh(wbody);
544 void startmenu(menu *mp, char *mtitle)
546 initscr();
547 incurses = TRUE;
548 initcolor();
550 wtitl = subwin(stdscr, th, bw, 0, 0);
551 wmain = subwin(stdscr, mh, bw, th, 0);
552 wbody = subwin(stdscr, bh, bw, th + mh, 0);
553 wstat = subwin(stdscr, sh, bw, th + mh + bh, 0);
555 colorbox(wtitl, TITLECOLOR, 0);
556 colorbox(wmain, MAINMENUCOLOR, 0);
557 colorbox(wbody, BODYCOLOR, 0);
558 colorbox(wstat, STATUSCOLOR, 0);
560 if (mtitle)
561 titlemsg(mtitle);
563 cbreak(); /* direct input (no newline required)... */
564 noecho(); /* ... without echoing */
565 curs_set(0); /* hide cursor (if possible) */
566 nodelay(wbody, TRUE); /* don't wait for input... */
567 halfdelay(10); /* ...well, no more than a second, anyway */
568 keypad(wbody, TRUE); /* enable cursor keys */
569 scrollok(wbody, TRUE); /* enable scrolling in main window */
571 leaveok(stdscr, TRUE);
572 leaveok(wtitl, TRUE);
573 leaveok(wmain, TRUE);
574 leaveok(wstat, TRUE);
576 mainmenu(mp);
578 cleanup();
581 static void repainteditbox(WINDOW *win, int x, char *buf)
583 #ifndef PDCURSES
584 int maxy;
585 #endif
586 int maxx;
588 #ifdef PDCURSES
589 maxx = getmaxx(win);
590 #else
591 getmaxyx(win, maxy, maxx);
592 #endif
593 werase(win);
594 mvwprintw(win, 0, 0, "%s", padstr(buf, maxx));
595 wmove(win, 0, x);
596 wrefresh(win);
601 weditstr() - edit string
603 Description:
604 The initial value of 'str' with a maximum length of 'field' - 1,
605 which is supplied by the calling routine, is editted. The user's
606 erase (^H), kill (^U) and delete word (^W) chars are interpreted.
607 The PC insert or Tab keys toggle between insert and edit mode.
608 Escape aborts the edit session, leaving 'str' unchanged.
609 Enter, Up or Down Arrow are used to accept the changes to 'str'.
610 NOTE: editstr(), mveditstr(), and mvweditstr() are macros.
612 Return Value:
613 Returns the input terminating character on success (Escape,
614 Enter, Up or Down Arrow) and ERR on error.
616 Errors:
617 It is an error to call this function with a NULL window pointer.
618 The length of the initial 'str' must not exceed 'field' - 1.
622 int weditstr(WINDOW *win, char *buf, int field)
624 char org[MAXSTRLEN], *tp, *bp = buf;
625 bool defdisp = TRUE, stop = FALSE, insert = FALSE;
626 int cury, curx, begy, begx, oldattr;
627 WINDOW *wedit;
628 int c = 0;
630 if ((field >= MAXSTRLEN) || (buf == NULL) ||
631 ((int)strlen(buf) > field - 1))
632 return ERR;
634 strcpy(org, buf); /* save original */
636 wrefresh(win);
637 getyx(win, cury, curx);
638 getbegyx(win, begy, begx);
640 wedit = subwin(win, 1, field, begy + cury, begx + curx);
641 oldattr = wedit->_attrs;
642 colorbox(wedit, EDITBOXCOLOR, 0);
644 keypad(wedit, TRUE);
645 curs_set(1);
647 while (!stop)
649 idle();
650 repainteditbox(wedit, bp - buf, buf);
652 switch (c = wgetch(wedit))
654 case ERR:
655 break;
657 case KEY_ESC:
658 strcpy(buf, org); /* restore original */
659 stop = TRUE;
660 break;
662 case '\n':
663 case KEY_UP:
664 case KEY_DOWN:
665 stop = TRUE;
666 break;
668 case KEY_LEFT:
669 if (bp > buf)
670 bp--;
671 break;
673 case KEY_RIGHT:
674 defdisp = FALSE;
675 if (bp - buf < (int)strlen(buf))
676 bp++;
677 break;
679 case '\t': /* TAB -- because insert
680 is broken on HPUX */
681 case KEY_IC: /* enter insert mode */
682 case KEY_EIC: /* exit insert mode */
683 defdisp = FALSE;
684 insert = !insert;
686 curs_set(insert ? 2 : 1);
687 break;
689 default:
690 if (c == erasechar()) /* backspace, ^H */
692 if (bp > buf)
694 memmove((void *)(bp - 1), (const void *)bp, strlen(bp) + 1);
695 bp--;
698 else if (c == killchar()) /* ^U */
700 bp = buf;
701 *bp = '\0';
703 else if (c == wordchar()) /* ^W */
705 tp = bp;
707 while ((bp > buf) && (*(bp - 1) == ' '))
708 bp--;
709 while ((bp > buf) && (*(bp - 1) != ' '))
710 bp--;
712 memmove((void *)bp, (const void *)tp, strlen(tp) + 1);
714 else if (isprint(c))
716 if (defdisp)
718 bp = buf;
719 *bp = '\0';
720 defdisp = FALSE;
723 if (insert)
725 if ((int)strlen(buf) < field - 1)
727 memmove((void *)(bp + 1), (const void *)bp,
728 strlen(bp) + 1);
730 *bp++ = c;
733 else if (bp - buf < field - 1)
735 /* append new string terminator */
737 if (!*bp)
738 bp[1] = '\0';
740 *bp++ = c;
746 curs_set(0);
748 wattrset(wedit, oldattr);
749 repainteditbox(wedit, bp - buf, buf);
750 delwin(wedit);
752 return c;
755 WINDOW *winputbox(WINDOW *win, int nlines, int ncols)
757 WINDOW *winp;
758 int cury, curx, begy, begx;
760 getyx(win, cury, curx);
761 getbegyx(win, begy, begx);
763 winp = newwin(nlines, ncols, begy + cury, begx + curx);
764 colorbox(winp, INPUTBOXCOLOR, 1);
766 return winp;
769 int getstrings(char *desc[], char *buf[], int field)
771 WINDOW *winput;
772 int oldy, oldx, maxy, maxx, nlines, ncols, i, n, l, mmax = 0;
773 int c = 0;
774 bool stop = FALSE;
776 for (n = 0; desc[n]; n++)
777 if ((l = strlen(desc[n])) > mmax)
778 mmax = l;
780 nlines = n + 2; ncols = mmax + field + 4;
781 getyx(wbody, oldy, oldx);
782 getmaxyx(wbody, maxy, maxx);
784 winput = mvwinputbox(wbody, (maxy - nlines) / 2, (maxx - ncols) / 2,
785 nlines, ncols);
787 for (i = 0; i < n; i++)
788 mvwprintw(winput, i + 1, 2, "%s", desc[i]);
790 i = 0;
792 while (!stop)
794 switch (c = mvweditstr(winput, i+1, mmax+3, buf[i], field))
796 case KEY_ESC:
797 stop = TRUE;
798 break;
800 case KEY_UP:
801 i = (i + n - 1) % n;
802 break;
804 case '\n':
805 case '\t':
806 case KEY_DOWN:
807 if (++i == n)
808 stop = TRUE; /* all passed? */
812 delwin(winput);
813 touchwin(wbody);
814 wmove(wbody, oldy, oldx);
815 wrefresh(wbody);
817 return c;