File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / trafshow / selector.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 <stdlib.h>
   22: #include <string.h>
   23: 
   24: #include "selector.h"
   25: #include "screen.h"
   26: #include "getkey.h"
   27: 
   28: #define	BLANK	' '
   29: 
   30: #ifdef	ACS_HLINE
   31: #define	HLINE	ACS_HLINE
   32: #else
   33: #define	HLINE	'-'
   34: #endif
   35: 
   36: static void get_size(const SELECTOR *sp, int *lines, int *cols);
   37: static void get_colors(const SELECTOR *sp, int *foreground, int *cursor);
   38: 
   39: static void
   40: get_size(sp, lines, cols)
   41: 	const SELECTOR *sp;
   42: 	int *lines, *cols;
   43: {
   44: 	int ln = LINES, cl = COLS;
   45: 	if (sp) {
   46: 		if (sp->LINES > 0 && sp->LINES < LINES)
   47: 			ln = sp->LINES;
   48: 		if (sp->get_header)
   49: 			ln -= 2;
   50: 		if (sp->get_footer)
   51: 			ln -= 2;
   52: 		if (ln < 1)
   53: 			ln = 1;
   54: 
   55: 		if (sp->COLS > 0 && sp->COLS < COLS)
   56: 			cl = sp->COLS;
   57: 		if (cl < 1)
   58: 			cl = 1;
   59: 	}
   60: 	if (lines) *lines = ln;
   61: 	if (cols) *cols = cl;
   62: }
   63: 
   64: static void
   65: get_colors(sp, fore, curs)
   66: 	const SELECTOR *sp;
   67: 	int *fore, *curs;
   68: {
   69: 	int fg = A_NORMAL, cr = A_REVERSE;
   70: 	if (sp && use_colors) {
   71: 		if (sp->window_color != -1)
   72: 			fg = sp->window_color;
   73: 		if (sp->cursor_color != -1)
   74: 			cr = sp->cursor_color;
   75: 	}
   76: 	if (prompt_mode) cr = fg;
   77: 	if (fore) *fore = fg;
   78: 	if (curs) *curs = cr;
   79: }
   80: 
   81: /*
   82:  * Allocate & initialize selector handler.
   83:  */
   84: SELECTOR *
   85: selector_init()
   86: {
   87: 	SELECTOR *sp = (SELECTOR *)malloc(sizeof(SELECTOR));
   88: 	if (sp) {
   89: 		memset(sp, 0, sizeof(SELECTOR));
   90: 		sp->window_color = -1;
   91: 		sp->cursor_color = -1;
   92: 	}
   93: 	return sp;
   94: }
   95: 
   96: /*
   97:  * Redraw selector region and refresh screen.
   98:  */
   99: void
  100: selector_redraw(sp)
  101: 	SELECTOR *sp;
  102: {
  103: 	int i, l, r, lines, cols, first_line, first_col;
  104: 	int fg_color, cr_color, attr;
  105: 	char *cp, buf[1024];
  106: 
  107: 	/* sanity check */
  108: 	if (!sp) return;
  109: 
  110: 	if (sp->index >= sp->items)
  111: 		selector_set(sp->items - 1, sp);
  112: 
  113: 	get_size(sp, &lines, &cols);
  114: 	get_colors(sp, &fg_color, &cr_color);
  115: 
  116: 	first_line = sp->LINE;
  117: 	first_col = sp->COL;
  118: 
  119: 	attrset(A_NORMAL);
  120: 
  121: #ifdef	HAVE_WREDRAWLN
  122: 	wredrawln(stdscr, first_line, lines + 2);
  123: #endif
  124: 
  125: 	/* draw header */
  126: 	if (sp->get_header) {
  127: 		attr = fg_color;
  128: 		attr |= (*sp->get_header)(buf, sizeof(buf), sp->header);
  129: 
  130: 		move(first_line, first_col);
  131: 		r = cols;
  132: 		for (cp = buf; *cp && r-- > 0; cp++) {
  133: 			if (*cp > ' ')
  134: 				addch(*cp | attr);
  135: 			else	addch(BLANK | attr);
  136: 		}
  137: 		while (r-- > 0) addch(BLANK | attr);
  138: 
  139: 		move(first_line + 1, first_col);
  140: 		r = cols;
  141: 		while (r-- > 0) addch(HLINE | attr);
  142: 
  143: 		first_line += 2;
  144: 	}
  145: 
  146: 	/* draw main area */
  147: 	for (i = sp->fline, l = 0; l < lines; i++, l++) {
  148: 		attr = fg_color;
  149: 		move(first_line + l, first_col);
  150: 		r = cols;
  151: 		if (i < sp->items && sp->get_line) {
  152: 			attr |= (*sp->get_line)(buf, sizeof(buf), sp->list, i);
  153: 			if (i == sp->index)
  154: 				attr = cr_color;
  155: 			for (cp = buf; *cp && r-- > 0; cp++) {
  156: 				if (*cp > ' ')
  157: 					addch(*cp | attr);
  158: 				else	addch(BLANK | attr);
  159: 
  160: 				/* workaround -- last attr mustbe foreground */
  161: 				if (r == 1 && i == sp->items - 1)
  162: 					attr = fg_color;
  163: 			}
  164: 		}
  165: 		while (r-- > 0) addch(BLANK | attr);
  166: 	}
  167: 
  168: 	/* draw footer */
  169: 	if (sp->get_footer) {
  170: 		attr = fg_color;
  171: 		attr |= (*sp->get_footer)(buf, sizeof(buf), sp->footer);
  172: 
  173: 		first_line += l;
  174: 		move(first_line++, first_col);
  175: 		r = cols;
  176: 		while (r-- > 0) addch(HLINE | attr);
  177: 
  178: 		if (!prompt_mode || first_line != LINES-1) {
  179: 			move(first_line, first_col);
  180: 			r = cols;
  181: 			for (cp = buf; *cp && r-- > 0; cp++) {
  182: 				if (*cp > ' ')
  183: 					addch(*cp | attr);
  184: 				else	addch(BLANK | attr);
  185: 			}
  186: 			while (r-- > 0) addch(BLANK | attr);
  187: 		}
  188: 	}
  189: 
  190: 	/* refresh screen */
  191: 	screen_update();
  192: }
  193: 
  194: /*
  195:  * Withdraw selector from the screen.
  196:  */
  197: void
  198: selector_withdraw(sp)
  199: 	SELECTOR *sp;
  200: {
  201: 	int i, l, r, lines, cols, first_line, first_col;
  202: 	int fg_color, attr;
  203: 	char *cp, buf[1024];
  204: 
  205: 	/* sanity check */
  206: 	if (!sp || !sp->get_line) return;
  207: 
  208: 	get_size(sp, &lines, &cols);
  209: 	get_colors(sp, &fg_color, 0);
  210: 
  211: 	first_line = sp->LINE;
  212: 	first_col = sp->COL;
  213: 
  214: 	attrset(A_NORMAL);
  215: 
  216: 	if (sp->get_header)
  217: 		first_line += 2;
  218: 
  219: #ifdef	HAVE_WREDRAWLN
  220: 	wredrawln(stdscr, first_line, lines);
  221: #endif
  222: 	for (i = sp->fline, l = 0; l < lines; i++, l++) {
  223: 		if (i != sp->index)
  224: 			continue;
  225: 		attr = fg_color;
  226: 		move(first_line + l, first_col);
  227: 		r = cols;
  228: 		if (i < sp->items && sp->get_line) {
  229: 			attr |= (*sp->get_line)(buf, sizeof(buf), sp->list, i);
  230: 			for (cp = buf; *cp && r-- > 0; cp++) {
  231: 				if (*cp > ' ')
  232: 					addch(*cp | attr);
  233: 				else	addch(BLANK | attr);
  234: 
  235: 				/* workaround -- last attr mustbe foreground */
  236: 				if (r == 1 && i == sp->items - 1)
  237: 					attr = fg_color;
  238: 			}
  239: 			while (r-- > 0) addch(BLANK | attr);
  240: 		}
  241: 		break;
  242: 	}
  243: }
  244: 
  245: /*
  246:  * Return current selector position or -1 if no selector present.
  247:  */
  248: int
  249: selector_get(sp)
  250: 	SELECTOR *sp;
  251: {
  252: 	/* sanity check */
  253: 	if (!sp || !sp->list || sp->items < 1 ||
  254: 	    sp->index < 0 || sp->index >= sp->items)
  255: 		return -1;
  256: 	return sp->index;
  257: }
  258: 
  259: /*
  260:  * Set selector to requested position.
  261:  */
  262: void
  263: selector_set(new_index, sp)
  264: 	int new_index;
  265: 	SELECTOR *sp;
  266: {
  267: 	int lines;
  268: 
  269: 	/* sanity check */
  270: 	if (!sp) return;
  271: 
  272: 	if (sp->items < 1) {
  273: 		sp->index = 0;
  274: 		sp->fline = 0;
  275: 		sp->cline = 0;
  276: 		return;
  277: 	}
  278: 	get_size(sp, &lines, 0);
  279: 
  280: 	if (new_index >= sp->items)
  281: 		new_index = sp->items - 1;
  282: 
  283: 	sp->fline = (new_index / lines) * lines;
  284: 	sp->cline = new_index % lines;
  285: 	if (sp->fline + lines >= sp->items) {
  286: 		sp->fline = sp->items - lines;
  287: 		if (sp->fline < 0) sp->fline = 0;
  288: 		sp->cline = new_index - sp->fline;
  289: 	}
  290: 	sp->index = new_index;
  291: }
  292: 
  293: /*
  294:  * Move selector on screen.
  295:  * Return index selected or -1.
  296:  */
  297: int
  298: selector_move(ch, sp)
  299: 	int ch;
  300: 	SELECTOR *sp;
  301: {
  302: 	int lines;
  303: 
  304: 	/* sanity check */
  305: 	if (!sp) return -1;
  306: 
  307: 	get_size(sp, &lines, 0);
  308: 
  309: 	switch (ch) {
  310: 		case 'k':
  311: 		case K_CTRL('P'):
  312: 		case K_UP:		/* line up */
  313: 			if (sp->index - 1 < 0) break;
  314: 			sp->index--;
  315: 			if (--sp->cline < 0 && sp->fline) {
  316: 				sp->cline = 0;
  317: 				if (--sp->fline < 0)
  318: 					sp->fline = 0;
  319: 			}
  320: 			break;
  321: 
  322: 		case 'j':
  323: 		case K_CTRL('N'):
  324: 		case K_DOWN:		/* line down */
  325: 			if (sp->index + 1 >= sp->items) break;
  326: 			sp->index++;
  327: 			if (++sp->cline >= lines) {
  328: 				sp->cline--;
  329: 				sp->fline = sp->index - sp->cline;
  330: 			}
  331: 			break;
  332: 
  333: 		case K_BS:
  334: 		case K_CTRL('U'):
  335: 		case K_CTRL('B'):
  336: 		case K_PAGEUP:		/* page up */
  337: 			if (sp->cline > 0) {
  338: 				sp->index -= sp->cline;
  339: 			} else {
  340: 				sp->index -= lines;
  341: 				sp->fline -= lines;
  342: 				if (sp->index < 0 || sp->fline < 0)
  343: 					sp->index = sp->fline = 0;
  344: 			}
  345: 			sp->cline = 0;
  346: 			break;
  347: 
  348: 		case ' ':
  349: 		case K_CTRL('D'):
  350: 		case K_CTRL('F'):
  351: 		case K_PAGEDOWN:	/* page down */
  352: 			if (sp->items <= lines) {
  353: 				sp->index = sp->cline = sp->items - 1;
  354: 			} else {
  355: 				if (sp->cline < lines - 1) {
  356: 					sp->index += lines - sp->cline - 1;
  357: 				} else {
  358: 					sp->index += lines;
  359: 					sp->fline = sp->index - lines + 1;
  360: 				}
  361: 				if (sp->index >= sp->items) {
  362: 					sp->index = sp->items - 1;
  363: 					sp->fline = sp->items - lines;
  364: 				}
  365: 				sp->cline = lines - 1;
  366: 			}
  367: 			break;
  368: 
  369: 		case K_CTRL('A'):
  370: 		case K_HOME:		/* home */
  371: 			sp->index = 0;
  372: 			sp->fline = 0;
  373: 			sp->cline = 0;
  374: 			break;
  375: 
  376: 		case K_CTRL('E'):
  377: 		case K_END:		/* end */
  378: 			if (sp->items <= lines) {
  379: 				sp->index = sp->cline = sp->items - 1;
  380: 			} else {
  381: 				sp->index = sp->items - 1;
  382: 				sp->fline = sp->items - lines;
  383: 				sp->cline = lines - 1;
  384: 			}
  385: 			break;
  386: 
  387: 		case K_CR:	/* select index */
  388: 		case K_NL:
  389: 			return sp->index;
  390: 
  391: 		case K_CTRL('G'):	/* trace; for debug purpose only */
  392: 			mvprintw(LINES-1, 0, "items=%d index=%d fline=%d cline=%d LINE=%d COL=%d LINES=%d func=%p",
  393: 				 sp->items, sp->index, sp->fline,
  394: 				 sp->cline, sp->LINE, sp->COL,
  395: 				 lines, sp->get_line);
  396: 			clrtoeol();
  397: 			break;
  398: 	}
  399: 	return -1;
  400: }
  401: 

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