X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=test%2Fdemo_panels.c;h=ce6beb703ce2e901a0a9f5a7c1779cb26d739cf9;hp=5723263cc572c8c8118292254560b18e1a916323;hb=5bfda8791637989e00be64748603cf4be2efbce5;hpb=2c829dd4faf4c7933e06804793e84079300e34e9 diff --git a/test/demo_panels.c b/test/demo_panels.c old mode 100755 new mode 100644 index 5723263c..ce6beb70 --- a/test/demo_panels.c +++ b/test/demo_panels.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 2007 Free Software Foundation, Inc. * + * 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 * @@ -26,17 +26,10 @@ * authorization. * ****************************************************************************/ /* - * $Id: demo_panels.c,v 1.5 2007/05/26 22:35:46 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 @@ -44,53 +37,188 @@ replace_panel - #include +#define LAST_POS '@' +#define TEMP_POS '>' + typedef void (*InitPanel) (void); typedef void (*FillPanel) (PANEL *); -static bool use_colors; +static bool use_colors = FALSE; +static bool unboxed = FALSE; +static FILE *log_in; +static FILE *log_out; -static NCURSES_CONST char *mod[] = +static void +close_input(void) { - "test ", - "TEST ", - "(**) ", - "*()* ", - "<--> ", - "LAST " -}; - -/*+------------------------------------------------------------------------- - saywhat(text) ---------------------------------------------------------------------------*/ + 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) { - wmove(stdscr, LINES - 1, 0); - wclrtoeol(stdscr); + WINDOW *win = statusline(); if (text != 0 && *text != '\0') { - waddstr(stdscr, text); - waddstr(stdscr, "; "); + 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; + } } - waddstr(stdscr, "press any key to continue"); -} /* end of saywhat */ + + 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 = malloc(3); + 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 = (color == COLOR_BLUE) ? COLOR_WHITE : COLOR_BLACK; + 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 { + } else if (!unboxed) { wbkgdset(win, A_BOLD | ' '); } } @@ -99,30 +227,132 @@ mkpanel(short color, int rows, int cols, int tly, int tlx) return pan; } -/*+------------------------------------------------------------------------- - rmpanel(pan) ---------------------------------------------------------------------------*/ static void -rmpanel(PANEL * pan) +my_remove_panel(PANEL ** pans, int which) { - WINDOW *win = panel_window(pan); - del_panel(pan); - delwin(win); -} /* end of rmpanel */ + 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)) -/*+------------------------------------------------------------------------- - pflush() ---------------------------------------------------------------------------*/ static void -pflush(void) +my_create_panel(PANEL ** pans, int which, FillPanel myFill) { - update_panels(); - doupdate(); -} /* end of pflush */ + 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); + } + } + } +} -/*+------------------------------------------------------------------------- - fill_panel(win) ---------------------------------------------------------------------------*/ static void init_panel(void) { @@ -138,7 +368,8 @@ static void fill_panel(PANEL * pan) { WINDOW *win = panel_window(pan); - int num = ((const char *) panel_userptr(pan))[1]; + const char *userptr = (const char *) panel_userptr(pan); + int num = (userptr && *userptr) ? userptr[1] : '?'; int y, x; wmove(win, 1, 1); @@ -153,6 +384,22 @@ fill_panel(PANEL * pan) } } +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) @@ -202,164 +449,285 @@ fill_wide_panel(PANEL * pan) #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 -canned_panel(PANEL * px[MAX_PANELS + 1], NCURSES_CONST char *cmd) +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': - hide_panel(px[which]); + my_hide_panel(px[which]); break; - case 's': - show_panel(px[which]); + case 'm': + my_move_panel(px, which, FALSE); break; - case 't': - top_panel(px[which]); + case 'M': + my_move_panel(px, which, TRUE); break; - case 'b': - bottom_panel(px[which]); + case 'r': + my_resize_panel(px, which, myFill); break; - case 'd': - rmpanel(px[which]); + case 's': + my_show_panel(px[which]); + break; + case 't': + my_top_panel(px[which]); break; } - pflush(); - wgetch(stdscr); +} + +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(void (*myInit) (void), void (*myFill) (PANEL *)) +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(); - for (itmp = 1; itmp <= MAX_PANELS; ++itmp) - px[itmp] = 0; - - px[1] = mkpanel(COLOR_RED, - LINES / 2 - 2, - COLS / 8 + 1, - 0, - 0); - - px[2] = mkpanel(COLOR_GREEN, - LINES / 2 + 1, - COLS / 7, - LINES / 4, - COLS / 10); - - px[3] = mkpanel(COLOR_YELLOW, - LINES / 4, - COLS / 10, - LINES / 2, - COLS / 9); - - px[4] = mkpanel(COLOR_BLUE, - LINES / 2 - 2, - COLS / 8, - LINES / 2 - 2, - COLS / 3); - - px[5] = mkpanel(COLOR_MAGENTA, - LINES / 2 - 2, - COLS / 8, - LINES / 2, - COLS / 2 - 2); - - myFill(px[1]); - myFill(px[2]); - myFill(px[3]); - myFill(px[4]); - myFill(px[5]); - - hide_panel(px[4]); - hide_panel(px[5]); - pflush(); - saywhat(""); - wgetch(stdscr); - - saywhat("h3 s1 s2 s4 s5"); - move_panel(px[1], 0, 0); - hide_panel(px[3]); - show_panel(px[1]); - show_panel(px[2]); - show_panel(px[4]); - show_panel(px[5]); - pflush(); - wgetch(stdscr); - - canned_panel(px, "s1"); - canned_panel(px, "s2"); - - saywhat("m2"); - move_panel(px[2], LINES / 3 + 1, COLS / 8); - pflush(); - wgetch(stdscr); - - canned_panel(px, "s3"); - - saywhat("m3"); - move_panel(px[3], LINES / 4 + 1, COLS / 15); - pflush(); - wgetch(stdscr); - - canned_panel(px, "b3"); - canned_panel(px, "s4"); - canned_panel(px, "s5"); - canned_panel(px, "t3"); - canned_panel(px, "t1"); - canned_panel(px, "t2"); - canned_panel(px, "t3"); - canned_panel(px, "t4"); - - for (itmp = 0; itmp < 6; itmp++) { - WINDOW *w4 = panel_window(px[4]); - WINDOW *w5 = panel_window(px[5]); - - saywhat("m4"); - wmove(w4, LINES / 8, 1); - waddstr(w4, mod[itmp]); - move_panel(px[4], LINES / 6, itmp * (COLS / 8)); - wmove(w5, LINES / 6, 1); - waddstr(w5, mod[itmp]); - pflush(); - wgetch(stdscr); - - saywhat("m5"); - wmove(w4, LINES / 6, 1); - waddstr(w4, mod[itmp]); - move_panel(px[5], LINES / 3 - 1, (itmp * 10) + 6); - wmove(w5, LINES / 8, 1); - waddstr(w5, mod[itmp]); + 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(); - wgetch(stdscr); } - - saywhat("m4"); - move_panel(px[4], LINES / 6, itmp * (COLS / 8)); - pflush(); - wgetch(stdscr); - - canned_panel(px, "t5"); - canned_panel(px, "t2"); - canned_panel(px, "t1"); - canned_panel(px, "d2"); - canned_panel(px, "h3"); - canned_panel(px, "d1"); - canned_panel(px, "d4"); - canned_panel(px, "d5"); - canned_panel(px, "d3"); - - wgetch(stdscr); - - erase(); - endwin(); +#if NO_LEAKS + for (itmp = 1; itmp <= MAX_PANELS; ++itmp) { + my_remove_panel(px, itmp); + } +#endif } static void @@ -370,10 +738,13 @@ usage(void) "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++) @@ -389,8 +760,16 @@ main(int argc, char *argv[]) InitPanel myInit = init_panel; FillPanel myFill = fill_panel; - while ((c = getopt(argc, argv, "mw")) != EOF) { + 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; @@ -400,12 +779,20 @@ main(int argc, char *argv[]) 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) @@ -414,7 +801,10 @@ main(int argc, char *argv[]) demo_panels(myInit, myFill); endwin(); - return EXIT_SUCCESS; + close_input(); + close_output(); + + ExitProgram(EXIT_SUCCESS); } #else int