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