1 /*******************************************************************
2 Components for embedded applications builded for
3 laboratory and medical instruments firmware
5 cmd_proc.h - text line command processor
6 designed for instruments control and setup
9 Copyright (C) 2001 by Pavel Pisa pisa@cmp.felk.cvut.cz
10 (C) 2002 by PiKRON Ltd. http://www.pikron.com
11 (C) 2007 by Michal Sojka <sojkam1@fel.cvut.cz>
13 This file can be used and copied according to next
15 - MPL - Mozilla Public License
16 - GPL - GNU Public License
17 - other license provided by project originators
18 *******************************************************************/
21 #include "cmd_proc_priv.h"
25 /* cmd_io line editor */
28 * Adds new characters to an edit line buffer.
30 * @param elb Edit line buffer.
31 * @param ch character to add.
33 * @return 1 in case of end of line, -1 if called at inaproprate time, 0 otherwise.
35 int cmd_ed_line_buf(ed_line_buf_t *elb, int ch)
37 int lastch=elb->lastch;
38 if (elb->flg&FL_ELB_INSEND)
42 elb->inbuf=0; /* Start new line */
44 if(ch == '\b') { /* backspace */
49 if((!(elb->flg&FL_ELB_NOCRLF))&&((ch=='\n')||(ch=='\r'))){
50 if((lastch=='\n')&&(ch=='\r')) /* Empty line, ignore it. */
52 elb->lastch=0; /* End the string */
53 elb->buf[elb->inbuf]=0;
56 if(elb->inbuf>=elb->alloc-1){
57 /* try to reallocate buffer len not implemented */
60 elb->buf[elb->inbuf++]=ch;
64 int cmd_io_line_putc(cmd_io_t *cmd_io,int ch)
66 return cmd_ed_line_buf(cmd_io->priv.ed_line.out,ch);
69 /* Process pending output */
70 int cmd_io_line_out(cmd_io_t *cmd_io)
72 cmd_io_t* io_stack=cmd_io->priv.ed_line.io_stack;
73 ed_line_buf_t* ed_line_out=cmd_io->priv.ed_line.out;
75 if(!ed_line_out->inbuf) return 0;
79 if(!(ed_line_out->flg&FL_ELB_INSEND)){
80 ed_line_out->flg|=FL_ELB_INSEND;
81 ed_line_out->lastch=0;
83 while(cmd_io_putc(io_stack, ed_line_out->buf[ed_line_out->lastch])>=0){
84 if(++ed_line_out->lastch >= ed_line_out->inbuf){
85 ed_line_out->lastch=0;
87 ed_line_out->flg&=~FL_ELB_INSEND;
94 static void replace_history(ed_line_buf_t *el, cmd_io_t* io_stack)
97 el->inbuf=0; /* Make inbuf consistent */
98 while (el->inbuf) { /* Delete previous input */
100 while (cmd_io_putc(io_stack,'\b') < 0);
102 if (el->hist_idx >= 0) {
103 strncpy(el->buf, el->hist + el->hist_idx*el->alloc, el->alloc);
104 while (el->buf[el->inbuf]) {
105 el->lastch = el->buf[el->inbuf++];
106 while (cmd_io_putc(io_stack, el->lastch) < 0);
109 cmd_io_puts(io_stack, "\033[K"); /* Erase End of Line */
113 * @return One when the character was consumed, zero otherwise.
115 static int handle_history(ed_line_buf_t *el, char ch, cmd_io_t* io_stack)
117 enum { NONE, UP, DOWN } dir = NONE;
119 if (!(el->hist && el->hist_size && el->hist_size >= 2*el->alloc))
123 case 14: /* Ctrl-N */
126 case 16: /* Ctrl-P */
129 case '\033': /* ESC */
130 strcpy(el->esc, "\033");
137 while (*p && p < el->esc + sizeof(el->esc) - 2) p++;
143 if (strcmp(el->esc, "\033[A") == 0) dir = UP;
144 else if (strcmp(el->esc, "\033[B") == 0) dir = DOWN;
152 if (el->hist_idx >= 0)
156 } else if (dir == UP) {
157 if ((el->hist_idx+2) * el->alloc <= el->hist_size &&
158 el->hist[(el->hist_idx+1) * el->alloc])
164 replace_history(el, io_stack);
168 /* process input & perform echo if requested */
169 int cmd_io_line_in(cmd_io_t *cmd_io)
172 cmd_io_t* io_stack = cmd_io->priv.ed_line.io_stack;
173 ed_line_buf_t *el = cmd_io->priv.ed_line.in;
178 while((ch=cmd_io_getc(io_stack))>=0){
179 // DPRINT("Added %c (%d)\n", ch, ch);
180 if (handle_history(el, ch, io_stack) == 1)
182 int eol = cmd_ed_line_buf(el,ch);
186 if(el->flg&FL_ELB_ECHO){
187 while(cmd_io_putc(io_stack,'\r')<0);
188 while(cmd_io_putc(io_stack,'\n')<0);
190 if (el->hist && el->hist_size) {
192 if ((el->hist[0] && strcmp(el->buf, el->hist) == 0) || /* The same command as before */
193 !el->buf[0]) /* Empty line */
194 return 1; /* Don't add to the history */
195 memmove(el->hist + el->alloc, el->hist, el->hist_size - el->alloc);
196 strncpy(el->hist, el->buf, el->alloc);
201 if(el->flg&FL_ELB_ECHO) {
202 while(cmd_io_putc(io_stack,ch)<0);
204 cmd_io_puts(io_stack, "\033[K"); /* Erase End of Line */
210 /* The possibly blocking read of one line, should be used only
211 when other options fails */
212 char *cmd_io_line_rdline(cmd_io_t *cmd_io, int mode)
215 while((ret=cmd_io_line_in(cmd_io))==0)
217 if(ret<=0) return NULL;
218 return cmd_io->priv.ed_line.in->buf;
221 /* Local Variables: */
222 /* c-basic-offset: 2 */