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

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

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