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