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