void wideTest(WINDOW *win) { wchar_t tmp[513]; size_t i; attrset(A_BOLD); mvaddstr(1, (COLS - 25) / 2, "Wide Character Input Test"); attrset(A_NORMAL); mvaddstr(4, 1, "Enter a string: "); echo(); get_wstr((wint_t *)tmp); addstr("\n\n String:\n\n "); addwstr(tmp); addstr("\n\n\n Hex:\n\n "); for (i = 0; i < wcslen(tmp); i++) { printw("%04x ", tmp[i]); addnwstr(tmp + i, 1); addstr(" "); } noecho(); Continue2(); }
int main(int argc, char *argv[]) { int optc; int option_differences = 0, option_differences_cumulative = 0, option_exec = 0, option_beep = 0, option_color = 0, option_errexit = 0, option_help = 0, option_version = 0; double interval = 2; char *command; wchar_t *wcommand = NULL; char **command_argv; int command_length = 0; /* not including final \0 */ int wcommand_columns = 0; /* not including final \0 */ int wcommand_characters = 0; /* not including final \0 */ watch_usec_t next_loop; /* next loop time in us, used for precise time keeping only */ int pipefd[2]; int status; pid_t child; setlocale(LC_ALL, ""); progname = argv[0]; while ((optc = getopt_long(argc, argv, "+bced::hn:pvtx", longopts, (int *) 0)) != EOF) { switch (optc) { case 'b': option_beep = 1; break; case 'c': option_color = 1; break; case 'd': option_differences = 1; if (optarg) option_differences_cumulative = 1; break; case 'e': option_errexit = 1; break; case 'h': option_help = 1; break; case 't': show_title = 0; break; case 'x': option_exec = 1; break; case 'n': { char *str; interval = strtod(optarg, &str); if (!*optarg || *str) do_usage(); if(interval < 0.1) interval = 0.1; if(interval > ~0u/1000000) interval = ~0u/1000000; } break; case 'p': precise_timekeeping = 1; break; case 'v': option_version = 1; break; default: do_usage(); break; } } if (option_version) { fprintf(stderr, "%s\n", VERSION); if (!option_help) exit(0); } if (option_help) { fprintf(stderr, usage, progname); fputs(" -b, --beep\t\t\t\tbeep if the command has a non-zero exit\n", stderr); fputs(" -d, --differences[=cumulative]\thighlight changes between updates\n", stderr); fputs("\t\t(cumulative means highlighting is cumulative)\n", stderr); fputs(" -e, --errexit\t\t\t\texit watch if the command has a non-zero exit\n", stderr); fputs(" -h, --help\t\t\t\tprint a summary of the options\n", stderr); fputs(" -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr); fputs(" -p, --precise\t\t\t\tprecise timing, ignore command run time\n", stderr); fputs(" -v, --version\t\t\t\tprint the version number\n", stderr); fputs(" -t, --no-title\t\t\tturns off showing the header\n", stderr); fputs(" -x, --exec\t\t\t\tpass command to exec instead of sh\n", stderr); exit(0); } if (optind >= argc) do_usage(); command_argv=&(argv[optind]); /* save for later */ command = strdup(argv[optind++]); command_length = strlen(command); for (; optind < argc; optind++) { char *endp; int s = strlen(argv[optind]); command = realloc(command, command_length + s + 2); /* space and \0 */ endp = command + command_length; *endp = ' '; memcpy(endp + 1, argv[optind], s); command_length += 1 + s; /* space then string length */ command[command_length] = '\0'; } // convert to wide for printing purposes //mbstowcs(NULL, NULL, 0); wcommand_characters = mbstowcs(NULL, command, 0); if(wcommand_characters < 0) { fprintf(stderr, "Unicode Handling Error\n"); exit(1); } wcommand = (wchar_t*)malloc((wcommand_characters+1) * sizeof(wcommand)); if(wcommand == NULL) { fprintf(stderr, "Unicode Handling Error (malloc)\n"); exit(1); } mbstowcs(wcommand, command, wcommand_characters+1); wcommand_columns = wcswidth(wcommand, -1); get_terminal_size(); /* Catch keyboard interrupts so we can put tty back in a sane state. */ signal(SIGINT, die); signal(SIGTERM, die); signal(SIGHUP, die); signal(SIGWINCH, winch_handler); /* Set up tty for curses use. */ curses_started = 1; initscr(); if (option_color) { if (has_colors()) { start_color(); use_default_colors(); init_ansi_colors(); } else option_color = 0; } nonl(); noecho(); cbreak(); if (precise_timekeeping) next_loop = get_time_usec(); for (;;) { time_t t = time(NULL); char *ts = ctime(&t); int tsl = strlen(ts); char *header; FILE *p; int x, y; int oldeolseen = 1; if (screen_size_changed) { get_terminal_size(); resizeterm(height, width); clear(); /* redrawwin(stdscr); */ screen_size_changed = 0; first_screen = 1; } if (show_title) { // left justify interval and command, // right justify time, clipping all to fit window width int hlen = asprintf(&header, "Every %.1fs: ", interval); // the rules: // width < tsl : print nothing // width < tsl + hlen + 1: print ts // width = tsl + hlen + 1: print header, ts // width < tsl + hlen + 4: print header, ..., ts // width < tsl + hlen + wcommand_columns: print header, truncated wcommand, ..., ts // width > "": print header, wcomand, ts // this is slightly different from how it used to be if(width >= tsl) { if(width >= tsl + hlen + 1) { mvaddstr(0, 0, header); if(width >= tsl + hlen + 2) { if(width < tsl + hlen + 4) { mvaddstr(0, width - tsl - 4, "... "); }else{ if(width < tsl + hlen + wcommand_columns) { // print truncated int avail_columns = width - tsl - hlen; int using_columns = wcommand_columns; int using_characters = wcommand_characters; while(using_columns > avail_columns - 4) { using_characters--; using_columns = wcswidth(wcommand, using_characters); } mvaddnwstr(0, hlen, wcommand, using_characters); mvaddstr(0, width - tsl - 4, "... "); }else{ mvaddwstr(0, hlen, wcommand); } } } } mvaddstr(0, width - tsl + 1, ts); } free(header); } /* allocate pipes */ if (pipe(pipefd)<0) { perror("pipe"); do_exit(7); } /* flush stdout and stderr, since we're about to do fd stuff */ fflush(stdout); fflush(stderr); /* fork to prepare to run command */ child=fork(); if (child<0) { /* fork error */ perror("fork"); do_exit(2); } else if (child==0) { /* in child */ close (pipefd[0]); /* child doesn't need read side of pipe */ close (1); /* prepare to replace stdout with pipe */ if (dup2 (pipefd[1], 1)<0) { /* replace stdout with write side of pipe */ perror("dup2"); exit(3); } dup2(1, 2); /* stderr should default to stdout */ if (option_exec) { /* pass command to exec instead of system */ if (execvp(command_argv[0], command_argv)==-1) { perror("exec"); exit(4); } } else { status=system(command); /* watch manpage promises sh quoting */ /* propagate command exit status as child exit status */ if (!WIFEXITED(status)) { /* child exits nonzero if command does */ exit(1); } else { exit(WEXITSTATUS(status)); } } } /* otherwise, we're in parent */ close(pipefd[1]); /* close write side of pipe */ if ((p=fdopen(pipefd[0], "r"))==NULL) { perror("fdopen"); do_exit(5); } for (y = show_title; y < height; y++) { int eolseen = 0, tabpending = 0; wint_t carry = WEOF; for (x = 0; x < width; x++) { wint_t c = L' '; int attr = 0; if (!eolseen) { /* if there is a tab pending, just spit spaces until the next stop instead of reading characters */ if (!tabpending) do { if(carry == WEOF) { c = my_getwc(p); }else{ c = carry; carry = WEOF; } }while (c != WEOF && !isprint(c) && c<128 && wcwidth(c) == 0 && c != L'\n' && c != L'\t' && (c != L'\033' || option_color != 1)); if (c == L'\033' && option_color == 1) { x--; process_ansi(p); continue; } if (c == L'\n') if (!oldeolseen && x == 0) { x = -1; continue; } else eolseen = 1; else if (c == L'\t') tabpending = 1; if (x==width-1 && wcwidth(c)==2) { y++; x = -1; //process this double-width carry = c; //character on the next line continue; //because it won't fit here } if (c == WEOF || c == L'\n' || c == L'\t') c = L' '; if (tabpending && (((x + 1) % 8) == 0)) tabpending = 0; } move(y, x); if (option_differences) { cchar_t oldc; in_wch(&oldc); attr = !first_screen && ((wchar_t)c != oldc.chars[0] || (option_differences_cumulative && (oldc.attr & A_ATTRIBUTES))); } if (attr) standout(); addnwstr((wchar_t*)&c,1); if (attr) standend(); if(wcwidth(c) == 0) { x--; } if(wcwidth(c) == 2) { x++; } } oldeolseen = eolseen; } fclose(p); /* harvest child process and get status, propagated from command */ if (waitpid(child, &status, 0)<0) { perror("waitpid"); do_exit(8); }; /* if child process exited in error, beep if option_beep is set */ if ((!WIFEXITED(status) || WEXITSTATUS(status))) { if (option_beep) beep(); if (option_errexit) do_exit(8); } first_screen = 0; refresh(); if (precise_timekeeping) { watch_usec_t cur_time = get_time_usec(); next_loop += USECS_PER_SEC*interval; if (cur_time < next_loop) usleep(next_loop - cur_time); } else usleep(interval * 1000000); } endwin(); return 0; }