1 /* Author: Domen Puncer <domen@cba.si>. License: WTFPL, see file LICENSE */
10 static char history
[HIST_SIZE
][LINE_LEN
+1]; /* circ buf of nul terminated strings should be more effective */
11 static int hist_len
= 0;
12 static int hist_pos
= -1;
14 static char line
[LINE_LEN
+1];
26 K_BACKSPACE2
= '\x7f',
28 /* below are our made up values */
30 K_VT100_START
= 0x100,
52 static const struct vt100_seq vt100_seqs
[] = {
53 { .key
= K_UP
, .seq
= "[A" },
54 { .key
= K_DOWN
, .seq
= "[B" },
55 { .key
= K_RIGHT
, .seq
= "[C" },
56 { .key
= K_LEFT
, .seq
= "[D" },
57 { .key
= K_END
, .seq
= "[F" },
58 { .key
= K_HOME
, .seq
= "[H" },
59 { .key
= K_INSERT
, .seq
= "[2~" },
60 { .key
= K_DELETE
, .seq
= "[3~" },
61 { .key
= K_PGUP
, .seq
= "[5~" },
62 { .key
= K_PGDN
, .seq
= "[6~" },
66 static int vt100_cmp(const char *seq
, int len
, const char *ntseq
)
70 if (seq
[i
] != ntseq
[i
])
77 /* matched, but the sequence wasn't complete */
82 static const char *vt100_seq(enum vt100_key key
)
85 for (i
=0; i
<ALEN(vt100_seqs
); i
++) {
86 if (vt100_seqs
[i
].key
== key
)
87 return vt100_seqs
[i
].seq
;
93 static enum vt100_key
vt100_match(const char *seq
, int len
)
97 for (i
=0; i
<ALEN(vt100_seqs
); i
++) {
99 m
= vt100_cmp(seq
, len
, vt100_seqs
[i
].seq
);
101 return vt100_seqs
[i
].key
;
109 static void cbashell_command(const char *cmd
)
113 for (i
=0; command_list
[i
]; i
++)
114 if (command_list
[i
](cmd
) != 0)
120 * readline like prompt handling
121 * TODO history should be improved with a circ buf for string storage or sth,
122 * to be more effective.
124 static int cbashell_char(int c
)
126 if (hist_pos
>= 0 && !(c
== K_UP
|| c
== K_DOWN
)) {
127 strcpy(line
, history
[hist_pos
]);
131 if (c
>= ' ' && c
< '\x7f') {
132 /* guard against buffer overflow */
136 memmove(&line
[pos
+1], &line
[pos
], len
-pos
);
142 /* string (overwrites), move back x left */
143 printf("%s\x1b[%iD", &line
[pos
-1], len
-pos
);
150 strcpy(line
, history
[0]);
155 if (hist_len
>= HIST_SIZE
)
156 hist_len
= HIST_SIZE
-1;
158 for (i
=hist_len
-1; i
>=0; i
--)
159 strcpy(history
[i
+1], history
[i
]);
160 strcpy(history
[0], line
);
165 cbashell_command(line
);
172 if (c
== K_BACKSPACE
|| c
== K_BACKSPACE2
) {
174 memmove(&line
[pos
-1], &line
[pos
], len
-pos
);
180 /* move left, clear line right, string, move x left */
181 printf("\x1b[D\x1b[K%s\x1b[%iD", &line
[pos
], len
-pos
);
183 printf("\x1b[D\x1b[K");
189 memmove(&line
[pos
], &line
[pos
+1], len
-pos
-1);
194 /* clear line right, string, move x left */
195 printf("\x1b[K%s\x1b[%iD", &line
[pos
], len
-pos
);
206 printf("\x1b[D"); /* left */
212 printf("\x1b[C"); /* right */
217 printf("\x1b[%iD", pos
); /* left x */
223 printf("\x1b[%iC", len
-pos
); /* right x */
228 if (hist_pos
< hist_len
-1) {
231 printf("\x1b[%iD", pos
); /* left x */
232 printf("\x1b[K%s", history
[hist_pos
]); /* clear line right, print history */
233 len
= pos
= strlen(history
[hist_pos
]);
238 const char *newline
= line
;
241 newline
= history
[hist_pos
];
243 printf("\x1b[%iD", pos
); /* left x */
244 printf("\x1b[K%s", newline
); /* clear line right, print history */
245 len
= pos
= strlen(newline
);
250 printf("\x1b[%iD", pos
); /* left x */
251 printf("\x1b[K"); /* clear line right */
255 if (c
>= K_VT100_START
) {
256 /* debugging print */
257 printf("vt100:%i ", c
);
265 /* partial VT100 parsing, see
266 * http://ascii-table.com/ansi-escape-sequences-vt-100.php
268 int cbashell_charraw(int c
)
270 static int inside_esc
;
276 /* just a silly guard */
277 if (esc_pos
== sizeof(esc
))
281 c
= vt100_match(esc
, esc_pos
);
282 if (c
== K_INVALID
) {
285 r
|= cbashell_char('^');
286 r
|= cbashell_char('[');
287 for (i
=0; i
<esc_pos
; i
++)
288 r
|= cbashell_char(esc
[i
]);
297 return cbashell_char(c
);
306 return cbashell_char(c
);