Annotation of embedaddon/trafshow/selector.c, revision 1.1
1.1 ! misho 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>