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>