Exemplo n.º 1
0
static int
test_inchs(int level, char **argv, WINDOW *chrwin, WINDOW *strwin)
{
    WINDOW *txtbox = 0;
    WINDOW *txtwin = 0;
    FILE *fp;
    int j;
    int txt_x = 0, txt_y = 0;
    int base_y;
    int limit;
    cchar_t ch;
    cchar_t text[MAX_COLS];

    if (argv[level] == 0) {
	beep();
	return FALSE;
    }

    if (level > 1) {
	txtbox = newwin(LINES - BASE_Y, COLS - level, BASE_Y, level);
	box(txtbox, 0, 0);
	wnoutrefresh(txtbox);

	txtwin = derwin(txtbox,
			getmaxy(txtbox) - 2,
			getmaxx(txtbox) - 2,
			1, 1);
	base_y = 0;
    } else {
	txtwin = stdscr;
	base_y = BASE_Y;
    }

    keypad(txtwin, TRUE);	/* enable keyboard mapping */
    (void) cbreak();		/* take input chars one at a time, no wait for \n */
    (void) noecho();		/* don't echo input */

    txt_y = base_y;
    txt_x = 0;
    wmove(txtwin, txt_y, txt_x);

    if ((fp = fopen(argv[level], "r")) != 0) {
	while ((j = fgetc(fp)) != EOF) {
	    if (waddch(txtwin, UChar(j)) != OK) {
		break;
	    }
	}
	fclose(fp);
    } else {
	wprintw(txtwin, "Cannot open:\n%s", argv[1]);
    }

    while (!Quit(j = mvwgetch(txtwin, txt_y, txt_x))) {
	switch (j) {
	case KEY_DOWN:
	case 'j':
	    if (txt_y < getmaxy(txtwin) - 1)
		txt_y++;
	    else
		beep();
	    break;
	case KEY_UP:
	case 'k':
	    if (txt_y > base_y)
		txt_y--;
	    else
		beep();
	    break;
	case KEY_LEFT:
	case 'h':
	    if (txt_x > 0)
		txt_x--;
	    else
		beep();
	    break;
	case KEY_RIGHT:
	case 'l':
	    if (txt_x < getmaxx(txtwin) - 1)
		txt_x++;
	    else
		beep();
	    break;
	case 'w':
	    test_inchs(level + 1, argv, chrwin, strwin);
	    if (txtbox != 0) {
		touchwin(txtbox);
		wnoutrefresh(txtbox);
	    } else {
		touchwin(txtwin);
		wnoutrefresh(txtwin);
	    }
	    break;
	default:
	    beep();
	    break;
	}

	MvWPrintw(chrwin, 0, 0, "char:");
	wclrtoeol(chrwin);

	if (txtwin != stdscr) {
	    wmove(txtwin, txt_y, txt_x);
	    if (win_wch(txtwin, &ch) != ERR) {
		if (wadd_wch(chrwin, &ch) != ERR) {
		    for (j = txt_x + 1; j < getmaxx(txtwin); ++j) {
			if (mvwin_wch(txtwin, txt_y, j, &ch) != ERR) {
			    if (wadd_wch(chrwin, &ch) == ERR) {
				break;
			    }
			} else {
			    break;
			}
		    }
		}
	    }
	} else {
	    move(txt_y, txt_x);
	    if (in_wch(&ch) != ERR) {
		if (wadd_wch(chrwin, &ch) != ERR) {
		    for (j = txt_x + 1; j < getmaxx(txtwin); ++j) {
			if (mvin_wch(txt_y, j, &ch) != ERR) {
			    if (wadd_wch(chrwin, &ch) == ERR) {
				break;
			    }
			} else {
			    break;
			}
		    }
		}
	    }
	}
	wnoutrefresh(chrwin);

	MvWPrintw(strwin, 0, 0, "text:");
	wclrtobot(strwin);

	limit = getmaxx(strwin) - 5;

	if (txtwin != stdscr) {
	    wmove(txtwin, txt_y, txt_x);
	    if (win_wchstr(txtwin, text) != ERR) {
		(void) mvwadd_wchstr(strwin, 0, 5, text);
	    }

	    wmove(txtwin, txt_y, txt_x);
	    if (win_wchnstr(txtwin, text, limit) != ERR) {
		(void) mvwadd_wchstr(strwin, 1, 5, text);
	    }

	    if (mvwin_wchstr(txtwin, txt_y, txt_x, text) != ERR) {
		(void) mvwadd_wchstr(strwin, 2, 5, text);
	    }

	    if (mvwin_wchnstr(txtwin, txt_y, txt_x, text, limit) != ERR) {
		(void) mvwadd_wchstr(strwin, 3, 5, text);
	    }
	} else {
	    move(txt_y, txt_x);
	    if (in_wchstr(text) != ERR) {
		(void) mvwadd_wchstr(strwin, 0, 5, text);
	    }

	    move(txt_y, txt_x);
	    if (in_wchnstr(text, limit) != ERR) {
		(void) mvwadd_wchstr(strwin, 1, 5, text);
	    }

	    if (mvin_wchstr(txt_y, txt_x, text) != ERR) {
		(void) mvwadd_wchstr(strwin, 2, 5, text);
	    }

	    if (mvin_wchnstr(txt_y, txt_x, text, limit) != ERR) {
		(void) mvwadd_wchstr(strwin, 3, 5, text);
	    }
	}

	wnoutrefresh(strwin);
    }
    if (level > 1) {
	delwin(txtwin);
	delwin(txtbox);
    }
    return TRUE;
}
Exemplo n.º 2
0
int
main(int argc, char *argv[])
{
	int optc;
	int option_differences = 0,
	    option_differences_cumulative = 0,
	    option_help = 0, option_version = 0;
	double interval = 2;
	char *command;
	int command_length = 0;	/* not including final \0 */

	setlocale(LC_ALL, "");
	progname = argv[0];

	while ((optc = getopt_long(argc, argv, "+d::hn:vt", longopts, (int *) 0))
	       != EOF) {
		switch (optc) {
		case 'd':
			option_differences = 1;
			if (optarg)
				option_differences_cumulative = 1;
			break;
		case 'h':
			option_help = 1;
			break;
		case 't':
			show_title = 0;
			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 '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("  -d, --differences[=cumulative]\thighlight changes between updates\n", stderr);
		fputs("\t\t(cumulative means highlighting is cumulative)\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("  -v, --version\t\t\t\tprint the version number\n", stderr);
		fputs("  -t, --no-title\t\t\tturns off showing the header\n", stderr);
		exit(0);
	}

	if (optind >= argc)
		do_usage();

	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';
	}

	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();
	nonl();
	noecho();
	cbreak();

	for (;;) {
		time_t t = time(NULL);
		char *ts = ctime(&t);
		int tsl = strlen(ts);
		char *header;
		FILE *p;
		int x, y;
		int oldeolseen = 1;
		mbstate_t mbs;

		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
			asprintf(&header, "Every %.1fs: %.*s",
				interval, min(width - 1, command_length), command);
			mvaddstr(0, 0, header);
			if (strlen(header) > (size_t) (width - tsl - 1))
				mvaddstr(0, width - tsl - 4, "...  ");
			mvaddstr(0, width - tsl + 1, ts);
			free(header);
		}

		if (!(p = popen(command, "r"))) {
			perror("popen");
			do_exit(2);
		}

		memset(&mbs, 0, sizeof(mbs));
		for (y = show_title; y < height; y++) {
			int eolseen = 0, tabpending = 0;
			for (x = 0; x < width; x++) {
				wint_t c = L' ';
				int attr = 0, c_width;
				cchar_t cc;
				wchar_t wstr[2];

				if (!eolseen) {
					/* if there is a tab pending, just spit spaces until the
					   next stop instead of reading characters */
					if (!tabpending)
						do
							c = readwc(p, &mbs);
						while (c != WEOF && !iswprint(c)
						       && c != L'\n'
						       && c != L'\t');
					if (c == L'\n')
						if (!oldeolseen && x == 0) {
							x = -1;
							continue;
						} else
							eolseen = 1;
					else if (c == L'\t')
						tabpending = 1;
					if (c == WEOF || c == L'\n' || c == L'\t')
						c = L' ';
					if (tabpending && (((x + 1) % 8) == 0))
						tabpending = 0;
				}
				wstr[0] = c;
				wstr[1] = 0;
				setcchar (&cc, wstr, 0, 0, NULL);
				move(y, x);
				if (option_differences) {
					cchar_t oldc;
					wchar_t oldwstr[2];
					attr_t attrs;
					short colors;

					in_wch(&oldc);
					getcchar(&oldc, oldwstr, &attrs, &colors, NULL);
					attr = !first_screen
					    && (wstr[0] != oldwstr[0]
						||
						(option_differences_cumulative
						 && attrs));
				}
				if (attr)
					standout();
				add_wch(&cc);

				if (attr)
					standend();
				c_width = wcwidth(c);
				if (c_width > 1)
					x += c_width - 1;

			}
			oldeolseen = eolseen;
		}

		pclose(p);

		first_screen = 0;
		refresh();
		usleep(interval * 1000000);
	}

	endwin();

	return 0;
}
Exemplo n.º 3
0
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;
}