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

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.3 ! misho     224:                memmove(buf->line_buf + buf->line_eol, buf->line_buf + buf->line_eol + 1, 
        !           225:                                buf->line_len - buf->line_eol);
        !           226:                buf->line_buf[buf->line_len - 1] = 0;
        !           227: 
        !           228:                printfEOL(buf, buf->line_len - 1, 1);
        !           229:                printfEOL(buf, -1, 1);
        !           230:        }
        !           231: 
        !           232:        return RETCODE_OK;
        !           233: }
        !           234: 
        !           235: static int
        !           236: bufBTAB(int idx, void * __restrict buffer)
        !           237: {
        !           238:        linebuffer_t *buf = buffer;
        !           239: 
        !           240:        if (!buffer || idx < 0 || idx > MAX_BINDKEY)
        !           241:                return RETCODE_ERR;
        !           242: 
        !           243:        if (buf->line_bol < buf->line_eol) {
        !           244:                clrscrEOL(buf);
        !           245: 
        !           246:                buf->line_eol--;
        !           247:                buf->line_len--;
1.1.2.2   misho     248:                buf->line_buf[buf->line_eol - buf->line_bol] = 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--;
        !           335:        memmove(buf->line_buf + buf->line_eol, buf->line_buf + buf->line_eol + 1, 
        !           336:                        buf->line_len - buf->line_eol);
        !           337:        buf->line_buf[buf->line_len - 1] = 0;
1.1.2.2   misho     338: 
1.1.2.3 ! misho     339:        printfEOL(buf, buf->line_len - 1, 1);
        !           340:        printfEOL(buf, -1, 1);
1.1.2.1   misho     341: 
                    342:        return RETCODE_OK;
                    343: }
                    344: 
                    345: // ---------------------------------------------------------------
                    346: 
                    347: int
                    348: bindKeyCLI(bindkey_t * __restrict key, linebuffer_t * __restrict buffer)
                    349: {
                    350:        register int i;
                    351: 
                    352:        if (!key || !buffer)
                    353:                return RETCODE_ERR;
                    354: 
                    355:        for (i = 0; i < MAX_BINDKEY; i++)
                    356:                if (key->key_len == buffer->line_keys[i].key_len && 
                    357:                                !memcmp(key->key_ch, buffer->line_keys[i].key_ch, key->key_len)) {
                    358:                        buffer->line_keys[i].key_func = key->key_func;
                    359:                        return i;
                    360:                }
                    361:        return RETCODE_OK;
                    362: }
                    363: 
                    364: linebuffer_t *
1.1.2.2   misho     365: initCLI(int fin, int fout, const char *prompt)
1.1.2.1   misho     366: {
                    367:        linebuffer_t *buffer;
                    368:        bindkey_t *keys;
                    369:        register int i;
                    370:        struct termios t;
                    371: 
                    372:        memset(&t, 0, sizeof t);
                    373:        /* init buffer */
                    374:        buffer = malloc(sizeof (linebuffer_t));
                    375:        if (!buffer)
                    376:                return NULL;
                    377:        else {
                    378:                memset(buffer, 0, sizeof(linebuffer_t));
                    379: 
                    380:                buffer->line_in = fin;
                    381:                buffer->line_out = fout;
                    382: 
                    383:                TAILQ_INIT(&buffer->line_history);
1.1.2.2   misho     384: 
                    385:                if (prompt) {
                    386:                        buffer->line_prompt = strdup(prompt);
                    387:                        if (!buffer->line_prompt) {
                    388:                                free(buffer);
                    389:                                return NULL;
                    390:                        } else {
                    391:                                buffer->line_bol = strlen(buffer->line_prompt);
                    392:                                buffer->line_eol = buffer->line_bol;
                    393:                        }
                    394:                }
1.1.2.1   misho     395:        }
1.1.2.2   misho     396:        buffer->line_buf = malloc(BUFSIZ);
1.1.2.1   misho     397:        if (!buffer->line_buf) {
1.1.2.2   misho     398:                if (buffer->line_prompt)
                    399:                        free(buffer->line_prompt);
1.1.2.1   misho     400:                free(buffer);
                    401:                return NULL;
                    402:        } else {
1.1.2.2   misho     403:                memset(buffer->line_buf, 0, BUFSIZ);
                    404:                buffer->line_len = 1 + buffer->line_eol;
1.1.2.1   misho     405:        }
                    406:        keys = calloc(MAX_BINDKEY + 1, sizeof(bindkey_t));
                    407:        if (!keys) {
1.1.2.2   misho     408:                if (buffer->line_prompt)
                    409:                        free(buffer->line_prompt);
1.1.2.1   misho     410:                free(buffer->line_buf);
                    411:                free(buffer);
                    412:                return NULL;
                    413:        } else
                    414:                memset(keys, 0, sizeof(bindkey_t) * (MAX_BINDKEY + 1));
                    415: 
                    416:        /* fill key bindings */
                    417:        // ascii chars & ctrl+chars
                    418:        for (i = 0; i < 256; i++) {
                    419:                *keys[i].key_ch = (unsigned char) i;
                    420:                keys[i].key_len = 1;
                    421: 
                    422:                if (!i || i == *K_CTRL_D)
                    423:                        keys[i].key_func = bufEOF;
                    424:                if (i == *K_CTRL_M || i == *K_CTRL_J)
                    425:                        keys[i].key_func = bufEOL;
1.1.2.2   misho     426:                if (i == *K_CTRL_H || i == *K_BACKSPACE)
                    427:                        keys[i].key_func = bufBS;
1.1.2.1   misho     428:                if (i == *K_CTRL_C)
                    429:                        keys[i].key_func = bufClr;
1.1.2.2   misho     430:                if (i == *K_CTRL_A)
                    431:                        keys[i].key_func = bufBegin;
                    432:                if (i == *K_CTRL_E)
                    433:                        keys[i].key_func = bufEnd;
1.1.2.1   misho     434:                if (i >= *K_SPACE && i < *K_BACKSPACE)
                    435:                        keys[i].key_func = catCh2Buf;
                    436:                if (i > *K_BACKSPACE && i < 0xff)
                    437:                        keys[i].key_func = catCh2Buf;
                    438:        }
                    439:        // alt+chars
                    440:        for (i = 256; i < 512; i++) {
                    441:                keys[i].key_ch[0] = 0x1b;
                    442:                keys[i].key_ch[1] = (unsigned char) i - 256;
                    443:                keys[i].key_len = 2;
                    444:        }
                    445: 
                    446:        // 3 bytes
                    447:        keys[i].key_len = sizeof K_F1 - 1;
                    448:        memcpy(keys[i].key_ch, K_F1, keys[i++].key_len);
                    449:        keys[i].key_len = sizeof K_F2 - 1;
                    450:        memcpy(keys[i].key_ch, K_F2, keys[i++].key_len);
                    451:        keys[i].key_len = sizeof K_F3 - 1;
                    452:        memcpy(keys[i].key_ch, K_F3, keys[i++].key_len);
                    453:        keys[i].key_len = sizeof K_F4 - 1;
                    454:        memcpy(keys[i].key_ch, K_F4, keys[i++].key_len);
                    455:        keys[i].key_len = sizeof K_CTRL_SH_F1 - 1;
                    456:        memcpy(keys[i].key_ch, K_CTRL_SH_F1, keys[i++].key_len);
                    457:        keys[i].key_len = sizeof K_CTRL_SH_F2 - 1;
                    458:        memcpy(keys[i].key_ch, K_CTRL_SH_F2, keys[i++].key_len);
                    459:        keys[i].key_len = sizeof K_CTRL_SH_F3 - 1;
                    460:        memcpy(keys[i].key_ch, K_CTRL_SH_F3, keys[i++].key_len);
                    461:        keys[i].key_len = sizeof K_CTRL_SH_F4 - 1;
                    462:        memcpy(keys[i].key_ch, K_CTRL_SH_F4, keys[i++].key_len);
                    463:        keys[i].key_len = sizeof K_CTRL_SH_F5 - 1;
                    464:        memcpy(keys[i].key_ch, K_CTRL_SH_F5, keys[i++].key_len);
                    465:        keys[i].key_len = sizeof K_CTRL_SH_F6 - 1;
                    466:        memcpy(keys[i].key_ch, K_CTRL_SH_F6, keys[i++].key_len);
                    467:        keys[i].key_len = sizeof K_CTRL_SH_F7 - 1;
                    468:        memcpy(keys[i].key_ch, K_CTRL_SH_F7, keys[i++].key_len);
                    469:        keys[i].key_len = sizeof K_CTRL_SH_F8 - 1;
                    470:        memcpy(keys[i].key_ch, K_CTRL_SH_F8, keys[i++].key_len);
                    471:        keys[i].key_len = sizeof K_CTRL_SH_F9 - 1;
                    472:        memcpy(keys[i].key_ch, K_CTRL_SH_F9, keys[i++].key_len);
                    473:        keys[i].key_len = sizeof K_CTRL_SH_F10 - 1;
                    474:        memcpy(keys[i].key_ch, K_CTRL_SH_F10, keys[i++].key_len);
                    475:        keys[i].key_len = sizeof K_CTRL_SH_F11 - 1;
                    476:        memcpy(keys[i].key_ch, K_CTRL_SH_F11, keys[i++].key_len);
                    477:        keys[i].key_len = sizeof K_CTRL_SH_F12 - 1;
                    478:        memcpy(keys[i].key_ch, K_CTRL_SH_F12, keys[i++].key_len);
                    479:        keys[i].key_len = sizeof K_CTRL_F1 - 1;
                    480:        memcpy(keys[i].key_ch, K_CTRL_F1, keys[i++].key_len);
                    481:        keys[i].key_len = sizeof K_CTRL_F2 - 1;
                    482:        memcpy(keys[i].key_ch, K_CTRL_F2, keys[i++].key_len);
                    483:        keys[i].key_len = sizeof K_CTRL_F3 - 1;
                    484:        memcpy(keys[i].key_ch, K_CTRL_F3, keys[i++].key_len);
                    485:        keys[i].key_len = sizeof K_CTRL_F4 - 1;
                    486:        memcpy(keys[i].key_ch, K_CTRL_F4, keys[i++].key_len);
                    487:        keys[i].key_len = sizeof K_CTRL_F5 - 1;
                    488:        memcpy(keys[i].key_ch, K_CTRL_F5, keys[i++].key_len);
                    489:        keys[i].key_len = sizeof K_CTRL_F6 - 1;
                    490:        memcpy(keys[i].key_ch, K_CTRL_F6, keys[i++].key_len);
                    491:        keys[i].key_len = sizeof K_CTRL_F7 - 1;
                    492:        memcpy(keys[i].key_ch, K_CTRL_F7, keys[i++].key_len);
                    493:        keys[i].key_len = sizeof K_CTRL_F8 - 1;
                    494:        memcpy(keys[i].key_ch, K_CTRL_F8, keys[i++].key_len);
                    495:        keys[i].key_len = sizeof K_CTRL_F9 - 1;
                    496:        memcpy(keys[i].key_ch, K_CTRL_F9, keys[i++].key_len);
                    497:        keys[i].key_len = sizeof K_CTRL_F10 - 1;
                    498:        memcpy(keys[i].key_ch, K_CTRL_F10, keys[i++].key_len);
                    499:        keys[i].key_len = sizeof K_CTRL_F11 - 1;
                    500:        memcpy(keys[i].key_ch, K_CTRL_F11, keys[i++].key_len);
                    501:        keys[i].key_len = sizeof K_CTRL_F12 - 1;
                    502:        memcpy(keys[i].key_ch, K_CTRL_F12, keys[i++].key_len);
                    503:        keys[i].key_len = sizeof K_HOME - 1;
1.1.2.2   misho     504:        keys[i].key_func = bufBegin;
1.1.2.1   misho     505:        memcpy(keys[i].key_ch, K_HOME, keys[i++].key_len);
                    506:        keys[i].key_len = sizeof K_END - 1;
1.1.2.2   misho     507:        keys[i].key_func = bufEnd;
1.1.2.1   misho     508:        memcpy(keys[i].key_ch, K_END, keys[i++].key_len);
                    509:        keys[i].key_len = sizeof K_UP - 1;
                    510:        keys[i].key_func = bufUP;
                    511:        memcpy(keys[i].key_ch, K_UP, keys[i++].key_len);
                    512:        keys[i].key_len = sizeof K_DOWN - 1;
                    513:        keys[i].key_func = bufDOWN;
                    514:        memcpy(keys[i].key_ch, K_DOWN, keys[i++].key_len);
                    515:        keys[i].key_len = sizeof K_RIGHT - 1;
1.1.2.2   misho     516:        keys[i].key_func = bufRIGHT;
1.1.2.1   misho     517:        memcpy(keys[i].key_ch, K_RIGHT, keys[i++].key_len);
                    518:        keys[i].key_len = sizeof K_LEFT - 1;
1.1.2.2   misho     519:        keys[i].key_func = bufLEFT;
1.1.2.1   misho     520:        memcpy(keys[i].key_ch, K_LEFT, keys[i++].key_len);
                    521:        keys[i].key_len = sizeof K_BTAB - 1;
1.1.2.3 ! misho     522:        keys[i].key_func = bufBTAB;
1.1.2.1   misho     523:        memcpy(keys[i].key_ch, K_BTAB, keys[i++].key_len);
                    524:        // 4 bytes
                    525:        keys[i].key_len = sizeof K_INS - 1;
1.1.2.2   misho     526:        keys[i].key_func = bufMode;
1.1.2.1   misho     527:        memcpy(keys[i].key_ch, K_INS, keys[i++].key_len);
                    528:        keys[i].key_len = sizeof K_DEL - 1;
1.1.2.2   misho     529:        keys[i].key_func = bufDel;
1.1.2.1   misho     530:        memcpy(keys[i].key_ch, K_DEL, keys[i++].key_len);
                    531:        keys[i].key_len = sizeof K_PGUP - 1;
                    532:        memcpy(keys[i].key_ch, K_PGUP, keys[i++].key_len);
                    533:        keys[i].key_len = sizeof K_PGDN - 1;
                    534:        memcpy(keys[i].key_ch, K_PGDN, keys[i++].key_len);
                    535:        // 5 bytes
                    536:        keys[i].key_len = sizeof K_F5 - 1;
                    537:        memcpy(keys[i].key_ch, K_F5, keys[i++].key_len);
                    538:        keys[i].key_len = sizeof K_F6 - 1;
                    539:        memcpy(keys[i].key_ch, K_F6, keys[i++].key_len);
                    540:        keys[i].key_len = sizeof K_F7 - 1;
                    541:        memcpy(keys[i].key_ch, K_F7, keys[i++].key_len);
                    542:        keys[i].key_len = sizeof K_F8 - 1;
                    543:        memcpy(keys[i].key_ch, K_F8, keys[i++].key_len);
                    544:        keys[i].key_len = sizeof K_F9 - 1;
                    545:        memcpy(keys[i].key_ch, K_F9, keys[i++].key_len);
                    546:        keys[i].key_len = sizeof K_F10 - 1;
                    547:        memcpy(keys[i].key_ch, K_F10, keys[i++].key_len);
                    548:        keys[i].key_len = sizeof K_F11 - 1;
                    549:        memcpy(keys[i].key_ch, K_F11, keys[i++].key_len);
                    550:        keys[i].key_len = sizeof K_F12 - 1;
                    551:        memcpy(keys[i].key_ch, K_F12, keys[i++].key_len);
                    552: 
                    553:        tcgetattr(buffer->line_in, &t);
                    554:        t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);
                    555:        t.c_iflag |= IGNBRK;
                    556:        t.c_cc[VMIN] = 1;
                    557:        t.c_cc[VTIME] = 0;
                    558:        tcsetattr(buffer->line_in, TCSANOW, &t);
                    559: 
                    560:        buffer->line_keys = keys;
                    561:        return buffer;
                    562: }
                    563: 
                    564: void
                    565: endCLI(linebuffer_t * __restrict buffer)
                    566: {
                    567:        struct tagHistory *h;
                    568: 
                    569:        if (buffer) {
                    570:                while ((h = TAILQ_FIRST(&buffer->line_history))) {
                    571:                        TAILQ_REMOVE(&buffer->line_history, h, hist_next);
                    572:                        free(h);
                    573:                }
                    574: 
1.1.2.2   misho     575:                if (buffer->line_prompt)
                    576:                        free(buffer->line_prompt);
                    577: 
1.1.2.1   misho     578:                if (buffer->line_keys)
                    579:                        free(buffer->line_keys);
                    580:                if (buffer->line_buf)
                    581:                        free(buffer->line_buf);
                    582: 
                    583:                free(buffer);
                    584:                buffer = NULL;
                    585:        }
                    586: }
                    587: 
