X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=test%2Fdemo_panels.c;h=ce6beb703ce2e901a0a9f5a7c1779cb26d739cf9;hp=20fd029c82f5f38d6bb96ff9d2ed0f7e3b24d966;hb=7ca9d1eb1a8a995514d4dee312bf136fba88ec62;hpb=a8987e73ec254703634802b4f7ee30d3a485524d diff --git a/test/demo_panels.c b/test/demo_panels.c index 20fd029c..ce6beb70 100644 --- a/test/demo_panels.c +++ b/test/demo_panels.c @@ -1,15 +1,35 @@ +/**************************************************************************** + * Copyright (c) 2007-2008,2010 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ /* - * $Id: demo_panels.c,v 1.1 2003/04/26 22:11:23 tom Exp $ + * $Id: demo_panels.c,v 1.37 2010/05/01 22:19:02 tom Exp $ * * Demonstrate a variety of functions from the panel library. - * Thomas Dickey - 2003/4/26 */ -/* -panel_above - -panel_below - -panel_hidden - -replace_panel - -*/ #include @@ -17,11 +37,774 @@ replace_panel - #include +#define LAST_POS '@' +#define TEMP_POS '>' + +typedef void (*InitPanel) (void); +typedef void (*FillPanel) (PANEL *); + +static bool use_colors = FALSE; +static bool unboxed = FALSE; +static FILE *log_in; +static FILE *log_out; + +static void +close_input(void) +{ + if (log_in != 0) { + fclose(log_in); + log_in = 0; + } +} + +static void +close_output(void) +{ + if (log_out != 0) { + fclose(log_out); + log_out = 0; + } +} + +static WINDOW * +statusline(void) +{ + WINDOW *result = stdscr; + + wmove(result, LINES - 1, 0); + wclrtoeol(result); + return result; +} + +static void +pflush(void) +{ + update_panels(); + doupdate(); +} + +static void +saywhat(NCURSES_CONST char *text) +{ + WINDOW *win = statusline(); + if (text != 0 && *text != '\0') { + waddstr(win, text); + waddstr(win, "; "); + } + waddstr(win, "press any key to continue"); +} + +static void +show_position(NCURSES_CONST char *text, + NCURSES_CONST char *also, + int which, + int ypos, + int xpos) +{ + WINDOW *win = statusline(); + + wprintw(win, "%s for panel %d now %d,%d%s", text, which, ypos, xpos, also); + wmove(stdscr, ypos, xpos); +} + +static int +get_position(NCURSES_CONST char *text, + NCURSES_CONST char *also, + int which, + int *xpos, + int *ypos) +{ + int result = 0; + int x1, y1; + char cmd; + + getyx(stdscr, y1, x1); + (void) statusline(); + + show_position(text, also, which, y1, x1); + + if (log_in != 0) { + if (fscanf(log_in, "%c%d,%d\n", &cmd, &y1, &x1) == 3) { + switch (cmd) { + case LAST_POS: + result = 1; + (void) wgetch(stdscr); + break; + case TEMP_POS: + result = 0; + wrefresh(stdscr); + napms(100); + break; + default: + result = -1; + break; + } + } else { + result = -1; + } + } else { + + switch (wgetch(stdscr)) { + case QUIT: + case ESCAPE: + case ERR: + result = -1; + break; + case ' ': + result = 1; + break; + case KEY_UP: + if (y1 > 0) { + --y1; + } else { + beep(); + } + break; + case KEY_DOWN: + if (y1 < getmaxy(stdscr)) { + ++y1; + } else { + beep(); + } + break; + case KEY_LEFT: + if (x1 > 0) { + --x1; + } else { + beep(); + } + break; + case KEY_RIGHT: + if (x1 < getmaxx(stdscr)) { + ++x1; + } else { + beep(); + } + break; + } + } + + wmove(stdscr, y1, x1); + *ypos = y1; + *xpos = x1; + + if (result >= 0) { + if (log_out) + fprintf(log_out, "%c%d,%d\n", + ((result > 0) + ? LAST_POS + : TEMP_POS), + y1, x1); + } + return result; +} + +static PANEL * +mkpanel(short color, int rows, int cols, int tly, int tlx) +{ + WINDOW *win; + PANEL *pan = 0; + char *userdata = typeMalloc(char, 3); + + if ((win = newwin(rows, cols, tly, tlx)) != 0) { + keypad(win, TRUE); + if ((pan = new_panel(win)) == 0) { + delwin(win); + } else if (use_colors) { + short fg = (short) ((color == COLOR_BLUE) + ? COLOR_WHITE + : COLOR_BLACK); + short bg = color; + + init_pair(color, fg, bg); + wbkgdset(win, (chtype) (COLOR_PAIR(color) | ' ')); + } else if (!unboxed) { + wbkgdset(win, A_BOLD | ' '); + } + } + sprintf(userdata, "p%d", color % 8); + set_panel_userptr(pan, (NCURSES_CONST void *) userdata); + return pan; +} + +static void +my_remove_panel(PANEL ** pans, int which) +{ + if (pans[which] != 0) { + PANEL *pan = pans[which]; + WINDOW *win = panel_window(pan); + char *user = (char *) panel_userptr(pan); + + free(user); + del_panel(pan); + delwin(win); + + pans[which] = 0; + } +} + +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +static void +my_create_panel(PANEL ** pans, int which, FillPanel myFill) +{ + PANEL *pan = 0; + int code; + short pair = (short) which; + short fg = (short) ((pair == COLOR_BLUE) ? COLOR_WHITE : COLOR_BLACK); + short bg = pair; + int x0, y0, x1, y1; + + init_pair(pair, fg, bg); + + /* remove the old panel, if any */ + my_remove_panel(pans, which); + + /* get the position of one corner */ + wmove(stdscr, getmaxy(stdscr) / 2, getmaxx(stdscr) / 2); + getyx(stdscr, y0, x0); + while ((code = get_position("First corner", "", which, &x0, &y0)) == 0) { + ; + } + + if (code > 0) { + char also[80]; + sprintf(also, " (first %d,%d)", y0, x0); + /* get the position of the opposite corner */ + while ((code = get_position("Opposite corner", + also, which, &x1, &y1)) == 0) { + ; + } + + if (code > 0) { + int tly = MIN(y0, y1); + int tlx = MIN(x0, x1); + pan = mkpanel(pair, ABS(y1 - y0) + 1, ABS(x1 - x0) + 1, tly, tlx); + /* finish */ + myFill(pan); + pans[which] = pan; + pflush(); + wmove(stdscr, y1, x1); + } + } +} + +static void +my_move_panel(PANEL ** pans, int which, bool continuous) +{ + if (pans[which] != 0) { + int code; + int y0, x0; + int y1, x1; + WINDOW *win = panel_window(pans[which]); + char also[80]; + + getbegyx(win, y0, x0); + sprintf(also, " (start %d,%d)", y0, x0); + wmove(stdscr, y0, x0); + while ((code = get_position("Move panel", also, which, &x1, &y1)) == 0) { + if (continuous) { + move_panel(pans[which], y1, x1); + pflush(); + } + } + if (code > 0) { + move_panel(pans[which], y1, x1); + } + } +} + +static void +my_resize_panel(PANEL ** pans, int which, FillPanel myFill) +{ + if (pans[which] != 0) { + int code; + int y0, x0; + int y1, x1; + WINDOW *win = panel_window(pans[which]); + char also[80]; + + getbegyx(win, y0, x0); + sprintf(also, " (start %d,%d)", y0, x0); + wmove(stdscr, y0, x0); + while ((code = get_position("Resize panel", + also, which, &x1, &y1)) == 0) { + ; + } + if (code > 0) { + WINDOW *next = newwin(ABS(y1 - y0) + 1, + ABS(x1 - x0) + 1, + MIN(y0, y1), + MIN(x0, x1)); + if (next != 0) { + keypad(next, TRUE); + if (use_colors) { + wbkgdset(next, (chtype) (COLOR_PAIR(which) | ' ')); + } else if (!unboxed) { + wbkgdset(next, A_BOLD | ' '); + } + replace_panel(pans[which], next); + myFill(pans[which]); + delwin(win); + } + } + } +} + +static void +init_panel(void) +{ + register int y, x; + + for (y = 0; y < LINES - 1; y++) { + for (x = 0; x < COLS; x++) + wprintw(stdscr, "%d", (y + x) % 10); + } +} + +static void +fill_panel(PANEL * pan) +{ + WINDOW *win = panel_window(pan); + const char *userptr = (const char *) panel_userptr(pan); + int num = (userptr && *userptr) ? userptr[1] : '?'; + int y, x; + + wmove(win, 1, 1); + wprintw(win, "-pan%c-", num); + wclrtoeol(win); + box(win, 0, 0); + for (y = 2; y < getmaxy(win) - 1; y++) { + for (x = 1; x < getmaxx(win) - 1; x++) { + wmove(win, y, x); + waddch(win, UChar(num)); + } + } +} + +static void +fill_unboxed(PANEL * pan) +{ + WINDOW *win = panel_window(pan); + const char *userptr = (const char *) panel_userptr(pan); + int num = (userptr && *userptr) ? userptr[1] : '?'; + int y, x; + + for (y = 0; y < getmaxy(win); y++) { + for (x = 0; x < getmaxx(win); x++) { + wmove(win, y, x); + waddch(win, UChar(num)); + } + } +} + +#if USE_WIDEC_SUPPORT +static void +make_fullwidth_digit(cchar_t *target, int digit) +{ + wchar_t source[2]; + + source[0] = digit + 0xff10; + source[1] = 0; + setcchar(target, source, A_NORMAL, 0, 0); +} + +static void +init_wide_panel(void) +{ + int digit; + cchar_t temp[10]; + + for (digit = 0; digit < 10; ++digit) + make_fullwidth_digit(&temp[digit], digit); + + do { + int y, x; + getyx(stdscr, y, x); + digit = (y + x / 2) % 10; + } while (add_wch(&temp[digit]) != ERR); +} + +static void +fill_wide_panel(PANEL * pan) +{ + WINDOW *win = panel_window(pan); + int num = ((const char *) panel_userptr(pan))[1]; + int y, x; + + wmove(win, 1, 1); + wprintw(win, "-pan%c-", num); + wclrtoeol(win); + box(win, 0, 0); + for (y = 2; y < getmaxy(win) - 1; y++) { + for (x = 1; x < getmaxx(win) - 1; x++) { + wmove(win, y, x); + waddch(win, UChar(num)); + } + } +} +#endif + +#define MAX_PANELS 5 + +static int +which_panel(PANEL * px[MAX_PANELS + 1], PANEL * pan) +{ + int result = 0; + int j; + + for (j = 1; j <= MAX_PANELS; ++j) { + if (px[j] == pan) { + result = j; + break; + } + } + return result; +} + +static void +show_panels(PANEL * px[MAX_PANELS + 1]) +{ + static const char *help[] = + { + "", + "Commands are letter/digit pairs. Digits are the panel number.", + "", + " b - put the panel on the bottom of the stack", + " c - create the panel", + " d - delete the panel", + " h - hide the panel", + " m - move the panel (M for continuous move)", + " r - resize the panel", + " s - show the panel", + " b - put the panel on the top of the stack" + }; + + struct { + bool valid; + bool hidden; + PANEL *above; + PANEL *below; + } table[MAX_PANELS + 1]; + + WINDOW *win; + PANEL *pan; + int j; + + memset(table, 0, sizeof(table)); + for (j = 1; j <= MAX_PANELS; ++j) { + table[j].valid = (px[j] != 0); + if (table[j].valid) { + table[j].hidden = panel_hidden(px[j]); + table[j].above = panel_above(px[j]); + table[j].below = panel_below(px[j]); + } + } + + if ((win = newwin(LINES - 1, COLS, 0, 0)) != 0) { + keypad(win, TRUE); + if ((pan = new_panel(win)) != 0) { + werase(win); + MvWPrintw(win, 0, 0, "Panels:\n"); + for (j = 1; j <= MAX_PANELS; ++j) { + if (table[j].valid) { + wprintw(win, " %d:", j); + if (table[j].hidden) { + waddstr(win, " hidden"); + } else { + if (table[j].above) { + wprintw(win, " above %d", + which_panel(px, table[j].above)); + } + if (table[j].below) { + wprintw(win, "%s below %d", + table[j].above ? "," : "", + which_panel(px, table[j].below)); + } + } + waddch(win, '\n'); + } + } + for (j = 0; j < (int) SIZEOF(help); ++j) { + if (wprintw(win, "%s\n", help[j]) == ERR) + break; + } + wgetch(win); + del_panel(pan); + pflush(); + } + delwin(win); + } +} + +#define wrapper(func) \ +static int my_##func(PANEL *pan) \ +{ \ + int code = ERR; \ + if (pan != 0) { \ + code = func(pan); \ + } \ + return code; \ +} +/* *INDENT-OFF* */ +wrapper(bottom_panel) +wrapper(hide_panel) +wrapper(show_panel) +wrapper(top_panel) +/* *INDENT-ON* */ + +static void +do_panel(PANEL * px[MAX_PANELS + 1], + NCURSES_CONST char *cmd, + FillPanel myFill) +{ + int which = cmd[1] - '0'; + + if (which < 1 || which > MAX_PANELS) { + beep(); + return; + } + + if (log_in != 0) { + pflush(); + } + + saywhat(cmd); + switch (*cmd) { + case 'b': + my_bottom_panel(px[which]); + break; + case 'c': + my_create_panel(px, which, myFill); + break; + case 'd': + my_remove_panel(px, which); + break; + case 'h': + my_hide_panel(px[which]); + break; + case 'm': + my_move_panel(px, which, FALSE); + break; + case 'M': + my_move_panel(px, which, TRUE); + break; + case 'r': + my_resize_panel(px, which, myFill); + break; + case 's': + my_show_panel(px[which]); + break; + case 't': + my_top_panel(px[which]); + break; + } +} + +static bool +ok_letter(int ch) +{ + return isalpha(UChar(ch)) && strchr("bcdhmMrst", ch) != 0; +} + +static bool +ok_digit(int ch) +{ + return isdigit(UChar(ch)) && (ch >= '1') && (ch - '0' <= MAX_PANELS); +} + +/* + * A command consists of one or more letter/digit pairs separated by a space. + * Digits are limited to 1..MAX_PANELS. + * + * End the command with a newline. Reject other characters. + */ +static bool +get_command(PANEL * px[MAX_PANELS + 1], char *buffer, int limit) +{ + int length = 0; + int y0, x0; + int c0, ch; + WINDOW *win; + + getyx(stdscr, y0, x0); + win = statusline(); + waddstr(win, "Command:"); + buffer[length = 0] = '\0'; + + if (log_in != 0) { + if (fgets(buffer, limit - 3, log_in) != 0) { + length = (int) strlen(buffer); + while (length > 0 && isspace(UChar(buffer[length - 1]))) + buffer[--length] = '\0'; + waddstr(win, buffer); + } else { + close_input(); + } + (void) wgetch(win); + } else { + c0 = 0; + for (;;) { + ch = wgetch(win); + if (ch == ERR || ch == QUIT || ch == ESCAPE) { + buffer[0] = '\0'; + break; + } else if (ch == CTRL('L')) { + wrefresh(curscr); + } else if (ch == '\n' || ch == KEY_ENTER) { + break; + } else if (ch == '?') { + show_panels(px); + } else if (length + 3 < limit) { + if (ch >= KEY_MIN) { + beep(); + } else if (ok_letter(UChar(ch))) { + if (isalpha(UChar(c0))) { + beep(); + } else if (isdigit(UChar(c0))) { + wprintw(win, " %c", ch); + buffer[length++] = ' '; + buffer[length++] = (char) (c0 = ch); + } else { + wprintw(win, "%c", ch); + buffer[length++] = (char) (c0 = ch); + } + } else if (ok_digit(ch)) { + if (isalpha(UChar(c0))) { + wprintw(win, "%c", ch); + buffer[length++] = (char) (c0 = ch); + } else { + beep(); + } + } else if (ch == ' ') { + if (isdigit(UChar(c0))) { + wprintw(win, "%c", ch); + buffer[length++] = (char) (c0 = ch); + } else { + beep(); + } + } else { + beep(); + } + } else { + beep(); + } + } + } + + wmove(stdscr, y0, x0); + + buffer[length] = '\0'; + if (log_out && length) { + fprintf(log_out, "%s\n", buffer); + } + return (length != 0); +} + +static void +demo_panels(InitPanel myInit, FillPanel myFill) +{ + int itmp; + PANEL *px[MAX_PANELS + 1]; + char buffer[BUFSIZ]; + + scrollok(stdscr, FALSE); /* we don't want stdscr to scroll! */ + refresh(); + + myInit(); + memset(px, 0, sizeof(px)); + + while (get_command(px, buffer, sizeof(buffer))) { + int limit = (int) strlen(buffer); + for (itmp = 0; itmp < limit; itmp += 3) { + do_panel(px, buffer + itmp, myFill); + } + pflush(); + } +#if NO_LEAKS + for (itmp = 1; itmp <= MAX_PANELS; ++itmp) { + my_remove_panel(px, itmp); + } +#endif +} + +static void +usage(void) +{ + static const char *const tbl[] = + { + "Usage: demo_panels [options]" + ,"" + ,"Options:" + ," -i file read commands from file" + ," -o file record commands in file" + ," -m do not use colors" +#if USE_WIDEC_SUPPORT + ," -w use wide-characters in panels and background" +#endif + ," -x do not enclose panels in boxes" + }; + size_t n; + for (n = 0; n < SIZEOF(tbl); n++) + fprintf(stderr, "%s\n", tbl[n]); + ExitProgram(EXIT_FAILURE); +} + int -main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) +main(int argc, char *argv[]) { - printf("Not implemented - demo for panel library\n"); - return EXIT_SUCCESS; + int c; + bool monochrome = FALSE; + InitPanel myInit = init_panel; + FillPanel myFill = fill_panel; + + setlocale(LC_ALL, ""); + + while ((c = getopt(argc, argv, "i:o:mwx")) != -1) { + switch (c) { + case 'i': + log_in = fopen(optarg, "r"); + break; + case 'o': + log_out = fopen(optarg, "w"); + break; + case 'm': + monochrome = TRUE; + break; +#if USE_WIDEC_SUPPORT + case 'w': + myInit = init_wide_panel; + myFill = fill_wide_panel; + break; +#endif + case 'x': + unboxed = TRUE; + break; + default: + usage(); + } + } + if (unboxed) + myFill = fill_unboxed; + + initscr(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); + + use_colors = monochrome ? FALSE : has_colors(); + if (use_colors) + start_color(); + + demo_panels(myInit, myFill); + endwin(); + + close_input(); + close_output(); + + ExitProgram(EXIT_SUCCESS); } #else int