|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * ncurses frontend for a text-based user interface.
5: *
6: * Copyright 1996 Bernd Schmidt
7: * If you find the routines in this file useful, you may use them in your
8: * programs without restrictions. Essentially, it's in the public domain.
9: *
10: */
11:
12:
13: #include "sysconfig.h"
14: #include "sysdeps.h"
15:
1.1.1.2 ! root 16: #ifdef HAVE_NCURSES_H
1.1 root 17: #include <ncurses.h>
1.1.1.2 ! root 18: #else
! 19: #include <curses.h>
! 20: #endif
! 21: #include <ctype.h>
1.1 root 22:
23: #include "config.h"
24: #include "options.h"
1.1.1.2 ! root 25: #include "uae.h"
1.1 root 26: #include "tui.h"
27:
28: static WINDOW *currwin;
29:
30: static WINDOW *winstack[10]; /* more than enough */
31: static int winnr = 0;
32:
33: void tui_setup(void)
34: {
35: int i;
36:
37: for (i = 0; i < 10; i++)
38: winstack[i] = NULL;
39: /* From the ncurses manpage... */
40: initscr(); start_color(); cbreak(); noecho(); nonl(); intrflush(stdscr, FALSE); keypad(stdscr, TRUE);
41: currwin = stdscr;
42: if (has_colors()) {
43: init_pair(1, COLOR_WHITE, COLOR_BLUE);
44: init_pair(2, COLOR_BLACK, COLOR_WHITE);
45: wattron(currwin, COLOR_PAIR(1) | A_BOLD);
46: wbkgd(currwin, ' '|COLOR_PAIR(1));
47: }
48:
49: winstack[0] = stdscr;
50: winnr = 1;
51: }
52:
53: int tui_lines(void)
54: {
55: return LINES;
56: }
57:
58: int tui_cols(void)
59: {
60: return COLS;
61: }
62:
63: void tui_shutdown(void)
64: {
65: endwin();
66: }
67:
68: void tui_refresh(void)
69: {
1.1.1.2 ! root 70: int w;
! 71: for (w = 0; w < winnr; w++) {
! 72: touchwin(winstack[w]);
! 73: wnoutrefresh(winstack[w]);
! 74: }
! 75: doupdate();
1.1 root 76: }
77:
78: void tui_puts(const char *s)
79: {
80: waddstr(currwin, s);
81: }
82:
83: void tui_cursoff(void)
84: {
85: }
86:
87: void tui_curson(void)
88: {
89: }
90:
91: void tui_putc(char c)
92: {
93: waddch(currwin, c);
94: }
95:
96: void tui_cr(void)
97: {
98: waddch(currwin, '\r');
99: }
100:
101: char tui_getc(void)
102: {
103: return getch();
104: }
105:
106: void tui_gotoxy(int x, int y)
107: {
108: x--; y--;
109: wmove(currwin, y, x);
110: }
111:
112: void tui_selwin(int w)
113: {
114: currwin = winstack[w];
115: }
116:
117: void tui_clrwin(int w)
118: {
1.1.1.2 ! root 119: werase(winstack[w]);
1.1 root 120: }
121:
122: void tui_drawbox(int w)
123: {
124: wborder(winstack[w], 0, 0, 0, 0, 0, 0, 0, 0);
125: }
126:
127: void tui_hline(int x1, int y1, int x2)
128: {
129: wmove(currwin, y1-1, x1-1);
130: whline(currwin, 0, x2-x1+1);
131: }
132:
133: int tui_dlog(int x1, int y1, int x2, int y2)
134: {
135: x1--; y1--;
136: winstack[winnr] = newwin(y2 - y1, x2 - x1, y1, x1);
137: return winnr++;
138: }
139:
140: void tui_dlogdie(int w)
141: {
142: if (currwin == winstack[w])
143: currwin = stdscr;
144: delwin(winstack[w]);
145: winstack[w] = NULL;
146: while (winstack[winnr-1] == NULL)
147: winnr--;
148:
149: for (w = 0; w < winnr; w++)
150: redrawwin(winstack[w]), wrefresh(winstack[w]);
151: }
152:
153: int tui_gets(char *buf, int x, int y, int n)
154: {
155: int i = 0;
156: for (;;) {
1.1.1.2 ! root 157: int c, j;
! 158:
! 159: buf[i] = 0;
1.1 root 160: wmove(currwin, y, x);
161: for (j = 0; j < i; j++)
162: waddch(currwin, buf[j]);
163: for (; j < n; j++)
164: waddch(currwin, ' ');
1.1.1.2 ! root 165:
1.1 root 166: wmove(currwin, y, x + i);
167: wrefresh(currwin);
1.1.1.2 ! root 168:
! 169: c = getch();
! 170:
! 171: wmove(currwin, y, x + i);
1.1 root 172: if (c == 13)
173: return 1;
174: else if (c == 27)
175: return 0;
1.1.1.2 ! root 176: else if (i > 0 && c == KEY_BACKSPACE)
! 177: i--;
! 178: else if (i + 1 < n && !iscntrl(c))
1.1 root 179: buf[i++] = c;
180: }
181: }
182:
183: int tui_wgets(char *buf, const char *title, int n)
184: {
185: int l = strlen(title);
1.1.1.2 ! root 186: int ww = (l > n ? l : n) + 2;
! 187: int w = tui_dlog((tui_cols()-ww)/2, tui_lines()/2-1, (tui_cols()+ww)/2, tui_lines()/2+1);
! 188: int result;
! 189:
1.1 root 190: tui_selwin(w); tui_drawbox(w);
191: wmove(currwin, 0, (ww-l)/2);
192: waddstr(currwin, title);
1.1.1.2 ! root 193: result = tui_gets(buf, 1, 1, n);
! 194: tui_dlogdie(w);
! 195: return result;
! 196: }
! 197:
! 198: int tui_menubrowse(struct bstring *menu, int xoff, int yoff, int selected)
! 199: {
! 200: int count = 0, maxsel = 0, maxw = 0;
! 201: int i, j, w;
! 202:
! 203: const char *mtitle = NULL;
! 204:
! 205: for (i = 0; menu[i].val != -3; i++) {
! 206: int tmp;
! 207: if (menu[i].val != 0) {
! 208: count++;
! 209: if (menu[i].val != -2)
! 210: maxsel++;
! 211: } else
! 212: mtitle = menu[i].data;
! 213: if ((tmp = strlen(menu[i].data)) > maxw)
! 214: maxw = tmp;
! 215: }
! 216: maxw += 3;
! 217: w = tui_dlog(xoff, yoff, xoff+maxw, yoff+count+1);
! 218: tui_selwin(w);
! 219: tui_drawbox(w);
! 220: if (mtitle != NULL) {
! 221: wmove(currwin, 0, 1);
! 222: waddstr(currwin, mtitle);
! 223: }
! 224:
! 225: for (;;) {
! 226: int c;
! 227: int s2;
! 228:
! 229: for (i = j = s2 = 0; i < count; i++, j++) {
! 230: int k, x;
! 231: attr_t a = s2 == selected ? A_STANDOUT : 0;
! 232:
! 233: while (menu[j].val == 0)
! 234: j++;
! 235: wmove(currwin, 1+i, 1);
! 236: waddch(currwin, ' ' | a);
! 237: for (k = x = 0; menu[j].data[k]; k++, x++) {
! 238: int a2 = 0;
! 239: c = menu[j].data[k];
! 240: if (c == '_')
! 241: c = menu[j].data[++k], a2 = A_UNDERLINE;
! 242: wmove(currwin, 1+i, 2+x);
! 243: waddch(currwin, c | a | a2);
! 244: }
! 245: for (; x < maxw-2; x++) {
! 246: wmove(currwin, 1+i, 2+x);
! 247: waddch(currwin, ' ' | a);
! 248: }
! 249: if (menu[j].val != -1)
! 250: s2++;
! 251: }
! 252:
! 253: tui_refresh();
! 254: c = getch();
! 255: if (c == 27) {
! 256: tui_dlogdie(w);
! 257: return -1;
! 258: } else if (c == KEY_ENTER || c == 13 || c == ' ') {
! 259: tui_dlogdie(w);
! 260: return selected;
! 261: } else switch (c) {
! 262: case KEY_UP:
! 263: if (selected > 0)
! 264: selected--;
! 265: break;
! 266: case KEY_DOWN:
! 267: if (selected + 1 < count)
! 268: selected++;
! 269: break;
! 270: case KEY_PPAGE:
! 271: selected = 0;
! 272: break;
! 273: case KEY_NPAGE:
! 274: selected = count - 1;
! 275: break;
! 276: default:
! 277: for (j = i = 0; menu[i].val != -3; i++)
! 278: if (menu[i].val == toupper(c)) {
! 279: tui_dlogdie(w);
! 280: return j;
! 281: } else if (menu[i].val == -1 || menu[i].val > 0) {
! 282: j++;
! 283: }
! 284:
! 285: break;
! 286: }
! 287: }
! 288: return -1; /* Can't get here */
1.1 root 289: }
290:
1.1.1.2 ! root 291: void tui_errorbox(const char *err)
! 292: {
! 293: const char *hak = "Hit any key";
! 294: int n = strlen(hak);
! 295: int l = strlen(err);
! 296: int ww = (l > n ? l : n) + 2;
! 297: int w = tui_dlog((tui_cols()-ww)/2, tui_lines()/2-1, (tui_cols()+ww)/2, tui_lines()/2+1);
! 298: tui_selwin(w); tui_drawbox(w);
! 299:
! 300: wmove(currwin, 0, (ww-6)/2);
! 301: waddstr(currwin, "Error!");
! 302: wmove(currwin, 1, (ww-l)/2);
! 303: waddstr(currwin, err);
! 304: wmove(currwin, 2, (ww-n)/2);
! 305: waddstr(currwin, hak);
! 306:
! 307: wrefresh(currwin);
! 308: for (;;) {
! 309: int c = getch();
! 310: if (c == 13)
! 311: break;
! 312: }
! 313: tui_dlogdie(w);
! 314: }
1.1 root 315:
316: static char *pattern;
317: static int maxlen;
318:
319: static void put_filename(char *s, int x, int y, attr_t a)
320: {
321: char buf[256];
322: int i;
323:
324: tui_gotoxy(x,y);
325: if (strcmp(s, ".") == 0)
326: strcpy(buf, "(none)");
327: else
328: strcpy(buf, s);
329: buf[maxlen] = 0;
330: for (i = 0; i < strlen(buf); i++)
331: waddch(currwin, buf[i] | a);
332: for (; i < maxlen; i++)
333: waddch(currwin, ' ' | a);
334: }
335:
336: static char fsbuf[256];
337:
338: static int selectfn(const struct dirent *de)
339: {
340: int l1, l2;
341:
342: /* l1 = strlen(pattern + 1);*/
343: l2 = strlen(de->d_name);
344:
345: if (l2 >= tui_cols()-10) /* Restrict length of filenames so we won't mess up the display */
346: return 0;
347:
348: /* No pattern matching for now. But we don't show hidden files. */
349: if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0
350: && de->d_name[0] == '.')
351: return 0;
352: if (l2 > maxlen)
353: maxlen = l2;
354: return 1;
355: }
356:
357: char *tui_filereq(char *s, char *oldfile)
358: {
359: char cwd[256];
360: char *retval = fsbuf;
361: char *tmp;
362: int fin = 0;
363:
364: /* Save wd */
365: if (getcwd(cwd, 256) == NULL)
366: return NULL;
367:
368: /* Change into directory of old file */
369: strcpy(fsbuf, oldfile);
370: tmp = strrchr(fsbuf, '/');
371: if (tmp != NULL) {
372: *tmp = 0;
373: if (strlen(fsbuf) > 0)
374: chdir(fsbuf);
375: }
376:
377: pattern = s;
378: if (s[0] != '*')
379: fprintf(stderr, "Can't handle wildcard %s\n", s);
380: if (s[1] != 0 && strchr(s+1, '*') != NULL)
381: fprintf(stderr, "Can't handle wildcard %s\n", s);
382: for (;!fin;) {
383: struct dirent **names;
384: int i, w, n, l, yp, oldyp, s;
385:
386: maxlen = 0;
387: n = scandir(".", &names, selectfn, alphasort);
388:
389: if (n <= 0)
390: return NULL;
391: l = n;
392: if (l > 15)
393: l = 15;
394: yp = s = 0; oldyp = -1;
395: w = tui_dlog(5, 5, 5 + maxlen + 3, 5 + l + 1);
396: tui_selwin(w); tui_drawbox(w);
397: for (;;) {
398: int c;
399: char tmp[256];
400: while (s < yp)
401: yp--;
402: while (s >= yp + l)
403: yp++;
404: if (oldyp != yp) {
405: oldyp = yp;
406: for (i = 0; i < l; i++) {
407: put_filename(names[i + yp]->d_name, 3, 2 + i, 0);
408: }
409: }
410: put_filename(names[s]->d_name, 3, 2 + s - yp, A_STANDOUT);
411: tui_refresh();
412: c = getch();
413: put_filename(names[s]->d_name, 3, 2 + s - yp, 0);
414: if (c == 27) {
415: retval = NULL; fin = 1;
416: break;
417: } else if (c == KEY_ENTER || c == 13 || c == ' ') {
418: int err;
419:
420: if (strcmp(names[s]->d_name, ".") == 0) {
421: fin = 1;
422: strcpy(fsbuf, "");
423: break;
424: }
425: err = chdir(names[s]->d_name);
426:
427: if (err == 0)
428: break;
429: else if (errno == ENOTDIR) {
430: fin = 1;
431: if (getcwd(fsbuf, 256) == NULL)
432: retval = NULL;
433: if (strlen(fsbuf) + strlen(names[s]->d_name) + 2 >= 256)
434: retval = NULL;
435: else {
436: strcat(fsbuf, "/");
437: strcat(fsbuf, names[s]->d_name);
438: }
439: break;
440: } /* else what? */
441: }
442: switch (c) {
443: case KEY_UP:
444: if (s > 0)
445: s--;
446: break;
447: case KEY_DOWN:
448: if (s + 1 < n)
449: s++;
450: break;
451: case KEY_PPAGE:
452: if (s > l)
453: s -= l;
454: else
455: s = 0;
456: break;
457: case KEY_NPAGE:
458: if (s + l < n)
459: s += l;
460: else
461: s = n - 1;
462: break;
463: default:
464: for (i = 0; i < n; i++)
465: if (names[i]->d_name[0] == c) {
466: s = i;
467: break;
468: }
469: }
470: }
471: #if 0
472: /* @@@ is this right? */
473: for (i = 0; i < n; i++)
474: free(names[i]->d_name);
475: free(names);
476: #endif
477: tui_dlogdie(w);
478: }
479: chdir(cwd);
480: return retval;
481: }
482:
483: int tui_backup_optionsfile(void)
484: {
485: char tmp[257];
486: strcpy(tmp, optionsfile);
487: strcat(tmp, "~");
488: return rename(optionsfile, tmp);
489: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.