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

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>
1.1.2.3   misho       8: #include <sys/types.h>
1.1.2.1   misho       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: 
1.1.2.2   misho      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: 
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.3   misho      73:        unsigned char b[BUFSIZ];
1.1.2.1   misho      74: 
                     75:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
                     76:                return RETCODE_ERR;
                     77: 
1.1.2.2   misho      78:        pos = buf->line_eol - buf->line_bol;
                     79: 
1.1.2.3   misho      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)
1.1.2.1   misho      84:                buf->line_len += buf->line_keys[idx].key_len;
1.1.2.2   misho      85:        buf->line_eol += buf->line_keys[idx].key_len;
1.1.2.1   misho      86: 
1.1.2.2   misho      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;
1.1.2.1   misho      89: 
                     90:        write(buf->line_out, buf->line_keys[idx].key_ch, buf->line_keys[idx].key_len);
1.1.2.3   misho      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:        }
1.1.2.1   misho      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: 
1.1.2.2   misho     106:        printfCR(buffer, 1);
1.1.2.1   misho     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;
1.1.2.2   misho     140:        int pos;
1.1.2.1   misho     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: 
1.1.2.2   misho     152:        clrscrEOL(buf);
                    153:        freeLineCLI(buf);
1.1.2.1   misho     154: 
1.1.2.2   misho     155:        pos = buf->line_eol - buf->line_bol;
1.1.2.1   misho     156: 
1.1.2.2   misho     157:        buf->line_len += buf->line_h->hist_len;
1.1.2.1   misho     158:        buf->line_eol += buf->line_h->hist_len;
                    159: 
1.1.2.2   misho     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;
1.1.2.1   misho     162: 
1.1.2.2   misho     163:        printfEOL(buf, -1, 1);
1.1.2.1   misho     164:        return RETCODE_OK;
                    165: }
                    166: 
                    167: static int
                    168: bufDOWN(int idx, void * __restrict buffer)
                    169: {
                    170:        linebuffer_t *buf = buffer;
1.1.2.2   misho     171:        int pos;
1.1.2.1   misho     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: 
1.1.2.2   misho     183:        clrscrEOL(buf);
                    184:        freeLineCLI(buf);
1.1.2.1   misho     185: 
1.1.2.2   misho     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);
1.1.2.1   misho     205:        freeLineCLI(buffer);
1.1.2.2   misho     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)
1.1.2.1   misho     217:                return RETCODE_ERR;
                    218: 
1.1.2.2   misho     219:        if (buf->line_bol < buf->line_eol) {
                    220:                clrscrEOL(buf);
1.1.2.1   misho     221: 
1.1.2.2   misho     222:                buf->line_eol--;
                    223:                buf->line_len--;
1.1.2.4 ! misho     224:                memmove(buf->line_buf + buf->line_eol - buf->line_bol, 
        !           225:                                buf->line_buf + buf->line_eol - buf->line_bol + 1, 
1.1.2.3   misho     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: 
1.1.2.4 ! misho     247:                buf->line_len = buf->line_eol - buf->line_bol + 1;
        !           248:                buf->line_buf[buf->line_len - 1] = 0;
1.1.2.1   misho     249: 
1.1.2.2   misho     250:                printfEOL(buf, -1, 1);
                    251:        }
1.1.2.1   misho     252: 
                    253:        return RETCODE_OK;
                    254: }
                    255: 
                    256: static int
