File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / trafshow / getkey.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:55:18 2012 UTC (12 years, 4 months ago) by misho
Branches: trafshow, MAIN
CVS tags: v5_2_3p0, v5_2_3, HEAD
trafshow

    1: /*
    2:  *	Copyright (c) 1998,2004 Rinet Corp., Novosibirsk, Russia
    3:  *
    4:  * Redistribution and use in source forms, with and without modification,
    5:  * are permitted provided that this entire comment appears intact.
    6:  *
    7:  * THIS SOURCE CODE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
    8:  */
    9: 
   10: #ifdef	HAVE_CONFIG_H
   11: #include <config.h>
   12: #endif
   13: 
   14: #ifdef	HAVE_SLCURSES
   15: #include <slcurses.h>
   16: #elif	HAVE_NCURSES
   17: #include <ncurses.h>
   18: #else
   19: #include <curses.h>
   20: #endif
   21: #include <stdio.h>
   22: #include <stdlib.h>
   23: #include <string.h>
   24: #include <unistd.h>
   25: 
   26: #include "getkey.h"
   27: #include "screen.h"
   28: #include "session.h"
   29: #include "trafshow.h"
   30: #include "selector.h"
   31: #include "show_if.h"
   32: #include "show_stat.h"
   33: #include "show_dump.h"
   34: #include "events.h"
   35: #include "netstat.h"
   36: #include "help_page.h"
   37: 
   38: 
   39: static void read_key(SESSION *sd, const unsigned char *data, int len);
   40: static int scan_key(const unsigned char *buf, int len);
   41: static void parse_key(int key, PCAP_HANDLER *ph);
   42: static void init_edit_string(const char *prompter, const char *charset, int size);
   43: static int edit_string(int ch);
   44: 
   45: /* edit string stuff */
   46: static const char *numbers = "1234567890";
   47: static const char *spaces = " ,.;@/\\";
   48: static char prompt_buf[MAX_PARAM_LEN], cut_buf[MAX_PARAM_LEN];
   49: static const char *char_set;
   50: static int buf_size, cur, nb, win, scr, bartop, barlen, touch, show_win;
   51: 
   52: 
   53: void
   54: getkey_init(ph)
   55: 	PCAP_HANDLER *ph;
   56: {
   57: 	SESSION *sd;
   58: 
   59: 	if ((sd = session_open(0, 0, PlainFile)) == 0) {
   60: 		perror("session_open 0"); /* should not happen */
   61: 		exit(1);
   62: 	}
   63: 	session_setcallback(sd, 0, 0, read_key);
   64: 	session_setcookie(sd, ph);
   65: 	prompt_mode = 0;
   66: }
   67: 
   68: static void
   69: read_key(sd, data, len)
   70: 	SESSION *sd;
   71: 	const unsigned char *data;
   72: 	int len;
   73: {
   74: 	/* sanity check */
   75: 	if (sd && data && len > 0) {
   76: 		int key = scan_key(data, len);
   77: 		if (key != -1)
   78: 			parse_key(key, (PCAP_HANDLER *)session_cookie(sd));
   79: 	}
   80: }
   81: 
   82: static SELECTOR *
   83: get_selector(ph_list)
   84: 	PCAP_HANDLER *ph_list;
   85: {
   86: 	/* return current selector */
   87: 	switch (show_mode) {
   88: 	case Interfaces:
   89: 		return show_if_selector();
   90: 	case NetStat:
   91: 		return show_stat_selector(pcap_get_selected(ph_list));
   92: 	case FlowDump:
   93: 		/* nope */
   94: 		break;
   95: 	case HelpPage:
   96: 		return help_page_selector();
   97: 	}
   98: 	return 0;
   99: }
  100: 
  101: static void
  102: parse_key(key, ph_list)
  103: 	int key;
  104: 	PCAP_HANDLER *ph_list;
  105: {
  106: 	int ch = key;
  107: 	PCAP_HANDLER *ph = 0;
  108: 	SELECTOR *sp = 0;
  109: 	struct timeval now;
  110: 
  111: 	if (prompt_mode) {
  112: 		const char *txt = 0;
  113: 		int redraw = 1;
  114: 		if ((ch = edit_string(ch)) == 0) /* still edit */
  115: 			return;
  116: 		if (ch > 0) {
  117: 			switch (prompt_mode) {
  118: 			case 'r':	/* end of getting refresh time */
  119: 			case 'R':
  120: 				ch = atoi(prompt_buf);
  121: 				if (ch > 0 && ch != refresh_time) {
  122: 					if (ch < purge_time)
  123: 						refresh_time = ch;
  124: 					else	txt = "Refresh Time must be less than Purge Time";
  125: 				}
  126: 				break;
  127: 			case 'p':	/* end of getting purge time */
  128: 			case 'P':
  129: 				ch = atoi(prompt_buf);
  130: 				if (ch > 0 && ch != purge_time) {
  131: 					if (ch > refresh_time) {
  132: 						purge_time = ch;
  133: 						add_event(0, pcap_purge, ph_list);
  134: 						redraw = 0;
  135: 					} else	txt = "Purge Time must be bigger than Refresh Time";
  136: 				}
  137: 				break;
  138: 			case 'f':	/* end of getting filter expression */
  139: 			case 'F':
  140: 				if (!expression || strcmp(prompt_buf, expression)) {
  141: 					if (expression) free(expression);
  142: 					expression = strdup(prompt_buf);
  143: 					if ((txt = pcap_setexpr(ph_list, expression)) == 0) {
  144: 						if (prompt_mode == 'F') {
  145: 							add_event(0, pcap_clear, ph_list);
  146: 							redraw = 0;
  147: 						}
  148: 					}
  149: 				}
  150: 				break;
  151: 			case '/':	/* end of getting search string */
  152: 				if (prompt_buf[0] == '\0') {
  153: 					if (search) {
  154: 						free(search);
  155: 						search = 0;
  156: 						txt = "Search mode turned Off";
  157: 					}
  158: 				} else if (!search || strcmp(prompt_buf, search)) {
  159: 					if (search) free(search);
  160: 					search = strdup(prompt_buf);
  161: 				}
  162: 				break;
  163: 			case 'a':	/* end of getting aggregation masklen */
  164: 			case 'A':
  165: 				if (prompt_buf[0]) {
  166: 					ch = atoi(prompt_buf);
  167: 					if (ch < 0 || ch > ADDRBITLEN) {
  168: 						txt = "Wrong netmask length";
  169: 						break;
  170: 					}
  171: 				} else	ch = -1;
  172: 				if (show_mode == NetStat &&
  173: 				    (ph = pcap_get_selected(ph_list)) != 0) {
  174: 					if (ph->masklen != ch) {
  175: 						ph->masklen = ch;
  176: 						if (prompt_mode == 'A')
  177: 							netstat_purge(ph, 0);
  178: 					}
  179: 				} else {
  180: 					aggregate = ch;
  181: 					for (ph = ph_list; ph; ph = ph->next) {
  182: 						if (ph->masklen != aggregate) {
  183: 							ph->masklen = aggregate;
  184: 							if (prompt_mode == 'A')
  185: 								netstat_purge(ph, 0);
  186: 						}
  187: 					}
  188: 				}
  189: 				break;
  190: 			}
  191: 		}
  192: 		prompt_mode = 0;
  193: 		if (redraw)
  194: 			add_event(0, pcap_show, ph_list);
  195: 		if (txt)
  196: 			screen_status(txt);
  197: 		else	screen_update();
  198: 		return;
  199: 	}
  200: 
  201: 	/* try global operation keys */
  202: 	switch (ch) {
  203: 	case K_ESC:	/* get back show mode */
  204: 	case 'q':
  205: 	case 'Q':
  206: 		switch (show_mode) {
  207: 		case Interfaces:
  208: 			exit(0);
  209: 		case NetStat:
  210: 			if ((ph = pcap_get_selected(ph_list)) != 0 && ph->top)
  211: 				pcaph_close(ph);
  212: 			else	show_mode = Interfaces;	
  213: 			pcap_show(ph_list);
  214: 			return;
  215: 		case FlowDump:
  216: 			show_dump_close();
  217: 			show_mode = NetStat;
  218: 			pcap_show(ph_list);
  219: 			return;
  220: 		case HelpPage:
  221: 			show_mode = help_page_mode();
  222: 			pcap_show(ph_list);
  223: 			return;
  224: 		}
  225: 		break;
  226: 	case K_CTRL('L'):	/* refresh screen */
  227: 		clear();
  228: 		refresh();
  229: 		pcap_show(ph_list);
  230: 		return;
  231: 	case 'h':	/* help page if any */
  232: 	case 'H':
  233: 	case '?':
  234: 	case K_F1:
  235: 		if (help_page_list(show_mode)) {
  236: 			show_mode = HelpPage;
  237: 			pcap_show(ph_list);
  238: 			return;
  239: 		}
  240: 		break;
  241: 	case 'r':	/* start to get refresh time */
  242: 	case 'R':
  243: 		if (show_mode != FlowDump) {
  244: 			prompt_mode = ch;
  245: 			snprintf(prompt_buf, sizeof(prompt_buf), "%d", refresh_time);
  246: 			init_edit_string("Refresh seconds: ", numbers, 5);
  247: 			selector_withdraw(get_selector(ph_list));
  248: 			screen_update();
  249: 			return;
  250: 		}
  251: 		break;
  252: 	case 'p':	/* start to get purge time */
  253: 	case 'P':
  254: 		if (show_mode != FlowDump) {
  255: 			prompt_mode = ch;
  256: 			snprintf(prompt_buf, sizeof(prompt_buf), "%d", purge_time);
  257: 			init_edit_string("Purge seconds: ", numbers, 5);
  258: 			selector_withdraw(get_selector(ph_list));
  259: 			screen_update();
  260: 			return;
  261: 		}
  262: 		break;
  263: 	case 'f':	/* start to get filter expression */
  264: 	case 'F':
  265: 		if (show_mode != FlowDump) {
  266: 			prompt_mode = ch;
  267: 			prompt_buf[0] = '\0';
  268: 			if (expression) {
  269: 				(void)strncpy(prompt_buf, expression, sizeof(prompt_buf));
  270: 				prompt_buf[sizeof(prompt_buf)-1] = '\0';
  271: 			}
  272: 			init_edit_string("Filter expression: ", 0, sizeof(prompt_buf));
  273: 			selector_withdraw(get_selector(ph_list));
  274: 			screen_update();
  275: 			return;
  276: 		}
  277: 		break;
  278: 	case '/':	/* start to get search string */
  279: 		if (show_mode != FlowDump) {
  280: 			prompt_mode = ch;
  281: 			prompt_buf[0] = '\0';
  282: 			if (search) {
  283: 				(void)strncpy(prompt_buf, search, sizeof(prompt_buf));
  284: 				prompt_buf[sizeof(prompt_buf)-1] = '\0';
  285: 			}
  286: 			init_edit_string("Search string: ", 0, sizeof(prompt_buf));
  287: 			selector_withdraw(get_selector(ph_list));
  288: 			screen_update();
  289: 			return;
  290: 		}
  291: 		break;
  292: 	case K_CTRL('_'):	/* turn off search mode */
  293: 		if (show_mode != FlowDump) {
  294: 			if (search) {
  295: 				free(search);
  296: 				search = 0;
  297: 				screen_status("Search mode turned Off");
  298: 			}
  299: 			return;
  300: 		}
  301: 		break;
  302: 	case 'a':	/* start to get aggregation masklen */
  303: 	case 'A':
  304: 		if (show_mode != FlowDump) {
  305: 			char buf[100];
  306: 			prompt_mode = ch;
  307: 			prompt_buf[0] = '\0';
  308: 			if (show_mode == NetStat &&
  309: 			    (ph = pcap_get_selected(ph_list)) != 0) {
  310: 				if (ph->masklen >= 0)
  311: 					snprintf(prompt_buf, sizeof(prompt_buf), "%d", ph->masklen);
  312: 				snprintf(buf, sizeof(buf), "%s aggregation netmask length: ", ph->name);
  313: 			} else {
  314: 				if (aggregate >= 0)
  315: 					snprintf(prompt_buf, sizeof(prompt_buf), "%d", aggregate);
  316: 				(void)strcpy(buf, "Aggregation netmask length: ");
  317: 			}
  318: 			init_edit_string(buf, numbers, 5);
  319: 			selector_withdraw(get_selector(ph_list));
  320: 			screen_update();
  321: 			return;
  322: 		}
  323: 		break;
  324: 	case K_CTRL('R'): /* reset all netstat hash */
  325: 		if (show_mode == Interfaces) {
  326: 			add_event(0, pcap_clear, ph_list);
  327: 			screen_status("Resetting all flows");
  328: 			return;
  329: 		}
  330: 		break;
  331: 	case 'n':	/* toggle numeric values to names conversion */
  332: 	case 'N':
  333: 		if (show_mode != FlowDump) {
  334: 			nflag ^= 1;
  335: 			if (ch == 'N') {
  336: 				add_event(0, pcap_show, ph_list);
  337: 			} else {
  338: 				screen_status("Numeric values turned %s",
  339: 					      nflag ? "On" : "Off");
  340: 			}
  341: 			return;
  342: 		}
  343: 		break;
  344: 	}
  345: 
  346: 	/* prevent screen refresh overhead */
  347: 	gettimeofday(&now, 0);
  348: 	now.tv_sec += refresh_time;
  349: 	add_event(&now, pcap_show, ph_list);
  350: 
  351: 	/* get current selector */
  352: 	switch (show_mode) {
  353: 	case Interfaces:
  354: 		sp = show_if_selector();
  355: 		break;
  356: 	case NetStat:
  357: 		if ((ph = pcap_get_selected(ph_list)) == 0)
  358: 			return;
  359: 		sp = show_stat_selector(ph);
  360: 
  361: 		/* try special input for the show mode */
  362: 		if (show_stat_input(ph, ch)) {
  363: 			selector_redraw(sp);
  364: 			return;
  365: 		}
  366: 		break;
  367: 	case FlowDump:
  368: 		/* special input only for the show mode */
  369: 		show_dump_input(ch);
  370: 		return;
  371: 	case HelpPage:
  372: 		sp = help_page_selector();
  373: 		break;
  374: 	}
  375: 
  376: 	/* try special input for the selecting */
  377: 	ch = selector_move(ch, sp);
  378: 	if (ch < 0) {
  379: 		selector_redraw(sp);
  380: 		return;
  381: 	}
  382: 
  383: 	/* something selected */
  384: 	switch (show_mode) {
  385: 	case Interfaces:
  386: 		if ((ph = pcap_set_selected(ph_list, ch)) == 0)
  387: 			return; /* should not happen */
  388: 		/*selector_withdraw(sp);*/
  389: 		show_mode = NetStat;
  390: 		pcap_show(ph_list);
  391: 		return;
  392: 	case NetStat:
  393: 		/*selector_withdraw(sp);*/
  394: 		if (ph->masklen == -1) {
  395: 			if (show_dump_open(ph, show_stat_get(ph, ch)) == 0)
  396: 				show_mode = FlowDump;
  397: 		} else if (pcaph_create(ph, (struct netstat_header *)show_stat_get(ph, ch))) {
  398: 			pcap_show(ph_list);
  399: 		}
  400: 		return;
  401: 	case FlowDump:
  402: 		/* not reached; just to avoid compiler warning */
  403: 		return;
  404: 	case HelpPage:
  405: 		key = help_page_key(ch);
  406: 		if (key != -1 && key != 0) {
  407: 			show_mode = help_page_mode(); /* get back show mode */
  408: 			pcap_show(ph_list);
  409: 			parse_key(key, ph_list);
  410: 		}
  411: 		return;
  412: 	}
  413: }
  414: 
  415: static int
  416: scan_key(buf, len)
  417: 	const unsigned char *buf;
  418: 	int len;
  419: {
  420: 	int i;
  421: 
  422: 	if (buf[0] != ESCAPE) return buf[0];
  423: 	if (len == 1) return K_ESC;
  424: 	i = 1;
  425: 	if (buf[i] == '[' || buf[i] == 'O')
  426: 		if (++i >= len) return -1;
  427: 
  428: 	switch (buf[i]) {
  429: 	case '\0':	/* xterm */
  430: 		return K_HOME;
  431: 	case 'A':
  432: 	case 'i':
  433: 		return K_UP;
  434: 	case 'B':
  435: 		return K_DOWN;
  436: 	case 'D':
  437: 		return K_LEFT;
  438: 	case 'C':
  439: 		return K_RIGHT;
  440: 	case 'I':	/* ansi  PgUp */
  441: 	case 'V':	/* at386 PgUp */
  442: 	case 'S':	/* 97801 PgUp */
  443: 	case 'v':	/* emacs style */
  444: 		return K_PAGEUP;
  445: 	case 'G':	/* ansi  PgDn */
  446: 	case 'U':	/* at386 PgDn */
  447: 	case 'T':	/* 97801 PgDn */
  448: 		return K_PAGEDOWN;
  449: 	case 'H':	/* at386  Home */
  450: 		return K_HOME;
  451: 	case 'F':	/* ansi   End */
  452: 	case 'Y':	/* at386  End */
  453: 		return K_END;
  454: 	case '5':	/* vt200 PgUp */
  455: 		return K_PAGEUP;
  456: 	case '6':	/* vt200 PgUp */
  457: 		return K_PAGEDOWN;
  458: 	case '1':	/* vt200 PgUp */
  459: 		if (++i >= len) return -1;
  460: 		switch(buf[i]) {	/* xterm */
  461: 		case '1':
  462: 			return K_F1;
  463: 		case '2':
  464: 			return K_F2;
  465: 		case '3':
  466: 			return K_F3;
  467: 		case '4':
  468: 			return K_F4;
  469: 		case '5':	/* RS/6000 PgUp is 150g, PgDn is 154g */
  470: 			if (++i >= len) return -1;
  471: 			if (buf[i] == '0')
  472: 				return K_PAGEUP;
  473: 			if (buf[i] == '4') 
  474: 				return K_PAGEDOWN;
  475: 		}
  476: 		return K_HOME;
  477: 	case '4':	/* vt200 PgUp */
  478: 		return K_END;
  479: 	case '2':	/* xterm */
  480: 	case 'L':
  481: 		return K_INS;
  482: 	case 'M':
  483: 		return K_F1;
  484: 	case 'N':
  485: 		return K_F2;
  486: 	case 'O':
  487: 		return K_F3;
  488: 	case 'P':
  489: 		return K_F4;
  490: 	}
  491: 	return -1;
  492: }
  493: 
  494: static void
  495: init_edit_string(prompter, charset, size)
  496: 	const char *prompter, *charset;
  497: 	int size;
  498: {
  499: 	int i;
  500: 
  501: 	char_set = charset;
  502: 	touch = 0;
  503: 	show_win = 0;
  504: 
  505: 	*cut_buf = '\0';
  506: 	bartop = strlen(prompter);
  507: 	i = COLS - (bartop + 3);
  508: 	barlen = buf_size = size;
  509: 	if (barlen < 1 || barlen > i) {
  510: 		barlen = i;
  511: 		show_win = 1;
  512: 	}
  513: 
  514: 	attrset(A_NORMAL);
  515: 	move(LINES-1, 0);
  516: 	clrtoeol();
  517: 	addstr(prompter);
  518: 
  519: 	nb = strlen(prompt_buf);
  520: 	if (nb >= buf_size) nb = buf_size - 1;
  521: 	prompt_buf[nb] = '\0';
  522: 	cur = nb;
  523: 
  524: 	win = cur / barlen;	/* window number */
  525: 	scr = cur % barlen;	/* screen position */
  526: 
  527: 	if (show_win) mvprintw(LINES-1, COLS-2, "%-2d", win+1);
  528: 
  529: 	attrset(A_STANDOUT);
  530: 	mvprintw(LINES-1, bartop, "%-*.*s", barlen, barlen, &prompt_buf[win * barlen]);
  531: 
  532: 	screen_dock_cursor(LINES-1, bartop + scr);
  533: }
  534: 
  535: static int
  536: edit_string(ch)
  537: 	int ch;
  538: {
  539: 	int i;
  540: 
  541: 	switch (ch) {
  542: 	case K_ESC:
  543: 	case K_CR:
  544: 	case K_NL:
  545: 		prompt_buf[nb] = '\0';
  546: 		attrset(A_NORMAL);
  547: 		move(LINES-1, 0);
  548: 		clrtoeol();
  549: 		screen_dock_cursor(0, 0);
  550: 		return (ch == K_ESC ? -1 : 1);
  551: 
  552: 	case K_PAGEUP:	/* move to begin of window */
  553: 		cur -= cur % barlen;
  554: 		break;
  555: 	case K_PAGEDOWN:/* move to end of window */
  556: 		if (strlen(&prompt_buf[cur]) < barlen)
  557: 			cur = nb;
  558: 		else	cur += barlen - cur % barlen - 1;
  559: 		break;
  560: 	case K_UP:	/* skip to previous word */
  561: 	case K_CTRL('P'):
  562: 		ch = 0;
  563: 		for (i = cur; i > 0; i--) {
  564: 			if (!ch) {
  565: 				if (strchr(spaces, prompt_buf[i-1]))
  566: 					ch++;
  567: 			} else if (!strchr(spaces, prompt_buf[i-1]))
  568: 				break;
  569: 		}
  570: 		cur = i;
  571: 		break;
  572: 	case K_DOWN:	/* skip to next word */
  573: 	case K_CTRL('N'):
  574: 		ch = 0;
  575: 		for (i = cur; i < nb; i++) {
  576: 			if (!ch) {
  577: 				if (strchr(spaces, prompt_buf[i]))
  578: 					ch++;
  579: 			} else if (!strchr(spaces, prompt_buf[i]))
  580: 				break;
  581: 		}
  582: 		cur = i;
  583: 		break;
  584: 	case K_HOME:	/* move to begin of line */
  585: 	case K_CTRL('A'):
  586: 		cur = 0;
  587: 		break;
  588: 	case K_END:	/* move to end of line */
  589: 	case K_CTRL('E'):
  590: 		cur = nb;
  591: 		break;
  592: 	case K_LEFT:	/* move cursor left */
  593: 	case K_CTRL('B'):
  594: 		if (cur > 0) cur--;
  595: 		break;
  596: 	case K_RIGHT:	/* move cursor right */
  597: 	case K_CTRL('F'):
  598: 		if (cur < nb) cur++;
  599: 		break;
  600: 	case K_BS:	/* backspace */
  601: 		if (nb && cur) {
  602: 			memmove(&prompt_buf[cur-1], &prompt_buf[cur], nb - cur);
  603: 			cur--;
  604: 			nb--;
  605: 		}
  606: 		break;
  607: 	case K_DEL:	/* delete */
  608: 	case K_CTRL('D'):
  609: 		if (nb && cur < nb) {
  610: 			memmove(&prompt_buf[cur], &prompt_buf[cur+1], nb - cur);
  611: 			nb--;
  612: 		}
  613: 		break;
  614: 	case K_CTRL('U'):	/* erase entire line */
  615: 		(void)strcpy(cut_buf, prompt_buf);
  616: 		nb = 0;
  617: 		cur = 0;
  618: 		break;
  619: 	case K_CTRL('W'):	/* erase last word */
  620: 		ch = 0;
  621: 		for (i = cur; i > 0; i--) {
  622: 			if (!ch) {
  623: 				if (strchr(spaces, prompt_buf[i-1]))
  624: 					ch++;
  625: 			} else if (!strchr(spaces, prompt_buf[i-1]))
  626: 				break;
  627: 		}
  628: 		if (cur > i) {
  629: 			memcpy(cut_buf, &prompt_buf[i], cur - i);
  630: 			cut_buf[cur - i] = '\0';
  631: 			memmove(&prompt_buf[i], &prompt_buf[cur], cur - i);
  632: 			nb -= cur - i;
  633: 			cur = i;
  634: 		}
  635: 		break;
  636: 	case K_CTRL('K'):	/* erase end of line */
  637: 		if (prompt_buf[cur] != '\0')
  638: 			(void)strcpy(cut_buf, &prompt_buf[cur]);
  639: 		nb = cur;
  640: 		break;
  641: 	case K_TAB:	/* insert cut_buf */
  642: 		i = strlen(cut_buf);
  643: 		if (i && (buf_size - 1) - strlen(prompt_buf) >= i) {
  644: 			memmove(&prompt_buf[cur+i], &prompt_buf[cur], nb - cur);
  645: 			memmove(&prompt_buf[cur], cut_buf, i);
  646: 			nb += i;
  647: 			cur += i;
  648: 		}
  649: 		break;
  650: 	default:
  651: 		if (ch < 32 || ch > 126)
  652: 			return 0; /* skip garbage chars */
  653: 
  654: 		if (char_set && !strchr(char_set, ch)) {
  655: 			beep();
  656: 			return 0;
  657: 		}
  658: 		if (!touch) {
  659: 			nb = 0;
  660: 			cur = 0;
  661: 		}
  662: 		if (nb >= buf_size - 1) { /* no more space available */
  663: 			beep();
  664: 			return 0;
  665: 		}
  666: 		if (nb > cur)
  667: 			memmove(&prompt_buf[cur+1], &prompt_buf[cur], nb - cur);
  668: 		prompt_buf[cur++] = ch;
  669: 		nb++;
  670: 	}
  671: 	touch = 1;
  672: 
  673: 	prompt_buf[nb] = '\0';
  674: 
  675: 	win = cur / barlen;	/* window number */
  676: 	scr = cur % barlen;	/* screen position */
  677: 
  678: 	attrset(A_STANDOUT);
  679: 	mvprintw(LINES-1, bartop, "%-*.*s", barlen, barlen, &prompt_buf[win * barlen]);
  680: 	if (show_win) {
  681: 		attrset(A_NORMAL);
  682: 		mvprintw(LINES-1, COLS-2, "%-2d", win+1);
  683: 	}
  684: 
  685: 	screen_dock_cursor(LINES-1, bartop + scr);
  686: 	screen_update();
  687: 	return 0;
  688: }
  689: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>