--- uae/src/svgancui.c 2018/04/24 16:38:39 1.1 +++ uae/src/svgancui.c 2018/04/24 16:42:08 1.1.1.4 @@ -13,12 +13,22 @@ #include "sysconfig.h" #include "sysdeps.h" +#ifdef HAVE_NCURSES_H #include +#else +#include +#endif +#include #include "config.h" #include "options.h" +#include "uae.h" #include "tui.h" +#ifdef DONT_HAVE_ATTR_T +typedef int attr_t; +#endif + static WINDOW *currwin; static WINDOW *winstack[10]; /* more than enough */ @@ -27,187 +37,371 @@ static int winnr = 0; void tui_setup(void) { int i; - + for (i = 0; i < 10; i++) winstack[i] = NULL; /* From the ncurses manpage... */ - initscr(); start_color(); cbreak(); noecho(); nonl(); intrflush(stdscr, FALSE); keypad(stdscr, TRUE); + initscr (); start_color (); cbreak(); noecho(); nonl (); intrflush (stdscr, FALSE); keypad (stdscr, TRUE); currwin = stdscr; - if (has_colors()) { - init_pair(1, COLOR_WHITE, COLOR_BLUE); - init_pair(2, COLOR_BLACK, COLOR_WHITE); - wattron(currwin, COLOR_PAIR(1) | A_BOLD); - wbkgd(currwin, ' '|COLOR_PAIR(1)); + if (has_colors ()) { + init_pair (1, COLOR_WHITE, COLOR_BLUE); + init_pair (2, COLOR_BLACK, COLOR_WHITE); + wattron (currwin, COLOR_PAIR (1) | A_BOLD); + wbkgd (currwin, ' ' | COLOR_PAIR (1)); } - + winstack[0] = stdscr; winnr = 1; } -int tui_lines(void) +int tui_lines (void) { return LINES; } -int tui_cols(void) +int tui_cols (void) { return COLS; } -void tui_shutdown(void) +void tui_shutdown (void) { - endwin(); + endwin (); } -void tui_refresh(void) +void tui_refresh (void) { - wrefresh(currwin); + int w; + for (w = 0; w < winnr; w++) { + touchwin (winstack[w]); + wnoutrefresh (winstack[w]); + } + doupdate (); } -void tui_puts(const char *s) +void tui_puts (const char *s) { - waddstr(currwin, s); + waddstr (currwin, s); } void tui_cursoff(void) { } -void tui_curson(void) +void tui_curson (void) { } void tui_putc(char c) { - waddch(currwin, c); + waddch (currwin, c); } -void tui_cr(void) +void tui_cr (void) { - waddch(currwin, '\r'); + waddch (currwin, '\r'); } char tui_getc(void) { - return getch(); + return getch (); } -void tui_gotoxy(int x, int y) +void tui_gotoxy (int x, int y) { x--; y--; - wmove(currwin, y, x); + wmove (currwin, y, x); } -void tui_selwin(int w) +void tui_selwin (int w) { currwin = winstack[w]; } -void tui_clrwin(int w) +void tui_clrwin (int w) { - wclear(winstack[w]); + werase (winstack[w]); } void tui_drawbox(int w) { - wborder(winstack[w], 0, 0, 0, 0, 0, 0, 0, 0); + wborder (winstack[w], 0, 0, 0, 0, 0, 0, 0, 0); } -void tui_hline(int x1, int y1, int x2) +void tui_hline (int x1, int y1, int x2) { - wmove(currwin, y1-1, x1-1); - whline(currwin, 0, x2-x1+1); + wmove (currwin, y1-1, x1-1); + whline (currwin, 0, x2-x1+1); } int tui_dlog(int x1, int y1, int x2, int y2) { x1--; y1--; - winstack[winnr] = newwin(y2 - y1, x2 - x1, y1, x1); + winstack[winnr] = newwin (y2 - y1, x2 - x1, y1, x1); return winnr++; } -void tui_dlogdie(int w) +void tui_dlogdie (int w) { if (currwin == winstack[w]) currwin = stdscr; - delwin(winstack[w]); + delwin (winstack[w]); winstack[w] = NULL; while (winstack[winnr-1] == NULL) winnr--; - + for (w = 0; w < winnr; w++) - redrawwin(winstack[w]), wrefresh(winstack[w]); + redrawwin (winstack[w]), wrefresh (winstack[w]); } -int tui_gets(char *buf, int x, int y, int n) +int tui_gets (char *buf, int x, int y, int n) { int i = 0; for (;;) { - int c = getch(); - int j; - wmove(currwin, y, x); + int c, j; + + buf[i] = 0; + wmove (currwin, y, x); for (j = 0; j < i; j++) - waddch(currwin, buf[j]); + waddch (currwin, buf[j]); for (; j < n; j++) - waddch(currwin, ' '); - wmove(currwin, y, x + i); - wrefresh(currwin); - buf[i] = 0; + waddch (currwin, ' '); + + wmove (currwin, y, x + i); + wrefresh (currwin); + + c = getch (); + + wmove (currwin, y, x + i); if (c == 13) return 1; else if (c == 27) return 0; - else if (i + 1 < n) + else if (i > 0 && c == KEY_BACKSPACE) + i--; + else if (i + 1 < n && !iscntrl (c)) buf[i++] = c; } } -int tui_wgets(char *buf, const char *title, int n) +int tui_wgets (char *buf, const char *title, int n) { - int l = strlen(title); - int ww = l > n ? l : n; - int w = tui_dlog((tui_cols()-ww-2)/2, tui_lines()/2-1, (tui_cols()+ww+2)/2, tui_lines()/2+1); - tui_selwin(w); tui_drawbox(w); - wmove(currwin, 0, (ww-l)/2); - waddstr(currwin, title); - return tui_gets(buf, 1, 1, n); + int l = strlen (title); + int ww = (l > n ? l : n) + 2; + int w = tui_dlog((tui_cols ()-ww)/2, tui_lines ()/2-1, (tui_cols ()+ww)/2, tui_lines ()/2+1); + int result; + + tui_selwin (w); tui_drawbox(w); + wmove (currwin, 0, (ww-l)/2); + waddstr (currwin, title); + result = tui_gets (buf, 1, 1, n); + tui_dlogdie (w); + return result; +} + +int tui_menubrowse (struct bstring *menu, int xoff, int yoff, int selected, int height) +{ + int count = 0, maxsel = 0, maxw = 0; + int i, j, w, s, yp, oldyp; + chtype moresave[6][2]; + int xpos, ypos; + + const char *mtitle = NULL; + + for (i = 0; menu[i].val != -3; i++) { + int tmp; + if (menu[i].val == -4) { + if (maxsel < selected) + selected--; + continue; + } + if (menu[i].val != 0) { + count++; + if (menu[i].val != -2) + maxsel++; + } else + mtitle = menu[i].data; + if ((tmp = strlen (menu[i].data)) > maxw) + maxw = tmp; + } + if (height > count) + height = count; + maxw += 3; + if (strlen (mtitle ? mtitle : "") + 8 > maxw) + maxw = strlen (mtitle ? mtitle : "") + 8; + if (xoff > 0) + xpos = xoff; + else + xpos = tui_cols () + xoff - maxw - 1; + if (yoff > 0) + ypos = yoff; + else + ypos = tui_lines () + yoff - height - 2; + w = tui_dlog(xpos, ypos, xpos+maxw, ypos+height+1); + tui_selwin (w); + tui_drawbox(w); + if (mtitle != NULL) { + mvwaddstr (currwin, 0, 1, mtitle); + } + for (i = 0; i < 6; i++) { + moresave[i][0] = mvwinch (currwin, 0, maxw-6+i); + moresave[i][1] = mvwinch (currwin, height+1, maxw-6+i); + } + s = yp = 0; oldyp = -1; + for (;;) { + int c; + int s2; + + while (selected < yp) + yp--; + while (selected >= yp + height) + yp++; + if (yp == 0) + for (i = 0; i < 6; i++) + mvwaddch (currwin, 0, maxw-6+i, moresave[i][0]); + else + mvwaddstr (currwin, 0, maxw-6, "(more)"); + if (yp + height == count) + for (i = 0; i < 6; i++) + mvwaddch (currwin, height+1, maxw-6+i, moresave[i][1]); + else + mvwaddstr (currwin, height+1, maxw-6, "(more)"); + for (i = s2 = j = 0; i < count; i++, j++) { + int k, x; + attr_t a = s2 == selected ? A_STANDOUT : 0; + while (menu[j].val == 0 || menu[j].val == -4) + j++; + if (i >= yp && i < yp+height) { + mvwaddch (currwin, 1+i-yp, 1, ' ' | a); + for (k = x = 0; menu[j].data[k]; k++, x++) { + int a2 = 0; + c = menu[j].data[k]; + if (c == '_') + c = menu[j].data[++k], a2 = A_UNDERLINE; + mvwaddch (currwin, 1+i-yp, 2+x, c | a | a2); + } + for (; x < maxw-2; x++) { + mvwaddch (currwin, 1+i-yp, 2+x, ' ' | a); + } + } + if (menu[j].val != -2) + s2++; + } + + tui_refresh (); + c = getch (); + if (c == 27) { + tui_dlogdie (w); + return -1; + } else if (c == KEY_ENTER || c == 13 || c == ' ') { + tui_dlogdie (w); + for (i = s2 = j = 0; s2 <= selected; j++) { + if (menu[j].val == -4) { + i++; j++; continue; + } + while (menu[j].val == 0) + j++; + if (s2 == selected) + return i; + if (menu[j].val != -2) + s2++, i++; + } + abort(); + } else switch (c) { + case KEY_UP: + if (selected > 0) + selected--; + break; + case KEY_DOWN: + if (selected + 1 < count) + selected++; + break; + case KEY_PPAGE: + if (selected > height) + selected -= height; + else + selected = 0; + break; + case KEY_NPAGE: + if (selected + height < count) + selected += height; + else + selected = count-1; + break; + default: + for (j = i = 0; menu[i].val != -3; i++) + if (menu[i].val == toupper (c)) { + tui_dlogdie (w); + return j; + } else if (menu[i].val == -1 || menu[i].val == -4 || menu[i].val > 0) { + j++; + } + + break; + } + } + return -1; /* Can't get here */ } +void tui_errorbox(const char *err) +{ + const char *hak = "Hit any key"; + int n = strlen (hak); + int l = strlen (err); + int ww = (l > n ? l : n) + 2; + int w = tui_dlog((tui_cols ()-ww)/2, tui_lines ()/2-1, (tui_cols ()+ww)/2, tui_lines ()/2+1); + tui_selwin (w); tui_drawbox(w); + + wmove (currwin, 0, (ww-6)/2); + waddstr (currwin, "Error!"); + wmove (currwin, 1, (ww-l)/2); + waddstr (currwin, err); + wmove (currwin, 2, (ww-n)/2); + waddstr (currwin, hak); + + wrefresh (currwin); + for (;;) { + int c = getch (); + if (c == 13) + break; + } + tui_dlogdie (w); +} static char *pattern; static int maxlen; -static void put_filename(char *s, int x, int y, attr_t a) +static void put_filename (char *s, int x, int y, attr_t a) { char buf[256]; int i; - tui_gotoxy(x,y); - if (strcmp(s, ".") == 0) - strcpy(buf, "(none)"); + tui_gotoxy (x,y); + if (strcmp (s, ".") == 0) + strcpy (buf, "(none)"); else - strcpy(buf, s); + strcpy (buf, s); buf[maxlen] = 0; - for (i = 0; i < strlen(buf); i++) - waddch(currwin, buf[i] | a); + for (i = 0; i < strlen (buf); i++) + waddch (currwin, buf[i] | a); for (; i < maxlen; i++) - waddch(currwin, ' ' | a); + waddch (currwin, ' ' | a); } static char fsbuf[256]; -static int selectfn(const struct dirent *de) +static int selectfn (const struct dirent *de) { int l1, l2; -/* l1 = strlen(pattern + 1);*/ - l2 = strlen(de->d_name); +/* l1 = strlen (pattern + 1);*/ + l2 = strlen (de->d_name); - if (l2 >= tui_cols()-10) /* Restrict length of filenames so we won't mess up the display */ + if (l2 >= tui_cols ()-10) /* Restrict length of filenames so we won't mess up the display */ return 0; /* No pattern matching for now. But we don't show hidden files. */ - if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0 + if (strcmp (de->d_name, ".") != 0 && strcmp (de->d_name, "..") != 0 && de->d_name[0] == '.') return 0; if (l2 > maxlen) @@ -215,46 +409,61 @@ static int selectfn(const struct dirent return 1; } -char *tui_filereq(char *s, char *oldfile) +static int my_alphasort (const void *a, const void *b) +{ + return strcmp ((*(struct dirent **) a)->d_name, + (*(struct dirent **) b)->d_name); +} + +char *tui_filereq(char *s, char *oldfile, const char *title) { char cwd[256]; char *retval = fsbuf; char *tmp; int fin = 0; + chtype moresave[6][2]; /* Save wd */ - if (getcwd(cwd, 256) == NULL) + if (getcwd (cwd, 256) == NULL) return NULL; /* Change into directory of old file */ - strcpy(fsbuf, oldfile); - tmp = strrchr(fsbuf, '/'); + strcpy (fsbuf, oldfile); + tmp = strrchr (fsbuf, '/'); if (tmp != NULL) { *tmp = 0; - if (strlen(fsbuf) > 0) - chdir(fsbuf); + if (strlen (fsbuf) > 0) + chdir (fsbuf); } - + pattern = s; if (s[0] != '*') fprintf(stderr, "Can't handle wildcard %s\n", s); - if (s[1] != 0 && strchr(s+1, '*') != NULL) + if (s[1] != 0 && strchr (s+1, '*') != NULL) fprintf(stderr, "Can't handle wildcard %s\n", s); for (;!fin;) { struct dirent **names; int i, w, n, l, yp, oldyp, s; - + maxlen = 0; - n = scandir(".", &names, selectfn, alphasort); - + n = scandir (".", &names, selectfn, my_alphasort); + if (n <= 0) return NULL; + if (title != NULL && strlen (title) + 6 > maxlen) + maxlen = strlen (title) + 6; l = n; if (l > 15) l = 15; yp = s = 0; oldyp = -1; - w = tui_dlog(5, 5, 5 + maxlen + 3, 5 + l + 1); - tui_selwin(w); tui_drawbox(w); + w = tui_dlog (tui_cols () - maxlen - 8, 5, tui_cols () - 5, 5 + l + 1); + tui_selwin (w); tui_drawbox (w); + if (title) + mvwaddstr (currwin, 0, 2, title); + for (i = 0; i < 6; i++) { + moresave[i][0] = mvwinch (currwin, 0, maxlen-3+i); + moresave[i][1] = mvwinch (currwin, l+1, maxlen-3+i); + } for (;;) { int c; char tmp[256]; @@ -265,33 +474,45 @@ char *tui_filereq(char *s, char *oldfile if (oldyp != yp) { oldyp = yp; for (i = 0; i < l; i++) { - put_filename(names[i + yp]->d_name, 3, 2 + i, 0); + put_filename (names[i + yp]->d_name, 3, 2 + i, 0); } } - put_filename(names[s]->d_name, 3, 2 + s - yp, A_STANDOUT); - tui_refresh(); - c = getch(); - put_filename(names[s]->d_name, 3, 2 + s - yp, 0); + put_filename (names[s]->d_name, 3, 2 + s - yp, A_STANDOUT); + + if (yp == 0) + for (i = 0; i < 6; i++) + mvwaddch (currwin, 0, maxlen-3+i, moresave[i][0]); + else + mvwaddstr (currwin, 0, maxlen-3, "(more)"); + if (yp + l == n) + for (i = 0; i < 6; i++) + mvwaddch (currwin, l+1, maxlen-3+i, moresave[i][1]); + else + mvwaddstr (currwin, l+1, maxlen-3, "(more)"); + + tui_refresh (); + c = getch (); + put_filename (names[s]->d_name, 3, 2 + s - yp, 0); if (c == 27) { retval = NULL; fin = 1; break; } else if (c == KEY_ENTER || c == 13 || c == ' ') { int err; - - if (strcmp(names[s]->d_name, ".") == 0) { + + if (strcmp (names[s]->d_name, ".") == 0) { fin = 1; - strcpy(fsbuf, ""); + strcpy (fsbuf, ""); break; } - err = chdir(names[s]->d_name); - + err = chdir (names[s]->d_name); + if (err == 0) break; else if (errno == ENOTDIR) { fin = 1; - if (getcwd(fsbuf, 256) == NULL) + if (getcwd (fsbuf, 256) == NULL) retval = NULL; - if (strlen(fsbuf) + strlen(names[s]->d_name) + 2 >= 256) + if (strlen (fsbuf) + strlen (names[s]->d_name) + 2 >= 256) retval = NULL; else { strcat(fsbuf, "/"); @@ -322,29 +543,36 @@ char *tui_filereq(char *s, char *oldfile s = n - 1; break; default: - for (i = 0; i < n; i++) - if (names[i]->d_name[0] == c) { - s = i; + i = 0; + if (names[s]->d_name[0] == c) + i = s+1; + for (; i < n*2; i++) { + int j = i; + if (i >= n) + j -= n; + if (names[j]->d_name[0] == c) { + s = j; break; } + } } } #if 0 /* @@@ is this right? */ for (i = 0; i < n; i++) - free(names[i]->d_name); - free(names); + free (names[i]); + free (names); #endif - tui_dlogdie(w); + tui_dlogdie (w); } - chdir(cwd); + chdir (cwd); return retval; } -int tui_backup_optionsfile(void) +int tui_backup_optionsfile (void) { char tmp[257]; - strcpy(tmp, optionsfile); - strcat(tmp, "~"); - return rename(optionsfile, tmp); + strcpy (tmp, optionsfile); + strcat (tmp, "~"); + return rename (optionsfile, tmp); }