File:  [ELWIX - Embedded LightWeight unIX -] / libaitcli / example / t.c
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Wed Mar 16 17:24:03 2011 UTC (13 years, 3 months ago) by misho
Branches: MAIN
CVS tags: cli4_6, cli4_5, cli4_4, cli4_3, cli4_2, cli4_1, cli4_0, cli3_9, cli3_8, cli3_7, cli3_6, cli3_5, cli3_4, cli3_3, cli3_2, cli3_1, cli3_0, cli2_3, cli2_2, cli2_1, HEAD, CLI4_5, CLI4_4, CLI4_3, CLI4_2, CLI4_1, CLI4_0, CLI3_9, CLI3_8, CLI3_7, CLI3_6, CLI3_5, CLI3_4, CLI3_3, CLI3_2, CLI3_1, CLI3_0, CLI2_3, CLI2_2, CLI2_1, CLI2_0
2.0

    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>