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>