X-Git-Url: http://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=test%2Fview.c;h=76a88a3096aeea8ac99f8b4721e3198048f724ae;hp=a6303c1d30d123b4cd812bb8dd3b3dcbeec7120f;hb=938680fa3bc29d2a086031a2f648dfd6cadcb51e;hpb=46722468f47c2b77b3987729b4bcf2321cccfd01 diff --git a/test/view.c b/test/view.c index a6303c1d..76a88a30 100644 --- a/test/view.c +++ b/test/view.c @@ -1,3 +1,30 @@ +/**************************************************************************** + * Copyright (c) 1998-2011,2012 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. * + ****************************************************************************/ /* * view.c -- a silly little viewer program * @@ -23,19 +50,23 @@ * scroll operation worked, and the refresh() code only had to do a * partial repaint. * - * $Id: view.c,v 1.53 2002/06/29 23:28:27 tom Exp $ + * $Id: view.c,v 1.89 2012/12/29 22:38:28 tom Exp $ */ -#include +#include +#include + #include -#include +#undef CTRL /* conflict on AIX 5.2 with */ #if HAVE_TERMIOS_H # include #else +#if !defined(__MINGW32__) # include #endif +#endif #if !defined(sun) || !HAVE_TERMIOS_H # if HAVE_SYS_IOCTL_H @@ -54,7 +85,7 @@ static RETSIGTYPE finish(int sig) GCC_NORETURN; static void show_all(const char *tag); -#if defined(SIGWINCH) && defined(TIOCGWINSZ) && HAVE_RESIZETERM +#if defined(SIGWINCH) && defined(TIOCGWINSZ) && HAVE_RESIZE_TERM #define CAN_RESIZE 1 #else #define CAN_RESIZE 0 @@ -63,15 +94,18 @@ static void show_all(const char *tag); #if CAN_RESIZE static RETSIGTYPE adjust(int sig); static int interrupted; +static bool waiting = FALSE; #endif -static bool waiting = FALSE; static int shift = 0; static bool try_color = FALSE; static char *fname; -static NCURSES_CH_T **my_lines; +static NCURSES_CH_T **vec_lines; static NCURSES_CH_T **lptr; +static int num_lines; + +static void usage(void) GCC_NORETURN; static void usage(void) @@ -103,11 +137,19 @@ ch_len(NCURSES_CH_T * src) { int result = 0; #if USE_WIDEC_SUPPORT + int count; #endif #if USE_WIDEC_SUPPORT - while (getcchar(src++, NULL, NULL, NULL, NULL) > 0) - result++; + for (;;) { + TEST_CCHAR(src, count, { + ++result; + ++src; + } + , { + break; + }) + } #else while (*src++) result++; @@ -122,24 +164,26 @@ ch_len(NCURSES_CH_T * src) static NCURSES_CH_T * ch_dup(char *src) { - unsigned len = strlen(src); + unsigned len = (unsigned) strlen(src); NCURSES_CH_T *dst = typeMalloc(NCURSES_CH_T, len + 1); - unsigned j, k; + size_t j, k; #if USE_WIDEC_SUPPORT wchar_t wstr[CCHARW_MAX + 1]; wchar_t wch; int l = 0; - mbstate_t state; size_t rc; int width; +#ifndef state_unused + mbstate_t state; #endif +#endif /* USE_WIDEC_SUPPORT */ #if USE_WIDEC_SUPPORT - memset(&state, 0, sizeof(state)); + reset_mbytes(state); #endif for (j = k = 0; j < len; j++) { #if USE_WIDEC_SUPPORT - rc = mbrtowc(&wch, src + j, len - j, &state); + rc = (size_t) check_mbytes(wch, src + j, len - j, state); if (rc == (size_t) -1 || rc == (size_t) -2) break; j += rc - 1; @@ -156,7 +200,7 @@ ch_dup(char *src) wstr[l++] = L' '; wstr[l++] = wch; #else - dst[k++] = src[j]; + dst[k++] = (chtype) UChar(src[j]); #endif } #if USE_WIDEC_SUPPORT @@ -165,7 +209,8 @@ ch_dup(char *src) if (setcchar(dst + k, wstr, 0, 0, NULL) == OK) ++k; } - setcchar(dst + k, L"", 0, 0, NULL); + wstr[0] = L'\0'; + setcchar(dst + k, wstr, 0, 0, NULL); #else dst[k] = 0; #endif @@ -181,7 +226,6 @@ main(int argc, char *argv[]) int i; int my_delay = 0; NCURSES_CH_T **olptr; - int length = 0; int value = 0; bool done = FALSE; bool got_number = FALSE; @@ -200,18 +244,17 @@ main(int argc, char *argv[]) (void) signal(SIGINT, finish); /* arrange interrupts to terminate */ #endif - while ((i = getopt(argc, argv, "cin:rtT:")) != EOF) { + while ((i = getopt(argc, argv, "cin:rtT:")) != -1) { switch (i) { case 'c': try_color = TRUE; break; case 'i': - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGTERM, SIG_IGN); + CATCHALL(SIG_IGN); break; case 'n': - if ((MAXLINES = atoi(optarg)) < 1) + if ((MAXLINES = atoi(optarg)) < 1 || + (MAXLINES + 2) <= 1) usage(); break; #if CAN_RESIZE @@ -221,7 +264,13 @@ main(int argc, char *argv[]) #endif #ifdef TRACE case 'T': - trace(atoi(optarg)); + { + char *next = 0; + int tvalue = strtol(optarg, &next, 0); + if (tvalue < 0 || (next != 0 && *next != 0)) + usage(); + trace((unsigned) tvalue); + } break; case 't': trace(TRACE_CALLS); @@ -234,9 +283,11 @@ main(int argc, char *argv[]) if (optind + 1 != argc) usage(); - if ((my_lines = typeMalloc(NCURSES_CH_T *, MAXLINES + 2)) == 0) + if ((vec_lines = typeCalloc(NCURSES_CH_T *, (size_t) MAXLINES + 2)) == 0) usage(); + assert(vec_lines != 0); + fname = argv[optind]; if ((fp = fopen(fname, "r")) == 0) { perror(fname); @@ -247,16 +298,34 @@ main(int argc, char *argv[]) (void) signal(SIGWINCH, adjust); /* arrange interrupts to resize */ #endif - /* slurp the file */ - for (lptr = &my_lines[0]; (lptr - my_lines) < MAXLINES; lptr++) { + Trace(("slurp the file")); + for (lptr = &vec_lines[0]; (lptr - vec_lines) < MAXLINES; lptr++) { char temp[BUFSIZ], *s, *d; int col; if (fgets(buf, sizeof(buf), fp) == 0) break; - /* convert tabs so that shift will work properly */ +#if USE_WIDEC_SUPPORT + if (lptr == vec_lines) { + if (!memcmp("", buf, 3)) { + Trace(("trim BOM")); + s = buf + 3; + d = buf; + do { + } while ((*d++ = *s++) != '\0'); + } + } +#endif + + /* convert tabs and nonprinting chars so that shift will work properly */ for (s = buf, d = temp, col = 0; (*d = *s) != '\0'; s++) { + if (*d == '\r') { + if (s[1] == '\n') + continue; + else + break; + } if (*d == '\n') { *d = '\0'; break; @@ -274,14 +343,14 @@ main(int argc, char *argv[]) } else { sprintf(d, "\\%03o", UChar(*s)); d += strlen(d); - col = (d - temp); + col = (int) (d - temp); } #endif } *lptr = ch_dup(temp); } (void) fclose(fp); - length = lptr - my_lines; + num_lines = (int) (lptr - vec_lines); (void) initscr(); /* initialize the curses library */ keypad(stdscr, TRUE); /* enable keyboard mapping */ @@ -295,36 +364,37 @@ main(int argc, char *argv[]) if (has_colors()) { start_color(); init_pair(my_pair, COLOR_WHITE, COLOR_BLUE); - bkgd(COLOR_PAIR(my_pair)); + bkgd((chtype) COLOR_PAIR(my_pair)); } else { try_color = FALSE; } } - lptr = my_lines; + lptr = vec_lines; while (!done) { int n, c; if (!got_number) show_all(my_label); - n = 0; for (;;) { #if CAN_RESIZE if (interrupted) { adjust(0); my_label = "interrupt"; } -#endif waiting = TRUE; c = getch(); waiting = FALSE; +#else + c = getch(); +#endif if ((c < 127) && isdigit(c)) { if (!got_number) { - mvprintw(0, 0, "Count: "); + MvPrintw(0, 0, "Count: "); clrtoeol(); } - addch(c); + addch(UChar(c)); value = 10 * value + (c - '0'); got_number = TRUE; } else @@ -343,35 +413,35 @@ main(int argc, char *argv[]) case 'n': olptr = lptr; for (i = 0; i < n; i++) - if ((lptr - my_lines) < (length - LINES + 1)) + if ((lptr - vec_lines) < (num_lines - LINES + 1)) lptr++; else break; - wscrl(stdscr, lptr - olptr); + scrl((int) (lptr - olptr)); break; case KEY_UP: case 'p': olptr = lptr; for (i = 0; i < n; i++) - if (lptr > my_lines) + if (lptr > vec_lines) lptr--; else break; - wscrl(stdscr, lptr - olptr); + scrl((int) (lptr - olptr)); break; case 'h': case KEY_HOME: - lptr = my_lines; + lptr = vec_lines; break; case 'e': case KEY_END: - if (length > LINES) - lptr = my_lines + length - LINES + 1; + if (num_lines > LINES) + lptr = vec_lines + num_lines - LINES + 1; else - lptr = my_lines; + lptr = vec_lines; break; case 'r': @@ -429,17 +499,25 @@ static RETSIGTYPE finish(int sig) { endwin(); +#if NO_LEAKS + if (vec_lines != 0) { + int n; + for (n = 0; n < num_lines; ++n) { + free(vec_lines[n]); + } + free(vec_lines); + } +#endif ExitProgram(sig != 0 ? EXIT_FAILURE : EXIT_SUCCESS); } #if CAN_RESIZE /* - * This uses functions that are "unsafe", but it seems to work on SunOS and - * Linux. Usually: the "unsafe" refers to the functions that POSIX lists - * which may be called from a signal handler. Those do not include buffered - * I/O, which is used for instance in wrefresh(). To be really portable, you - * should use the KEY_RESIZE return (which relies on ncurses' sigwinch - * handler). + * This uses functions that are "unsafe", but it seems to work on SunOS. + * Usually: the "unsafe" refers to the functions that POSIX lists which may be + * called from a signal handler. Those do not include buffered I/O, which is + * used for instance in wrefresh(). To be really portable, you should use the + * KEY_RESIZE return (which relies on ncurses' sigwinch handler). * * The 'wrefresh(curscr)' is needed to force the refresh to start from the top * of the screen -- some xterms mangle the bitmap while resizing. @@ -452,7 +530,7 @@ adjust(int sig) if (ioctl(fileno(stdout), TIOCGWINSZ, &size) == 0) { resize_term(size.ws_row, size.ws_col); - wrefresh(curscr); /* Linux needs this */ + wrefresh(curscr); show_all(sig ? "SIGWINCH" : "interrupt"); } interrupted = FALSE; @@ -472,18 +550,23 @@ show_all(const char *tag) time_t this_time; #if CAN_RESIZE - sprintf(temp, "%s (%3dx%3d) col %d ", tag, LINES, COLS, shift); - i = strlen(temp); - sprintf(temp + i, "view %.*s", (int) (sizeof(temp) - 7 - i), fname); + sprintf(temp, "%.20s (%3dx%3d) col %d ", tag, LINES, COLS, shift); + i = (int) strlen(temp); + if ((i + 7) < (int) sizeof(temp)) { + sprintf(temp + i, "view %.*s", + (int) (sizeof(temp) - 7 - (size_t) i), + fname); + } #else + (void) tag; sprintf(temp, "view %.*s", (int) sizeof(temp) - 7, fname); #endif move(0, 0); printw("%.*s", COLS, temp); clrtoeol(); this_time = time((time_t *) 0); - strcpy(temp, ctime(&this_time)); - if ((i = strlen(temp)) != 0) { + strncpy(temp, ctime(&this_time), 30); + if ((i = (int) strlen(temp)) != 0) { temp[--i] = 0; if (move(0, COLS - i - 2) != ERR) printw(" %s", temp); @@ -492,18 +575,21 @@ show_all(const char *tag) scrollok(stdscr, FALSE); /* prevent screen from moving */ for (i = 1; i < LINES; i++) { move(i, 0); - printw("%3ld:", (long) (lptr + i - my_lines)); + printw("%3ld:", (long) (lptr + i - vec_lines)); clrtoeol(); if ((s = lptr[i - 1]) != 0) { int len = ch_len(s); - if (len > shift) + if (len > shift) { #if USE_WIDEC_SUPPORT add_wchstr(s + shift); #else addchstr(s + shift); #endif + } +#if defined(NCURSES_VERSION) || defined(HAVE_WCHGAT) if (try_color) wchgat(stdscr, -1, A_NORMAL, my_pair, NULL); +#endif } } setscrreg(1, LINES - 1);