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