1.1.2.2   misho     257: bufMode(int idx, void * __restrict buffer)
1.1.2.1   misho     258: {
                    259:        linebuffer_t *buf = buffer;
                    260: 
                    261:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
                    262:                return RETCODE_ERR;
                    263: 
1.1.2.2   misho     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;
1.1.2.1   misho     277: 
1.1.2.2   misho     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: 
1.1.2.3   misho     332:        clrscrEOL(buf);
1.1.2.2   misho     333: 
1.1.2.3   misho     334:        buf->line_len--;
1.1.2.4 ! misho     335:        memmove(buf->line_buf + buf->line_eol - buf->line_bol, 
        !           336:                        buf->line_buf + buf->line_eol - buf->line_bol + 1, 
1.1.2.3   misho     337:                        buf->line_len - buf->line_eol);
                    338:        buf->line_buf[buf->line_len - 1] = 0;
1.1.2.2   misho     339: 
1.1.2.3   misho     340:        printfEOL(buf, buf->line_len - 1, 1);
                    341:        printfEOL(buf, -1, 1);
1.1.2.1   misho     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 *
1.1.2.2   misho     366: initCLI(int fin, int fout, const char *prompt)
1.1.2.1   misho     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);
1.1.2.2   misho     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:                }
1.1.2.1   misho     396:        }
1.1.2.2   misho     397:        buffer->line_buf = malloc(BUFSIZ);
1.1.2.1   misho     398:        if (!buffer->line_buf) {
1.1.2.2   misho     399:                if (buffer->line_prompt)
                    400:                        free(buffer->line_prompt);
1.1.2.1   misho     401:                free(buffer);
                    402:                return NULL;
                    403:        } else {
1.1.2.2   misho     404:                memset(buffer->line_buf, 0, BUFSIZ);
                    405:                buffer->line_len = 1 + buffer->line_eol;
1.1.2.1   misho     406:        }
                    407:        keys = calloc(MAX_BINDKEY + 1, sizeof(bindkey_t));
                    408:        if (!keys) {
1.1.2.2   misho     409:                if (buffer->line_prompt)
                    410:                        free(buffer->line_prompt);
1.1.2.1   misho     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;
1.1.2.2   misho     427:                if (i == *K_CTRL_H || i == *K_BACKSPACE)
                    428:                        keys[i].key_func = bufBS;
1.1.2.1   misho     429:                if (i == *K_CTRL_C)
                    430:                        keys[i].key_func = bufClr;
1.1.2.2   misho     431:                if (i == *K_CTRL_A)
                    432:                        keys[i].key_func = bufBegin;
                    433:                if (i == *K_CTRL_E)
                    434:                        keys[i].key_func = bufEnd;
1.1.2.1   misho     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;
1.1.2.2   misho     505:        keys[i].key_func = bufBegin;
1.1.2.1   misho     506:        memcpy(keys[i].key_ch, K_HOME, keys[i++].key_len);
                    507:        keys[i].key_len = sizeof K_END - 1;
1.1.2.2   misho     508:        keys[i].key_func = bufEnd;
1.1.2.1   misho     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;
1.1.2.2   misho     517:        keys[i].key_func = bufRIGHT;
1.1.2.1   misho     518:        memcpy(keys[i].key_ch, K_RIGHT, keys[i++].key_len);
                    519:        keys[i].key_len = sizeof K_LEFT - 1;
1.1.2.2   misho     520:        keys[i].key_func = bufLEFT;
1.1.2.1   misho     521:        memcpy(keys[i].key_ch, K_LEFT, keys[i++].key_len);
                    522:        keys[i].key_len = sizeof K_BTAB - 1;
1.1.2.3   misho     523:        keys[i].key_func = bufBTAB;
1.1.2.1   misho     524:        memcpy(keys[i].key_ch, K_BTAB, keys[i++].key_len);
                    525:        // 4 bytes
                    526:        keys[i].key_len = sizeof K_INS - 1;
1.1.2.2   misho     527:        keys[i].key_func = bufMode;
1.1.2.1   misho     528:        memcpy(keys[i].key_ch, K_INS, keys[i++].key_len);
                    529:        keys[i].key_len = sizeof K_DEL - 1;
1.1.2.2   misho     530:        keys[i].key_func = bufDel;
1.1.2.1   misho     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: 
1.1.2.2   misho     576:                if (buffer->line_prompt)
                    577:                        free(buffer->line_prompt);
                    578: 
1.1.2.1   misho     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: 
1.1.2.2   misho     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: 
1.1.2.1   misho     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: 
1.1.2.2   misho     619:                buffer->line_buf = malloc(BUFSIZ);
1.1.2.1   misho     620:                if (buffer->line_buf) {
1.1.2.2   misho     621:                        memset(buffer->line_buf, 0, BUFSIZ);
                    622:                        buffer->line_eol = buffer->line_bol;
                    623:                        buffer->line_len = 1 + buffer->line_eol;
1.1.2.1   misho     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: 
1.1.2.2   misho     647:        printfCR(buffer, 1);
1.1.2.1   misho     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
1.1.2.2   misho     724: saveHistoryCLI(linebuffer_t * __restrict buffer, const char *histfile, int lines)
1.1.2.1   misho     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;
1.1.2.2   misho     742:        TAILQ_FOREACH(h, &buffer->line_history, hist_next) {
1.1.2.1   misho     743:                fprintf(f, "%s\n", h->hist_line);
1.1.2.2   misho     744: 
                    745:                if (lines)
                    746:                        lines--;
                    747:                else
                    748:                        break;
                    749:        }
1.1.2.1   misho     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: 
1.1.2.2   misho     799: // ------------------------------------------------------------
1.1.2.1   misho     800: 
                    801: int
                    802: main()
                    803: {
                    804:        int ret;
                    805:        bindkey_t key = { sizeof K_TAB - 1, K_TAB, bufTab };
1.1.2.4 ! misho     806:        linebuffer_t *buffer = initCLI(STDIN_FILENO, STDOUT_FILENO, CLI_PROMPT);
1.1.2.1   misho     807: 
                    808:        bindKeyCLI(&key, buffer);
                    809: 
                    810:        loadHistoryCLI(buffer, NULL);
                    811: 
                    812:        while (42) {
                    813:                ret = readLineCLI(buffer);
                    814:                addHistoryCLI(buffer, NULL);
                    815: 
1.1.2.2   misho     816:                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     817: 
                    818:                freeLineCLI(buffer);
                    819:                resetHistoryCLI(buffer);
                    820: 
                    821:                if (ret == RETCODE_EOF)
                    822:                        break;
                    823:        }
                    824: 
1.1.2.2   misho     825:        saveHistoryCLI(buffer, NULL, HISTORY_LINES);
1.1.2.1   misho     826: 
                    827:        endCLI(buffer);
                    828:        return 0;
                    829: }

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