1.1.2.2   misho     588: void
                    589: setPromptCLI(linebuffer_t * __restrict buffer, const char *prompt)
                    590: {
                    591:        if (buffer) {
                    592:                if (buffer->line_prompt) {
                    593:                        free(buffer->line_prompt);
                    594:                        buffer->line_prompt = NULL;
                    595:                        buffer->line_bol = 0;
                    596:                }
                    597: 
                    598:                if (prompt) {
                    599:                        buffer->line_prompt = strdup(prompt);
                    600:                        if (buffer->line_prompt) {
                    601:                                buffer->line_bol = strlen(buffer->line_prompt);
                    602:                                buffer->line_eol = buffer->line_bol;
                    603:                                buffer->line_len = 1 + buffer->line_eol;
                    604:                        }
                    605:                }
                    606:        }
                    607: }
                    608: 
1.1.2.1   misho     609: int
                    610: freeLineCLI(linebuffer_t * __restrict buffer)
                    611: {
                    612:        int code = RETCODE_ERR;
                    613: 
                    614:        if (buffer) {
                    615:                if (buffer->line_buf)
                    616:                        free(buffer->line_buf);
                    617: 
1.1.2.2   misho     618:                buffer->line_buf = malloc(BUFSIZ);
1.1.2.1   misho     619:                if (buffer->line_buf) {
1.1.2.2   misho     620:                        memset(buffer->line_buf, 0, BUFSIZ);
                    621:                        buffer->line_eol = buffer->line_bol;
                    622:                        buffer->line_len = 1 + buffer->line_eol;
1.1.2.1   misho     623: 
                    624:                        code = RETCODE_OK;
                    625:                }
                    626:        }
                    627: 
                    628:        return code;
                    629: }
                    630: 
                    631: int
                    632: readLineCLI(linebuffer_t * __restrict buffer)
                    633: {
                    634:        int code, readLen;
                    635:        register int i;
                    636:        char buf[BUFSIZ];
                    637:        struct pollfd fds;
                    638: 
                    639:        if (!buffer)
                    640:                return RETCODE_ERR;
                    641: 
                    642:        memset(&fds, 0, sizeof fds);
                    643:        fds.fd = buffer->line_in;
                    644:        fds.events = POLLIN;
                    645: 
1.1.2.2   misho     646:        printfCR(buffer, 1);
1.1.2.1   misho     647:        while (42) {
                    648:                if (poll(&fds, 1, -1) < 1)
                    649:                        return RETCODE_ERR;
                    650: 
                    651:                memset(buf, 0, sizeof buf);
                    652:                readLen = read(buffer->line_in, buf, BUFSIZ);
                    653:                if (readLen == -1)
                    654:                        return RETCODE_ERR;
                    655:                if (!readLen)
                    656:                        return RETCODE_EOF;
                    657: 
                    658: recheck:
                    659: //             for (i = 0; i < readLen; i++)
                    660: //                     printf("i=%d readLen=%d buf=%x\n", i, readLen, (u_char) buf[i]);
                    661:                for (code = RETCODE_OK, i = MAX_BINDKEY - 1; i > -1; i--)
                    662:                        if (readLen >= buffer->line_keys[i].key_len && 
                    663:                                        !memcmp(buffer->line_keys[i].key_ch, buf, buffer->line_keys[i].key_len)) {
                    664:                                readLen -= buffer->line_keys[i].key_len;
                    665:                                if (readLen)
                    666:                                        memmove(buf, buf + buffer->line_keys[i].key_len, readLen);
                    667:                                else
                    668:                                        memset(buf, 0, buffer->line_keys[i].key_len);
                    669: 
                    670:                                if (buffer->line_keys[i].key_func)
                    671:                                        if ((code = buffer->line_keys[i].key_func(i, buffer)))
                    672:                                                readLen = 0;
                    673: 
                    674:                                if (readLen)
                    675:                                        goto recheck;
                    676:                                else
                    677:                                        break;
                    678:                        }
                    679: 
                    680:                if (code)
                    681:                        break;
                    682:        }
                    683: 
                    684:        return code;
                    685: }
                    686: 
                    687: int
                    688: addHistoryCLI(linebuffer_t * __restrict buffer, const char * __restrict str)
                    689: {
                    690:        struct tagHistory *h;
                    691: 
                    692:        if (!buffer)
                    693:                return RETCODE_ERR;
                    694: 
                    695:        if (!(h = malloc(sizeof(struct tagHistory)))) {
                    696:                return RETCODE_ERR;
                    697:        } else
                    698:                memset(h, 0, sizeof(struct tagHistory));
                    699: 
                    700:        if (str) {
                    701:                if (!*str) {
                    702:                        free(h);
                    703:                        return RETCODE_OK;
                    704:                }
                    705: 
                    706:                h->hist_len = strlcpy(h->hist_line, str, BUFSIZ);
                    707:        } else {
                    708:                if (!*buffer->line_buf || buffer->line_len < 2) {
                    709:                        free(h);
                    710:                        return RETCODE_OK;
                    711:                }
                    712: 
                    713:                memcpy(h->hist_line, buffer->line_buf, (h->hist_len = buffer->line_len));
                    714:                io_TrimStr((unsigned char*) h->hist_line);
                    715:                h->hist_len = strlen(h->hist_line);
                    716:        }
                    717: 
                    718:        TAILQ_INSERT_HEAD(&buffer->line_history, h, hist_next);
                    719:        return h->hist_len;
                    720: }
                    721: 
                    722: int
