Annotation of libaitcli/example/t.c, revision 1.2

1.2     ! misho       1: #include <stdio.h>
        !             2: #include <stdlib.h>
        !             3: #include <unistd.h>
        !             4: #include <string.h>
        !             5: #include <termios.h>
        !             6: #include <poll.h>
        !             7: #include <aitio.h>
        !             8: #include <sys/types.h>
        !             9: #include <sys/param.h>
        !            10: #include <sys/stat.h>
        !            11: #include <sys/queue.h>
        !            12: #include "keys.h"
        !            13: 
        !            14: 
        !            15: int freeLineCLI(linebuffer_t * __restrict buffer);
        !            16: 
        !            17: 
        !            18: static inline void
        !            19: clrscrEOL(linebuffer_t * __restrict buf)
        !            20: {
        !            21:        register int i;
        !            22: 
        !            23:        if (buf) {
        !            24:                write(buf->line_out, K_CR, 1);
        !            25: 
        !            26:                for (i = 0; i < buf->line_len; i++)
        !            27:                        write(buf->line_out, K_SPACE, 1);
        !            28:        }
        !            29: }
        !            30: 
        !            31: static inline void
        !            32: printfEOL(linebuffer_t * __restrict buf, int len, int prompt)
        !            33: {
        !            34:        if (buf) {
        !            35:                write(buf->line_out, K_CR, 1);
        !            36: 
        !            37:                if (prompt && buf->line_prompt)
        !            38:                        write(buf->line_out, buf->line_prompt, buf->line_bol);
        !            39: 
        !            40:                write(buf->line_out, buf->line_buf, len == -1 ? buf->line_eol - buf->line_bol: len);
        !            41:        }
        !            42: }
        !            43: 
        !            44: static inline void
        !            45: printfCR(linebuffer_t * __restrict buf, int prompt)
        !            46: {
        !            47:        if (buf) {
        !            48:                write(buf->line_out, K_CR, 1);
        !            49: 
        !            50:                if (prompt)
        !            51:                        if (prompt && buf->line_prompt)
        !            52:                                write(buf->line_out, buf->line_prompt, buf->line_bol);
        !            53:        }
        !            54: }
        !            55: 
        !            56: static inline void
        !            57: printfCLI(linebuffer_t * __restrict buf, const unsigned char *text, int textlen, int prompt)
        !            58: {
        !            59:        if (buf && text && textlen) {
        !            60:                if (prompt && buf->line_prompt)
        !            61:                        write(buf->line_out, buf->line_prompt, buf->line_bol);
        !            62: 
        !            63:                write(buf->line_out, text, textlen);
        !            64:        }
        !            65: }
        !            66: 
        !            67: 
        !            68: static int
        !            69: catCh2Buf(int idx, void * __restrict buffer)
        !            70: {
        !            71:        linebuffer_t *buf = buffer;
        !            72:        int pos;
        !            73:        unsigned char b[BUFSIZ];
        !            74: 
        !            75:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !            76:                return RETCODE_ERR;
        !            77: 
        !            78:        pos = buf->line_eol - buf->line_bol;
        !            79: 
        !            80:        if (buf->line_mode == LINEMODE_INS)
        !            81:                memmove(buf->line_buf + pos + buf->line_keys[idx].key_len, buf->line_buf + pos, 
        !            82:                                buf->line_len - buf->line_eol);
        !            83:        if (buf->line_mode == LINEMODE_INS || buf->line_eol == buf->line_len - 1)
        !            84:                buf->line_len += buf->line_keys[idx].key_len;
        !            85:        buf->line_eol += buf->line_keys[idx].key_len;
        !            86: 
        !            87:        memcpy(buf->line_buf + pos, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
        !            88:        buf->line_buf[buf->line_len - 1] = 0;
        !            89: 
        !            90:        write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
        !            91: 
        !            92:        if (buf->line_mode == LINEMODE_INS) {
        !            93:                printfCLI(buf, (const u_char*) buf->line_buf + pos + buf->line_keys[idx].key_len, 
        !            94:                                buf->line_len - buf->line_eol, 0);
        !            95:                printfEOL(buf, -1, 1);
        !            96:        }
        !            97:        return RETCODE_OK;
        !            98: }
        !            99: 
        !           100: static int
        !           101: bufEOL(int idx, void * __restrict buffer)
        !           102: {
        !           103:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           104:                return RETCODE_ERR;
        !           105: 
        !           106:        printfCR(buffer, 1);
        !           107:        return RETCODE_EOL;
        !           108: }
        !           109: 
        !           110: static int
        !           111: bufEOF(int idx, void * __restrict buffer)
        !           112: {
        !           113:        linebuffer_t *buf = buffer;
        !           114: 
        !           115:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           116:                return RETCODE_ERR;
        !           117: 
        !           118:        write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
        !           119:        return RETCODE_EOF;
        !           120: }
        !           121: 
        !           122: static int
        !           123: bufTab(int idx, void * __restrict buffer)
        !           124: {
        !           125:        linebuffer_t *buf = buffer;
        !           126: 
        !           127:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           128:                return RETCODE_ERR;
        !           129: 
        !           130:        /* show */
        !           131:        write(buf->line_out, "shmink", 6);
        !           132: 
        !           133:        return RETCODE_OK;
        !           134: }
        !           135: 
        !           136: static int
        !           137: bufUP(int idx, void * __restrict buffer)
        !           138: {
        !           139:        linebuffer_t *buf = buffer;
        !           140:        int pos;
        !           141: 
        !           142:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           143:                return RETCODE_ERR;
        !           144: 
        !           145:        if (!buf->line_h)
        !           146:                buf->line_h = TAILQ_FIRST(&buf->line_history);
        !           147:        else
        !           148:                buf->line_h = TAILQ_NEXT(buf->line_h, hist_next);
        !           149:        if (!buf->line_h)
        !           150:                return RETCODE_OK;
        !           151: 
        !           152:        clrscrEOL(buf);
        !           153:        freeLineCLI(buf);
        !           154: 
        !           155:        pos = buf->line_eol - buf->line_bol;
        !           156: 
        !           157:        buf->line_len += buf->line_h->hist_len;
        !           158:        buf->line_eol += buf->line_h->hist_len;
        !           159: 
        !           160:        memcpy(buf->line_buf + pos, buf->line_h->hist_line, buf->line_h->hist_len);
        !           161:        buf->line_buf[buf->line_len - 1] = 0;
        !           162: 
        !           163:        printfEOL(buf, -1, 1);
        !           164:        return RETCODE_OK;
        !           165: }
        !           166: 
        !           167: static int
        !           168: bufDOWN(int idx, void * __restrict buffer)
        !           169: {
        !           170:        linebuffer_t *buf = buffer;
        !           171:        int pos;
        !           172: 
        !           173:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           174:                return RETCODE_ERR;
        !           175: 
        !           176:        if (!buf->line_h)
        !           177:                buf->line_h = TAILQ_LAST(&buf->line_history, tqHistoryHead);
        !           178:        else
        !           179:                buf->line_h = TAILQ_PREV(buf->line_h, tqHistoryHead, hist_next);
        !           180:        if (!buf->line_h)
        !           181:                return RETCODE_OK;
        !           182: 
        !           183:        clrscrEOL(buf);
        !           184:        freeLineCLI(buf);
        !           185: 
        !           186:        pos = buf->line_eol - buf->line_bol;
        !           187: 
        !           188:        buf->line_len += buf->line_h->hist_len;
        !           189:        buf->line_eol += buf->line_h->hist_len;
        !           190: 
        !           191:        memcpy(buf->line_buf + pos, buf->line_h->hist_line, buf->line_h->hist_len);
        !           192:        buf->line_buf[buf->line_len - 1] = 0;
        !           193: 
        !           194:        printfEOL(buf, -1, 1);
        !           195:        return RETCODE_OK;
        !           196: }
        !           197: 
        !           198: static int
        !           199: bufClr(int idx, void * __restrict buffer)
        !           200: {
        !           201:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           202:                return RETCODE_ERR;
        !           203: 
        !           204:        clrscrEOL(buffer);
        !           205:        freeLineCLI(buffer);
        !           206: 
        !           207:        printfCR(buffer, 1);
        !           208:        return RETCODE_OK;
        !           209: }
        !           210: 
        !           211: static int
        !           212: bufBS(int idx, void * __restrict buffer)
        !           213: {
        !           214:        linebuffer_t *buf = buffer;
        !           215: 
        !           216:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           217:                return RETCODE_ERR;
        !           218: 
        !           219:        if (buf->line_bol < buf->line_eol) {
        !           220:                clrscrEOL(buf);
        !           221: 
        !           222:                buf->line_eol--;
        !           223:                buf->line_len--;
        !           224:                memmove(buf->line_buf + buf->line_eol - buf->line_bol, 
        !           225:                                buf->line_buf + buf->line_eol - buf->line_bol + 1, 
        !           226:                                buf->line_len - buf->line_eol);
        !           227:                buf->line_buf[buf->line_len - 1] = 0;
        !           228: 
        !           229:                printfEOL(buf, buf->line_len - 1, 1);
        !           230:                printfEOL(buf, -1, 1);
        !           231:        }
        !           232: 
        !           233:        return RETCODE_OK;
        !           234: }
        !           235: 
        !           236: static int
        !           237: bufBTAB(int idx, void * __restrict buffer)
        !           238: {
        !           239:        linebuffer_t *buf = buffer;
        !           240: 
        !           241:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           242:                return RETCODE_ERR;
        !           243: 
        !           244:        if (buf->line_bol < buf->line_eol) {
        !           245:                clrscrEOL(buf);
        !           246: 
        !           247:                buf->line_len = buf->line_eol - buf->line_bol + 1;
        !           248:                buf->line_buf[buf->line_len - 1] = 0;
        !           249: 
        !           250:                printfEOL(buf, -1, 1);
        !           251:        }
        !           252: 
        !           253:        return RETCODE_OK;
        !           254: }
        !           255: 
        !           256: static int
        !           257: bufMode(int idx, void * __restrict buffer)
        !           258: {
        !           259:        linebuffer_t *buf = buffer;
        !           260: 
        !           261:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           262:                return RETCODE_ERR;
        !           263: 
        !           264:        buf->line_mode = !buf->line_mode ? LINEMODE_OVER : LINEMODE_INS;
        !           265:        return RETCODE_OK;
        !           266: }
        !           267: 
        !           268: static int
        !           269: bufBegin(int idx, void * __restrict buffer)
        !           270: {
        !           271:        linebuffer_t *buf = buffer;
        !           272: 
        !           273:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           274:                return RETCODE_ERR;
        !           275: 
        !           276:        buf->line_eol = buf->line_bol;
        !           277: 
        !           278:        printfCR(buf, 1);
        !           279:        return RETCODE_OK;
        !           280: }
        !           281: 
        !           282: static int
        !           283: bufEnd(int idx, void * __restrict buffer)
        !           284: {
        !           285:        linebuffer_t *buf = buffer;
        !           286: 
        !           287:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           288:                return RETCODE_ERR;
        !           289: 
        !           290:        buf->line_eol = buf->line_len - 1;
        !           291: 
        !           292:        printfEOL(buf, -1, 1);
        !           293:        return RETCODE_OK;
        !           294: }
        !           295: 
        !           296: static int
        !           297: bufLEFT(int idx, void * __restrict buffer)
        !           298: {
        !           299:        linebuffer_t *buf = buffer;
        !           300: 
        !           301:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           302:                return RETCODE_ERR;
        !           303: 
        !           304:        if (buf->line_bol < buf->line_eol)
        !           305:                printfEOL(buf, --buf->line_eol - buf->line_bol, 1);
        !           306: 
        !           307:        return RETCODE_OK;
        !           308: }
        !           309: 
        !           310: static int
        !           311: bufRIGHT(int idx, void * __restrict buffer)
        !           312: {
        !           313:        linebuffer_t *buf = buffer;
        !           314: 
        !           315:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           316:                return RETCODE_ERR;
        !           317: 
        !           318:        if (buf->line_eol < buf->line_len - 1)
        !           319:                printfEOL(buf, ++buf->line_eol - buf->line_bol, 1);
        !           320: 
        !           321:        return RETCODE_OK;
        !           322: }
        !           323: 
        !           324: static int
        !           325: bufDel(int idx, void * __restrict buffer)
        !           326: {
        !           327:        linebuffer_t *buf = buffer;
        !           328: 
        !           329:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           330:                return RETCODE_ERR;
        !           331: 
        !           332:        clrscrEOL(buf);
        !           333: 
        !           334:        buf->line_len--;
        !           335:        memmove(buf->line_buf + buf->line_eol - buf->line_bol, 
        !           336:                        buf->line_buf + buf->line_eol - buf->line_bol + 1, 
        !           337:                        buf->line_len - buf->line_eol);
        !           338:        buf->line_buf[buf->line_len - 1] = 0;
        !           339: 
        !           340:        printfEOL(buf, buf->line_len - 1, 1);
        !           341:        printfEOL(buf, -1, 1);
        !           342: 
        !           343:        return RETCODE_OK;
        !           344: }
        !           345: 
        !           346: // ---------------------------------------------------------------
        !           347: 
        !           348: int
        !           349: bindKeyCLI(bindkey_t * __restrict key, linebuffer_t * __restrict buffer)
        !           350: {
        !           351:        register int i;
        !           352: 
        !           353:        if (!key || !buffer)
        !           354:                return RETCODE_ERR;
        !           355: 
        !           356:        for (i = 0; i < MAX_BINDKEY; i++)
        !           357:                if (key->key_len == buffer->line_keys[i].key_len && 
        !           358:                                !memcmp(key->key_ch, buffer->line_keys[i].key_ch, key->key_len)) {
        !           359:                        buffer->line_keys[i].key_func = key->key_func;
        !           360:                        return i;
        !           361:                }
        !           362:        return RETCODE_OK;
        !           363: }
        !           364: 
        !           365: linebuffer_t *
        !           366: initCLI(int fin, int fout, const char *prompt)
        !           367: {
        !           368:        linebuffer_t *buffer;
        !           369:        bindkey_t *keys;
        !           370:        register int i;
        !           371:        struct termios t;
        !           372: 
        !           373:        memset(&t, 0, sizeof t);
        !           374:        /* init buffer */
        !           375:        buffer = malloc(sizeof (linebuffer_t));
        !           376:        if (!buffer)
        !           377:                return NULL;
        !           378:        else {
        !           379:                memset(buffer, 0, sizeof(linebuffer_t));
        !           380: 
        !           381:                buffer->line_in = fin;
        !           382:                buffer->line_out = fout;
        !           383: 
        !           384:                TAILQ_INIT(&buffer->line_history);
        !           385: 
        !           386:                if (prompt) {
        !           387:                        buffer->line_prompt = strdup(prompt);
        !           388:                        if (!buffer->line_prompt) {
        !           389:                                free(buffer);
        !           390:                                return NULL;
        !           391:                        } else {
        !           392:                                buffer->line_bol = strlen(buffer->line_prompt);
        !           393:                                buffer->line_eol = buffer->line_bol;
        !           394:                        }
        !           395:                }
        !           396:        }
        !           397:        buffer->line_buf = malloc(BUFSIZ);
        !           398:        if (!buffer->line_buf) {
        !           399:                if (buffer->line_prompt)
        !           400:                        free(buffer->line_prompt);
        !           401:                free(buffer);
        !           402:                return NULL;
        !           403:        } else {
        !           404:                memset(buffer->line_buf, 0, BUFSIZ);
        !           405:                buffer->line_len = 1 + buffer->line_eol;
        !           406:        }
        !           407:        keys = calloc(MAX_BINDKEY + 1, sizeof(bindkey_t));
        !           408:        if (!keys) {
        !           409:                if (buffer->line_prompt)
        !           410:                        free(buffer->line_prompt);
        !           411:                free(buffer->line_buf);
        !           412:                free(buffer);
        !           413:                return NULL;
        !           414:        } else
        !           415:                memset(keys, 0, sizeof(bindkey_t) * (MAX_BINDKEY + 1));
        !           416: 
        !           417:        /* fill key bindings */
        !           418:        // ascii chars & ctrl+chars
        !           419:        for (i = 0; i < 256; i++) {
        !           420:                *keys[i].key_ch = (unsigned char) i;
        !           421:                keys[i].key_len = 1;
        !           422: 
        !           423:                if (!i || i == *K_CTRL_D)
        !           424:                        keys[i].key_func = bufEOF;
        !           425:                if (i == *K_CTRL_M || i == *K_CTRL_J)
        !           426:                        keys[i].key_func = bufEOL;
        !           427:                if (i == *K_CTRL_H || i == *K_BACKSPACE)
        !           428:                        keys[i].key_func = bufBS;
        !           429:                if (i == *K_CTRL_C)
        !           430:                        keys[i].key_func = bufClr;
        !           431:                if (i == *K_CTRL_A)
        !           432:                        keys[i].key_func = bufBegin;
        !           433:                if (i == *K_CTRL_E)
        !           434:                        keys[i].key_func = bufEnd;
        !           435:                if (i >= *K_SPACE && i < *K_BACKSPACE)
        !           436:                        keys[i].key_func = catCh2Buf;
        !           437:                if (i > *K_BACKSPACE && i < 0xff)
        !           438:                        keys[i].key_func = catCh2Buf;
        !           439:        }
        !           440:        // alt+chars
        !           441:        for (i = 256; i < 512; i++) {
        !           442:                keys[i].key_ch[0] = 0x1b;
        !           443:                keys[i].key_ch[1] = (unsigned char) i - 256;
        !           444:                keys[i].key_len = 2;
        !           445:        }
        !           446: 
        !           447:        // 3 bytes
        !           448:        keys[i].key_len = sizeof K_F1 - 1;
        !           449:        memcpy(keys[i].key_ch, K_F1, keys[i++].key_len);
        !           450:        keys[i].key_len = sizeof K_F2 - 1;
        !           451:        memcpy(keys[i].key_ch, K_F2, keys[i++].key_len);
        !           452:        keys[i].key_len = sizeof K_F3 - 1;
        !           453:        memcpy(keys[i].key_ch, K_F3, keys[i++].key_len);
        !           454:        keys[i].key_len = sizeof K_F4 - 1;
        !           455:        memcpy(keys[i].key_ch, K_F4, keys[i++].key_len);
        !           456:        keys[i].key_len = sizeof K_CTRL_SH_F1 - 1;
        !           457:        memcpy(keys[i].key_ch, K_CTRL_SH_F1, keys[i++].key_len);
        !           458:        keys[i].key_len = sizeof K_CTRL_SH_F2 - 1;
        !           459:        memcpy(keys[i].key_ch, K_CTRL_SH_F2, keys[i++].key_len);
        !           460:        keys[i].key_len = sizeof K_CTRL_SH_F3 - 1;
        !           461:        memcpy(keys[i].key_ch, K_CTRL_SH_F3, keys[i++].key_len);
        !           462:        keys[i].key_len = sizeof K_CTRL_SH_F4 - 1;
        !           463:        memcpy(keys[i].key_ch, K_CTRL_SH_F4, keys[i++].key_len);
        !           464:        keys[i].key_len = sizeof K_CTRL_SH_F5 - 1;
        !           465:        memcpy(keys[i].key_ch, K_CTRL_SH_F5, keys[i++].key_len);
        !           466:        keys[i].key_len = sizeof K_CTRL_SH_F6 - 1;
        !           467:        memcpy(keys[i].key_ch, K_CTRL_SH_F6, keys[i++].key_len);
        !           468:        keys[i].key_len = sizeof K_CTRL_SH_F7 - 1;
        !           469:        memcpy(keys[i].key_ch, K_CTRL_SH_F7, keys[i++].key_len);
        !           470:        keys[i].key_len = sizeof K_CTRL_SH_F8 - 1;
        !           471:        memcpy(keys[i].key_ch, K_CTRL_SH_F8, keys[i++].key_len);
        !           472:        keys[i].key_len = sizeof K_CTRL_SH_F9 - 1;
        !           473:        memcpy(keys[i].key_ch, K_CTRL_SH_F9, keys[i++].key_len);
        !           474:        keys[i].key_len = sizeof K_CTRL_SH_F10 - 1;
        !           475:        memcpy(keys[i].key_ch, K_CTRL_SH_F10, keys[i++].key_len);
        !           476:        keys[i].key_len = sizeof K_CTRL_SH_F11 - 1;
        !           477:        memcpy(keys[i].key_ch, K_CTRL_SH_F11, keys[i++].key_len);
        !           478:        keys[i].key_len = sizeof K_CTRL_SH_F12 - 1;
        !           479:        memcpy(keys[i].key_ch, K_CTRL_SH_F12, keys[i++].key_len);
        !           480:        keys[i].key_len = sizeof K_CTRL_F1 - 1;
        !           481:        memcpy(keys[i].key_ch, K_CTRL_F1, keys[i++].key_len);
        !           482:        keys[i].key_len = sizeof K_CTRL_F2 - 1;
        !           483:        memcpy(keys[i].key_ch, K_CTRL_F2, keys[i++].key_len);
        !           484:        keys[i].key_len = sizeof K_CTRL_F3 - 1;
        !           485:        memcpy(keys[i].key_ch, K_CTRL_F3, keys[i++].key_len);
        !           486:        keys[i].key_len = sizeof K_CTRL_F4 - 1;
        !           487:        memcpy(keys[i].key_ch, K_CTRL_F4, keys[i++].key_len);
        !           488:        keys[i].key_len = sizeof K_CTRL_F5 - 1;
        !           489:        memcpy(keys[i].key_ch, K_CTRL_F5, keys[i++].key_len);
        !           490:        keys[i].key_len = sizeof K_CTRL_F6 - 1;
        !           491:        memcpy(keys[i].key_ch, K_CTRL_F6, keys[i++].key_len);
        !           492:        keys[i].key_len = sizeof K_CTRL_F7 - 1;
        !           493:        memcpy(keys[i].key_ch, K_CTRL_F7, keys[i++].key_len);
        !           494:        keys[i].key_len = sizeof K_CTRL_F8 - 1;
        !           495:        memcpy(keys[i].key_ch, K_CTRL_F8, keys[i++].key_len);
        !           496:        keys[i].key_len = sizeof K_CTRL_F9 - 1;
        !           497:        memcpy(keys[i].key_ch, K_CTRL_F9, keys[i++].key_len);
        !           498:        keys[i].key_len = sizeof K_CTRL_F10 - 1;
        !           499:        memcpy(keys[i].key_ch, K_CTRL_F10, keys[i++].key_len);
        !           500:        keys[i].key_len = sizeof K_CTRL_F11 - 1;
        !           501:        memcpy(keys[i].key_ch, K_CTRL_F11, keys[i++].key_len);
        !           502:        keys[i].key_len = sizeof K_CTRL_F12 - 1;
        !           503:        memcpy(keys[i].key_ch, K_CTRL_F12, keys[i++].key_len);
        !           504:        keys[i].key_len = sizeof K_HOME - 1;
        !           505:        keys[i].key_func = bufBegin;
        !           506:        memcpy(keys[i].key_ch, K_HOME, keys[i++].key_len);
        !           507:        keys[i].key_len = sizeof K_END - 1;
        !           508:        keys[i].key_func = bufEnd;
        !           509:        memcpy(keys[i].key_ch, K_END, keys[i++].key_len);
        !           510:        keys[i].key_len = sizeof K_UP - 1;
        !           511:        keys[i].key_func = bufUP;
        !           512:        memcpy(keys[i].key_ch, K_UP, keys[i++].key_len);
        !           513:        keys[i].key_len = sizeof K_DOWN - 1;
        !           514:        keys[i].key_func = bufDOWN;
        !           515:        memcpy(keys[i].key_ch, K_DOWN, keys[i++].key_len);
        !           516:        keys[i].key_len = sizeof K_RIGHT - 1;
        !           517:        keys[i].key_func = bufRIGHT;
        !           518:        memcpy(keys[i].key_ch, K_RIGHT, keys[i++].key_len);
        !           519:        keys[i].key_len = sizeof K_LEFT - 1;
        !           520:        keys[i].key_func = bufLEFT;
        !           521:        memcpy(keys[i].key_ch, K_LEFT, keys[i++].key_len);
        !           522:        keys[i].key_len = sizeof K_BTAB - 1;
        !           523:        keys[i].key_func = bufBTAB;
        !           524:        memcpy(keys[i].key_ch, K_BTAB, keys[i++].key_len);
        !           525:        // 4 bytes
        !           526:        keys[i].key_len = sizeof K_INS - 1;
        !           527:        keys[i].key_func = bufMode;
        !           528:        memcpy(keys[i].key_ch, K_INS, keys[i++].key_len);
        !           529:        keys[i].key_len = sizeof K_DEL - 1;
        !           530:        keys[i].key_func = bufDel;
        !           531:        memcpy(keys[i].key_ch, K_DEL, keys[i++].key_len);
        !           532:        keys[i].key_len = sizeof K_PGUP - 1;
        !           533:        memcpy(keys[i].key_ch, K_PGUP, keys[i++].key_len);
        !           534:        keys[i].key_len = sizeof K_PGDN - 1;
        !           535:        memcpy(keys[i].key_ch, K_PGDN, keys[i++].key_len);
        !           536:        // 5 bytes
        !           537:        keys[i].key_len = sizeof K_F5 - 1;
        !           538:        memcpy(keys[i].key_ch, K_F5, keys[i++].key_len);
        !           539:        keys[i].key_len = sizeof K_F6 - 1;
        !           540:        memcpy(keys[i].key_ch, K_F6, keys[i++].key_len);
        !           541:        keys[i].key_len = sizeof K_F7 - 1;
        !           542:        memcpy(keys[i].key_ch, K_F7, keys[i++].key_len);
        !           543:        keys[i].key_len = sizeof K_F8 - 1;
        !           544:        memcpy(keys[i].key_ch, K_F8, keys[i++].key_len);
        !           545:        keys[i].key_len = sizeof K_F9 - 1;
        !           546:        memcpy(keys[i].key_ch, K_F9, keys[i++].key_len);
        !           547:        keys[i].key_len = sizeof K_F10 - 1;
        !           548:        memcpy(keys[i].key_ch, K_F10, keys[i++].key_len);
        !           549:        keys[i].key_len = sizeof K_F11 - 1;
        !           550:        memcpy(keys[i].key_ch, K_F11, keys[i++].key_len);
        !           551:        keys[i].key_len = sizeof K_F12 - 1;
        !           552:        memcpy(keys[i].key_ch, K_F12, keys[i++].key_len);
        !           553: 
        !           554:        tcgetattr(buffer->line_in, &t);
        !           555:        t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);
        !           556:        t.c_iflag |= IGNBRK;
        !           557:        t.c_cc[VMIN] = 1;
        !           558:        t.c_cc[VTIME] = 0;
        !           559:        tcsetattr(buffer->line_in, TCSANOW, &t);
        !           560: 
        !           561:        buffer->line_keys = keys;
        !           562:        return buffer;
        !           563: }
        !           564: 
        !           565: void
        !           566: endCLI(linebuffer_t * __restrict buffer)
        !           567: {
        !           568:        struct tagHistory *h;
        !           569: 
        !           570:        if (buffer) {
        !           571:                while ((h = TAILQ_FIRST(&buffer->line_history))) {
        !           572:                        TAILQ_REMOVE(&buffer->line_history, h, hist_next);
        !           573:                        free(h);
        !           574:                }
        !           575: 
        !           576:                if (buffer->line_prompt)
        !           577:                        free(buffer->line_prompt);
        !           578: 
        !           579:                if (buffer->line_keys)
        !           580:                        free(buffer->line_keys);
        !           581:                if (buffer->line_buf)
        !           582:                        free(buffer->line_buf);
        !           583: 
        !           584:                free(buffer);
        !           585:                buffer = NULL;
        !           586:        }
        !           587: }
        !           588: 
        !           589: void
        !           590: setPromptCLI(linebuffer_t * __restrict buffer, const char *prompt)
        !           591: {
        !           592:        if (buffer) {
        !           593:                if (buffer->line_prompt) {
        !           594:                        free(buffer->line_prompt);
        !           595:                        buffer->line_prompt = NULL;
        !           596:                        buffer->line_bol = 0;
        !           597:                }
        !           598: 
        !           599:                if (prompt) {
        !           600:                        buffer->line_prompt = strdup(prompt);
        !           601:                        if (buffer->line_prompt) {
        !           602:                                buffer->line_bol = strlen(buffer->line_prompt);
        !           603:                                buffer->line_eol = buffer->line_bol;
        !           604:                                buffer->line_len = 1 + buffer->line_eol;
        !           605:                        }
        !           606:                }
        !           607:        }
        !           608: }
        !           609: 
        !           610: int
        !           611: freeLineCLI(linebuffer_t * __restrict buffer)
        !           612: {
        !           613:        int code = RETCODE_ERR;
        !           614: 
        !           615:        if (buffer) {
        !           616:                if (buffer->line_buf)
        !           617:                        free(buffer->line_buf);
        !           618: 
        !           619:                buffer->line_buf = malloc(BUFSIZ);
        !           620:                if (buffer->line_buf) {
        !           621:                        memset(buffer->line_buf, 0, BUFSIZ);
        !           622:                        buffer->line_eol = buffer->line_bol;
        !           623:                        buffer->line_len = 1 + buffer->line_eol;
        !           624: 
        !           625:                        code = RETCODE_OK;
        !           626:                }
        !           627:        }
        !           628: 
        !           629:        return code;
        !           630: }
        !           631: 
        !           632: int
        !           633: readLineCLI(linebuffer_t * __restrict buffer)
        !           634: {
        !           635:        int code, readLen;
        !           636:        register int i;
        !           637:        char buf[BUFSIZ];
        !           638:        struct pollfd fds;
        !           639: 
        !           640:        if (!buffer)
        !           641:                return RETCODE_ERR;
        !           642: 
        !           643:        memset(&fds, 0, sizeof fds);
        !           644:        fds.fd = buffer->line_in;
        !           645:        fds.events = POLLIN;
        !           646: 
        !           647:        printfCR(buffer, 1);
        !           648:        while (42) {
        !           649:                if (poll(&fds, 1, -1) < 1)
        !           650:                        return RETCODE_ERR;
        !           651: 
        !           652:                memset(buf, 0, sizeof buf);
        !           653:                readLen = read(buffer->line_in, buf, BUFSIZ);
        !           654:                if (readLen == -1)
        !           655:                        return RETCODE_ERR;
        !           656:                if (!readLen)
        !           657:                        return RETCODE_EOF;
        !           658: 
        !           659: recheck:
        !           660: //             for (i = 0; i < readLen; i++)
        !           661: //                     printf("i=%d readLen=%d buf=%x\n", i, readLen, (u_char) buf[i]);
        !           662:                for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
        !           663:                        if (readLen >= buffer->line_keys[i].key_len && 
        !           664:                                        !memcmp(buffer->line_keys[i].key_ch, buf, buffer->line_keys[i].key_len)) {
        !           665:                                readLen -= buffer->line_keys[i].key_len;
        !           666:                                if (readLen)
        !           667:                                        memmove(buf, buf + buffer->line_keys[i].key_len, readLen);
        !           668:                                else
        !           669:                                        memset(buf, 0, buffer->line_keys[i].key_len);
        !           670: 
        !           671:                                if (buffer->line_keys[i].key_func)
        !           672:                                        if ((code = buffer->line_keys[i].key_func(i, buffer)))
        !           673:                                                readLen = 0;
        !           674: 
        !           675:                                if (readLen)
        !           676:                                        goto recheck;
        !           677:                                else
        !           678:                                        break;
        !           679:                        }
        !           680: 
        !           681:                if (code)
        !           682:                        break;
        !           683:        }
        !           684: 
        !           685:        return code;
        !           686: }
        !           687: 
        !           688: int
        !           689: addHistoryCLI(linebuffer_t * __restrict buffer, const char * __restrict str)
        !           690: {
        !           691:        struct tagHistory *h;
        !           692: 
        !           693:        if (!buffer)
        !           694:                return RETCODE_ERR;
        !           695: 
        !           696:        if (!(h = malloc(sizeof(struct tagHistory)))) {
        !           697:                return RETCODE_ERR;
        !           698:        } else
        !           699:                memset(h, 0, sizeof(struct tagHistory));
        !           700: 
        !           701:        if (str) {
        !           702:                if (!*str) {
        !           703:                        free(h);
        !           704:                        return RETCODE_OK;
        !           705:                }
        !           706: 
        !           707:                h->hist_len = strlcpy(h->hist_line, str, BUFSIZ);
        !           708:        } else {
        !           709:                if (!*buffer->line_buf || buffer->line_len < 2) {
        !           710:                        free(h);
        !           711:                        return RETCODE_OK;
        !           712:                }
        !           713: 
        !           714:                memcpy(h->hist_line, buffer->line_buf, (h->hist_len = buffer->line_len));
        !           715:                io_TrimStr((unsigned char*) h->hist_line);
        !           716:                h->hist_len = strlen(h->hist_line);
        !           717:        }
        !           718: 
        !           719:        TAILQ_INSERT_HEAD(&buffer->line_history, h, hist_next);
        !           720:        return h->hist_len;
        !           721: }
        !           722: 
        !           723: int
        !           724: saveHistoryCLI(linebuffer_t * __restrict buffer, const char *histfile, int lines)
        !           725: {
        !           726:        FILE *f;
        !           727:        mode_t mode;
        !           728:        char szFName[MAXPATHLEN];
        !           729:        struct tagHistory *h;
        !           730: 
        !           731:        if (!buffer)
        !           732:                return RETCODE_ERR;
        !           733:        if (!histfile)
        !           734:                strlcpy(szFName, HISTORY_FILE, MAXPATHLEN);
        !           735:        else
        !           736:                strlcpy(szFName, histfile, MAXPATHLEN);
        !           737: 
        !           738:        mode = umask(0177);
        !           739:        f = fopen(szFName, "w");
        !           740:        if (!f)
        !           741:                return RETCODE_ERR;
        !           742:        TAILQ_FOREACH(h, &buffer->line_history, hist_next) {
        !           743:                fprintf(f, "%s\n", h->hist_line);
        !           744: 
        !           745:                if (lines)
        !           746:                        lines--;
        !           747:                else
        !           748:                        break;
        !           749:        }
        !           750:        fclose(f);
        !           751:        umask(mode);
        !           752: 
        !           753:        return RETCODE_OK;
        !           754: }
        !           755: 
        !           756: int
        !           757: loadHistoryCLI(linebuffer_t * __restrict buffer, const char *histfile)
        !           758: {
        !           759:        FILE *f;
        !           760:        char szFName[MAXPATHLEN], buf[BUFSIZ];
        !           761:        struct tagHistory *h;
        !           762: 
        !           763:        if (!buffer)
        !           764:                return RETCODE_ERR;
        !           765:        if (!histfile)
        !           766:                strlcpy(szFName, HISTORY_FILE, MAXPATHLEN);
        !           767:        else
        !           768:                strlcpy(szFName, histfile, MAXPATHLEN);
        !           769: 
        !           770:        f = fopen(szFName, "r");
        !           771:        if (!f)
        !           772:                return RETCODE_ERR;
        !           773:        while (fgets(buf, BUFSIZ, f)) {
        !           774:                if (!*buf || *buf == '#')
        !           775:                        continue;
        !           776:                else
        !           777:                        io_TrimStr((unsigned char*) buf);
        !           778: 
        !           779:                if (!(h = malloc(sizeof(struct tagHistory)))) {
        !           780:                        fclose(f);
        !           781:                        return RETCODE_ERR;
        !           782:                } else
        !           783:                        memset(h, 0, sizeof(struct tagHistory));
        !           784: 
        !           785:                h->hist_len = strlcpy(h->hist_line, buf, BUFSIZ);
        !           786:                TAILQ_INSERT_TAIL(&buffer->line_history, h, hist_next);
        !           787:        }
        !           788:        fclose(f);
        !           789: 
        !           790:        return RETCODE_OK;
        !           791: }
        !           792: 
        !           793: inline void
        !           794: resetHistoryCLI(linebuffer_t * __restrict buffer)
        !           795: {
        !           796:        buffer->line_h = NULL;
        !           797: }
        !           798: 
        !           799: // ------------------------------------------------------------
        !           800: 
        !           801: int
        !           802: main()
        !           803: {
        !           804:        int ret;
        !           805:        bindkey_t key = { sizeof K_TAB - 1, K_TAB, bufTab };
        !           806:        linebuffer_t *buffer = initCLI(STDIN_FILENO, STDOUT_FILENO, CLI_PROMPT);
        !           807: 
        !           808:        bindKeyCLI(&key, buffer);
        !           809: 
        !           810:        loadHistoryCLI(buffer, NULL);
        !           811: 
        !           812:        while (42) {
        !           813:                ret = readLineCLI(buffer);
        !           814:                addHistoryCLI(buffer, NULL);
        !           815: 
        !           816:                printf("LINE=%s (%d)/%d/%d CODE=%d\n", buffer->line_buf, buffer->line_len, buffer->line_eol, buffer->line_bol, ret);
        !           817: 
        !           818:                freeLineCLI(buffer);
        !           819:                resetHistoryCLI(buffer);
        !           820: 
        !           821:                if (ret == RETCODE_EOF)
        !           822:                        break;
        !           823:        }
        !           824: 
        !           825:        saveHistoryCLI(buffer, NULL, HISTORY_LINES);
        !           826: 
        !           827:        endCLI(buffer);
        !           828:        return 0;
        !           829: }

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