Line data Source code
1 : /********************************************************************\
2 :
3 : Name: cmdedit.c
4 : Created by: Stefan Ritt
5 :
6 : Contents: Command-line editor for msc
7 :
8 : \********************************************************************/
9 :
10 : #include <stdio.h>
11 : #include <string.h>
12 :
13 : #define MAX_HISTORY 50
14 : #define LINE_LENGTH 256
15 :
16 : #define TRUE 1
17 : #define FALSE 0
18 :
19 : char history[MAX_HISTORY][LINE_LENGTH];
20 : int his_index = 0;
21 :
22 : extern int ss_getchar(int reset);
23 : extern char *ss_gets(char *string, int size);
24 : extern unsigned int ss_millitime(void);
25 :
26 : /* special characters */
27 : #define CH_BS 8
28 : #define CH_TAB 9
29 : #define CH_CR 13
30 :
31 : #define CH_EXT 0x100
32 :
33 : #define CH_HOME (CH_EXT+0)
34 : #define CH_INSERT (CH_EXT+1)
35 : #define CH_DELETE (CH_EXT+2)
36 : #define CH_END (CH_EXT+3)
37 : #define CH_PUP (CH_EXT+4)
38 : #define CH_PDOWN (CH_EXT+5)
39 : #define CH_UP (CH_EXT+6)
40 : #define CH_DOWN (CH_EXT+7)
41 : #define CH_RIGHT (CH_EXT+8)
42 : #define CH_LEFT (CH_EXT+9)
43 :
44 : /*------------------------------------------------------------------*/
45 :
46 0 : int cmd_edit(const char *prompt, char *cmd, int(*dir) (char *, int *), int(*idle) (void))
47 : {
48 : char line[LINE_LENGTH];
49 : int i, j, k, c, hi;
50 : int status;
51 0 : unsigned int last_time = 0;
52 0 : int escape_flag = 0;
53 :
54 0 : if (ss_getchar(0) == -1) {
55 : /* normal input if ss_getchar not supported */
56 0 : fputs(prompt, stdout);
57 0 : ss_gets(cmd, 256);
58 0 : return strlen(cmd);
59 : }
60 :
61 0 : fputs(prompt, stdout);
62 0 : fflush(stdout);
63 :
64 0 : hi = his_index;
65 0 : memset(line, 0, LINE_LENGTH);
66 0 : memset(history[hi], 0, LINE_LENGTH);
67 0 : strcpy(line, cmd);
68 0 : fputs(line, stdout);
69 0 : i = strlen(cmd);
70 0 : fflush(stdout);
71 :
72 : do {
73 0 : c = ss_getchar(0);
74 :
75 0 : if (c == 27)
76 0 : escape_flag = TRUE;
77 :
78 0 : if (c >= ' ' && c < CH_EXT && escape_flag) {
79 0 : escape_flag = FALSE;
80 0 : if (c == 'p')
81 0 : c = 6;
82 : }
83 :
84 : /* normal input */
85 0 : if (c >= ' ' && c < CH_EXT) {
86 0 : if (strlen(line) < LINE_LENGTH - 1) {
87 0 : for (j = strlen(line); j >= i; j--)
88 0 : line[j + 1] = line[j];
89 0 : if (i < LINE_LENGTH - 1) {
90 0 : line[i++] = c;
91 0 : fputc(c, stdout);
92 : }
93 0 : for (j = i; j < (int) strlen(line); j++)
94 0 : fputc(line[j], stdout);
95 0 : for (j = i; j < (int) strlen(line); j++)
96 0 : fputc('\b', stdout);
97 : }
98 : }
99 :
100 : /* BS */
101 0 : if (c == CH_BS && i > 0) {
102 0 : i--;
103 0 : fputc('\b', stdout);
104 0 : for (j = i; j <= (int) strlen(line); j++) {
105 0 : line[j] = line[j + 1];
106 0 : if (line[j])
107 0 : fputc(line[j], stdout);
108 : else
109 0 : fputc(' ', stdout);
110 : }
111 0 : for (k = 0; k < j - i; k++)
112 0 : fputc('\b', stdout);
113 : }
114 :
115 : /* DELETE/Ctrl-D */
116 0 : if (c == CH_DELETE || c == 4) {
117 0 : for (j = i; j <= (int) strlen(line); j++) {
118 0 : line[j] = line[j + 1];
119 0 : if (line[j])
120 0 : fputc(line[j], stdout);
121 : else
122 0 : fputc(' ', stdout);
123 : }
124 0 : for (k = 0; k < j - i; k++)
125 0 : fputc('\b', stdout);
126 : }
127 :
128 : /* Erase line: CTRL-W, CTRL-U */
129 0 : if (c == 23 || c == 21) {
130 0 : i = strlen(line);
131 0 : memset(line, 0, sizeof(line));
132 0 : printf("\r%s", prompt);
133 0 : for (j = 0; j < i; j++)
134 0 : fputc(' ', stdout);
135 0 : for (j = 0; j < i; j++)
136 0 : fputc('\b', stdout);
137 0 : i = 0;
138 : }
139 :
140 : /* Erase line from cursor: CTRL-K */
141 0 : if (c == 11) {
142 0 : for (j = i; j < (int) strlen(line); j++)
143 0 : fputc(' ', stdout);
144 0 : for (j = i; j < (int) strlen(line); j++)
145 0 : fputc('\b', stdout);
146 0 : for (j = strlen(line); j >= i; j--)
147 0 : line[j] = 0;
148 : }
149 :
150 : /* left arrow, CTRL-B */
151 0 : if ((c == CH_LEFT || c == 2) && i > 0) {
152 0 : i--;
153 0 : fputc('\b', stdout);
154 : }
155 :
156 : /* right arrow, CTRL-F */
157 0 : if ((c == CH_RIGHT || c == 6) && i < (int) strlen(line))
158 0 : fputc(line[i++], stdout);
159 :
160 : /* HOME, CTRL-A */
161 0 : if ((c == CH_HOME || c == 1) && i > 0) {
162 0 : for (j = 0; j < i; j++)
163 0 : fputc('\b', stdout);
164 0 : i = 0;
165 : }
166 :
167 : /* END, CTRL-E */
168 0 : if ((c == CH_END || c == 5) && i < (int) strlen(line)) {
169 0 : for (j = i; j < (int) strlen(line); j++)
170 0 : fputc(line[i++], stdout);
171 0 : i = strlen(line);
172 : }
173 :
174 : /* up arrow / CTRL-P */
175 0 : if (c == CH_UP || c == 16) {
176 0 : if (history[(hi + MAX_HISTORY - 1) % MAX_HISTORY][0]) {
177 0 : hi = (hi + MAX_HISTORY - 1) % MAX_HISTORY;
178 0 : i = strlen(line);
179 0 : fputc('\r', stdout);
180 0 : fputs(prompt, stdout);
181 0 : for (j = 0; j < i; j++)
182 0 : fputc(' ', stdout);
183 0 : for (j = 0; j < i; j++)
184 0 : fputc('\b', stdout);
185 0 : memcpy(line, history[hi], 256);
186 0 : i = strlen(line);
187 0 : for (j = 0; j < i; j++)
188 0 : fputc(line[j], stdout);
189 : }
190 : }
191 :
192 : /* down arrow / CTRL-N */
193 0 : if (c == CH_DOWN || c == 14) {
194 0 : if (history[hi][0]) {
195 0 : hi = (hi + 1) % MAX_HISTORY;
196 0 : i = strlen(line);
197 0 : fputc('\r', stdout);
198 0 : fputs(prompt, stdout);
199 0 : for (j = 0; j < i; j++)
200 0 : fputc(' ', stdout);
201 0 : for (j = 0; j < i; j++)
202 0 : fputc('\b', stdout);
203 0 : memcpy(line, history[hi], 256);
204 0 : i = strlen(line);
205 0 : for (j = 0; j < i; j++)
206 0 : fputc(line[j], stdout);
207 : }
208 : }
209 :
210 : /* CTRL-F */
211 0 : if (c == 6) {
212 0 : for (j = (hi + MAX_HISTORY - 1) % MAX_HISTORY; j != hi;
213 0 : j = (j + MAX_HISTORY - 1) % MAX_HISTORY)
214 0 : if (history[j][0] && strncmp(line, history[j], i) == 0) {
215 0 : memcpy(line, history[j], 256);
216 0 : fputs(line + i, stdout);
217 0 : i = strlen(line);
218 0 : break;
219 : }
220 0 : if (j == hi)
221 0 : fputc(7, stdout);
222 : }
223 :
224 : /* tab */
225 0 : if (c == 9 && dir != NULL) {
226 0 : status = dir(line, &i);
227 :
228 : /* redraw line */
229 0 : fputc('\r', stdout);
230 0 : fputs(prompt, stdout);
231 0 : fputs(line, stdout);
232 :
233 0 : for (j = 0; j < (int) strlen(line) - i; j++)
234 0 : fputc('\b', stdout);
235 : }
236 :
237 0 : if (c != 0) {
238 0 : last_time = ss_millitime();
239 0 : fflush(stdout);
240 : }
241 :
242 0 : if ((ss_millitime() - last_time > 300) && idle != NULL) {
243 0 : status = idle();
244 :
245 0 : if (status) {
246 0 : fputc('\r', stdout);
247 0 : fputs(prompt, stdout);
248 0 : fputs(line, stdout);
249 :
250 0 : for (j = 0; j < (int) strlen(line) - i; j++)
251 0 : fputc('\b', stdout);
252 :
253 0 : fflush(stdout);
254 : }
255 : }
256 :
257 0 : } while (c != CH_CR);
258 :
259 0 : strcpy(cmd, line);
260 :
261 0 : if (dir != NULL)
262 0 : if (strcmp(cmd, history[(his_index + MAX_HISTORY - 1) % MAX_HISTORY]) != 0 &&
263 0 : cmd[0]) {
264 0 : strcpy(history[his_index], cmd);
265 0 : his_index = (his_index + 1) % MAX_HISTORY;
266 : }
267 :
268 : /* reset terminal */
269 0 : ss_getchar(1);
270 :
271 0 : fputc('\n', stdout);
272 :
273 0 : return strlen(line);
274 : }
|