1.1.2.2   misho     723: saveHistoryCLI(linebuffer_t * __restrict buffer, const char *histfile, int lines)
1.1.2.1   misho     724: {
                    725:        FILE *f;
                    726:        mode_t mode;
                    727:        char szFName[MAXPATHLEN];
                    728:        struct tagHistory *h;
                    729: 
                    730:        if (!buffer)
                    731:                return RETCODE_ERR;
                    732:        if (!histfile)
                    733:                strlcpy(szFName, HISTORY_FILE, MAXPATHLEN);
                    734:        else
                    735:                strlcpy(szFName, histfile, MAXPATHLEN);
                    736: 
                    737:        mode = umask(0177);
                    738:        f = fopen(szFName, "w");
                    739:        if (!f)
                    740:                return RETCODE_ERR;
1.1.2.2   misho     741:        TAILQ_FOREACH(h, &buffer->line_history, hist_next) {
1.1.2.1   misho     742:                fprintf(f, "%s\n", h->hist_line);
1.1.2.2   misho     743: 
                    744:                if (lines)
                    745:                        lines--;
                    746:                else
                    747:                        break;
                    748:        }
1.1.2.1   misho     749:        fclose(f);
                    750:        umask(mode);
                    751: 
                    752:        return RETCODE_OK;
                    753: }
                    754: 
                    755: int
                    756: loadHistoryCLI(linebuffer_t * __restrict buffer, const char *histfile)
                    757: {
                    758:        FILE *f;
                    759:        char szFName[MAXPATHLEN], buf[BUFSIZ];
                    760:        struct tagHistory *h;
                    761: 
                    762:        if (!buffer)
                    763:                return RETCODE_ERR;
                    764:        if (!histfile)
                    765:                strlcpy(szFName, HISTORY_FILE, MAXPATHLEN);
                    766:        else
                    767:                strlcpy(szFName, histfile, MAXPATHLEN);
                    768: 
                    769:        f = fopen(szFName, "r");
                    770:        if (!f)
                    771:                return RETCODE_ERR;
                    772:        while (fgets(buf, BUFSIZ, f)) {
                    773:                if (!*buf || *buf == '#')
                    774:                        continue;
                    775:                else
                    776:                        io_TrimStr((unsigned char*) buf);
                    777: 
                    778:                if (!(h = malloc(sizeof(struct tagHistory)))) {
                    779:                        fclose(f);
                    780:                        return RETCODE_ERR;
                    781:                } else
                    782:                        memset(h, 0, sizeof(struct tagHistory));
                    783: 
                    784:                h->hist_len = strlcpy(h->hist_line, buf, BUFSIZ);
                    785:                TAILQ_INSERT_TAIL(&buffer->line_history, h, hist_next);
                    786:        }
                    787:        fclose(f);
                    788: 
                    789:        return RETCODE_OK;
                    790: }
                    791: 
                    792: inline void
                    793: resetHistoryCLI(linebuffer_t * __restrict buffer)
                    794: {
                    795:        buffer->line_h = NULL;
                    796: }
                    797: 
1.1.2.2   misho     798: // ------------------------------------------------------------
1.1.2.1   misho     799: 
                    800: int
                    801: main()
                    802: {
                    803:        int ret;
                    804:        bindkey_t key = { sizeof K_TAB - 1, K_TAB, bufTab };
1.1.2.2   misho     805:        linebuffer_t *buffer = initCLI(STDIN_FILENO, STDOUT_FILENO, /*CLI_PROMPT*/ NULL);
1.1.2.1   misho     806: 
                    807:        bindKeyCLI(&key, buffer);
                    808: 
                    809:        loadHistoryCLI(buffer, NULL);
                    810: 
                    811:        while (42) {
                    812:                ret = readLineCLI(buffer);
                    813:                addHistoryCLI(buffer, NULL);
                    814: 
1.1.2.2   misho     815:                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     816: 
                    817:                freeLineCLI(buffer);
                    818:                resetHistoryCLI(buffer);
                    819: 
                    820:                if (ret == RETCODE_EOF)
                    821:                        break;
                    822:        }
                    823: 
1.1.2.2   misho     824:        saveHistoryCLI(buffer, NULL, HISTORY_LINES);
1.1.2.1   misho     825: 
                    826:        endCLI(buffer);
                    827:        return 0;
                    828: }

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