GadgetSeed  0.9.6
lineedit.c
[詳解]
1 /** @file
2  @brief ラインエディタ
3 
4  @date 2002.03.30
5  @author Takashi SHUDO
6 
7  @info
8 
9  機能
10 
11  ラインエディタ、ヒストリ対応<br>
12  VT100互換のターミナル用<br>
13 
14  キー<br>
15  ↑ 1b 5b 41<br>
16  ↓ 1b 5b 42<br>
17  CTRL-P 10<br>
18  CTRL-N 0e ヒストリー<br>
19  ← 1b 5b 44<br>
20  → 1b 5b 43 カーソル移動<br>
21  CTRL-A 01 カーソルを先頭へ<br>
22  CTRL-B 02 カーソルを1文字前へ<br>
23  CTRL-D 04 1文字削除<br>
24  CTRL-E 05 カーソルを末尾へ<br>
25  CTRL-F 06 カーソルを1文字先へ<br>
26  CTRL-H 08 1文字前を削除(BS)<br>
27  CTRL-K 0b カーソル以降を削除<br>
28 */
29 
30 #include "lineedit.h"
31 #include "str.h"
32 #include "console.h"
33 
34 #define BS 0x08
35 #define HT 0x09
36 #define LF 0x0a
37 #define CR 0x0d
38 
39 ///< lineedit.stat
40 enum {
41  ESC0, ///< エスケープシーケンス未受信
42  ESC1, ///< エスケープシーケンス1バイト目
43  ESC2, ///< エスケープシーケンス2バイト目
44 };
45 
46 /**
47  @brief lineeditを初期化する
48 
49  @param[in] le 初期化するlineedit
50 */
51 void init_lineedit(struct st_lineedit *le)
52 {
53  int i;
54 
55  for(i=0; i<GSC_SHELL_MAX_LINE_COLUMS; i++) {
56  le->buf[i] = 0;
57  }
58  le->cur_pos = 0;
59  le->stat = ESC0;
60 }
61 
62 /**
63  @brief リターンを受けるまでの1行編集を行う
64  1文字づつデータを入れる
65 
66  @param[in] le 編集するlineedit
67  @param[in] ch 入力文字
68 
69  @return 編集結果(LER_*)
70 */
71 int do_lineedit(struct st_lineedit *le, uchar ch)
72 {
73  int i, j;
74 
75  switch(le->stat) {
76  case ESC1: // エスケープシーケンス2バイト目
77  switch(ch) {
78  case 0x5b:
79  le->stat = ESC2;
80  break;
81 
82  default:
83  le->stat = ESC0;
84  break;
85  }
86  break;
87 
88  case ESC2: // エスケープシーケンス3バイト目
89  switch(ch) {
90  case 0x41: // ↑
91  le->stat = ESC0;
92  return LER_BACKLINE;
93 
94  case 0x42: // ↓
95  le->stat = ESC0;
96  return LER_NEXTLINE;
97 
98  case 0x44: // ←
99  if(le->cur_pos != 0) {
100  cputc(BS);
101  le->cur_pos --;
102  }
103  le->stat = ESC0;
104  break;
105 
106  case 0x43: // →
107  if(le->cur_pos < strleng(le->buf)) {
108  cputc(le->buf[le->cur_pos]);
109  le->cur_pos ++;
110  }
111  le->stat = ESC0;
112  break;
113 
114  default:
115  le->stat = ESC0;
116  break;
117  }
118  break;
119 
120  default:
121  switch(ch) {
122  case 0x00:
123  // NULL文字(0x00)は無視
124  break;
125 
126  case 0x01: // CTRL-A
127  for(i=0; i<le->cur_pos; i++) {
128  cputc(BS);
129  }
130  le->cur_pos = 0;
131  break;
132 
133  case 0x02: // CTRL-B
134  if(le->cur_pos != 0) {
135  cputc(BS);
136  le->cur_pos --;
137  }
138  break;
139 
140  case 0x03: // CTRL-C
141  break;
142 
143  case 0x04: // CTRL-D
144  j = strleng(le->buf);
145  if(le->cur_pos < j) {
146  for(i=le->cur_pos; i<(j-1); i++) {
147  le->buf[i] = le->buf[i+1];
148  cputc(le->buf[i]);
149  }
150  le->buf[j-1] = 0;
151  cputc(' ');
152  for(i=le->cur_pos; i<j; i++) {
153  cputc(BS);
154  }
155  }
156  break;
157 
158  case 0x05: // CTRL-E
159  for(i=le->cur_pos; i<strleng(le->buf); i++) {
160  cputc(le->buf[i]);
161  le->cur_pos ++;
162  }
163  break;
164 
165  case 0x06: // CTRL-F
166  if(le->cur_pos < strleng(le->buf)) {
167  cputc(le->buf[le->cur_pos]);
168  le->cur_pos ++;
169  }
170  break;
171 
172  case 0x07:
173  break;
174 
175  case 0x7f:
176  case BS: // バックスペース
177  if(le->cur_pos > 0) {
178  cputc(BS);
179  j = strleng(le->buf);
180  for(i=le->cur_pos; i<j; i++) {
181  le->buf[i-1] = le->buf[i];
182  cputc(le->buf[i]);
183  }
184  le->buf[j-1] = 0;
185  cputc(' ');
186  for(i=le->cur_pos; i<j; i++) {
187  cputc(BS);
188  }
189  cputc(BS);
190  le->cur_pos --;
191  }
192  break;
193 
194  case HT: // HT(水平タブ)
195  break;
196 
197  case LF: // LF
198  break;
199 
200  case 0x0b: // CTRL-K
201  cputc(0x1b);
202  cputc(0x5b);
203  cputc(0x4b);
204  j = strleng(le->buf);
205  for(i=le->cur_pos; i<j; i++) {
206  le->buf[i] = 0;
207  }
208  break;
209 
210  case 0x0c: // CTRL-L
211  break;
212 
213  case CR: // CTRL-M
214  cputc(CR);
215  cputc(LF);
216 
217  return LER_RETURN;
218 
219  case 0x0e: // CTRL-N
220  le->stat = ESC0;
221  return LER_NEXTLINE;
222 
223  case 0x10: // CTRL-P
224  le->stat = ESC0;
225  return LER_BACKLINE;
226 
227  case 0x11: // CTRL-Q(X-ON)
228  break;
229 
230  case 0x13: // CTRL-S(X-OFF)
231  break;
232 
233  case 0x0f:
234  case 0x12:
235  case 0x14:
236  case 0x15:
237  case 0x16:
238  case 0x17:
239  case 0x18:
240  case 0x19:
241  case 0x1a:
242  break;
243 
244  case 0x1b: // エスケープシーケンス
245  le->stat = ESC1;
246  break;
247 
248  case 0x1c:
249  case 0x1d:
250  case 0x1e:
251  case 0x1f:
252  break;
253 
254  default: // 文字入力
255  {
256  j = strleng(le->buf);
257 
258  if(j < GSC_SHELL_MAX_LINE_COLUMS) {
259  if(j > 0) {
260  for(i=j; i>=(int)le->cur_pos; i--) {
261  le->buf[i] = le->buf[i-1];
262  }
263  }
264  le->buf[le->cur_pos] = ch;
265  le->buf[j+1] = 0;
266 
267  for(i=le->cur_pos; i<=j; i++) {
268  cputc(le->buf[i]);
269  }
270 
271  for(i=le->cur_pos; i<j; i++) {
272  cputc(BS);
273  }
274 
275  le->cur_pos ++;
276  }
277  }
278  break;
279  }
280  }
281 
282  return LER_NOP;
283 }
284 
285 /**
286  @brief 編集中のエディタを初期化(コマンド実行後にバッファ破棄)
287 
288  @param[in] le 編集するlineedit
289 */
290 void new_lineedit(struct st_lineedit *le)
291 {
292  int i;
293 
294  for(i=0; i<GSC_SHELL_MAX_LINE_COLUMS; i++) {
295  le->buf[i] = 0;
296  }
297 
298  le->cur_pos = 0;
299  le->stat = ESC0;
300 }
301 
302 /**
303  @brief 編集文字列を設定する
304 
305  @param[in] le 文字列を設定するlineedit
306  @param[in] str 設定する文字列
307 */
308 void set_str_lineedit(struct st_lineedit *le, uchar *str)
309 {
310  unsigned int i;
311 
312  for(i=0; i<le->cur_pos; i++) {
313  cputc(BS);
314  }
315  cputc(0x1b);
316  cputc(0x5b);
317  cputc(0x4b);
318 
319  le->cur_pos = 0;
320 
321  for(i=0; i<GSC_SHELL_MAX_LINE_COLUMS; i++) {
322  le->buf[i] = str[i];
323  if(le->buf[i] != 0) {
324  cputc(le->buf[i]);
325  le->cur_pos ++;
326  } else {
327  return;
328  }
329  }
330 }
331 
332 /**
333  @brief 表示する
334 
335  @param[in] le 文字列を設定するlineedit
336 */
337 void draw_lineedit(struct st_lineedit *le)
338 {
339  unsigned int i, j;
340 
341  for(i=0; i<GSC_SHELL_MAX_LINE_COLUMS; i++) {
342  if(le->buf[i] != 0) {
343  cputc(le->buf[i]);
344  } else {
345  break;
346  }
347  }
348 
349  for(j=i; j>le->cur_pos; j--) {
350  cputc(BS);
351  }
352 }
353 
354 
355 void insert_str_lineedit(struct st_lineedit *le, uchar *str, unsigned int len)
356 {
357  unsigned int i;
358 
359  for(i=0; i<len; i++) {
360  do_lineedit(le, str[i]);
361  }
362 }
unsigned char uchar
GadgetSeedの文字(列)は unsigned char 型となる
Definition: str.h:13
unsigned int cur_pos
カーソル位置
Definition: lineedit.h:32
エスケープシーケンス2バイト目
Definition: lineedit.c:43
ラインエディタ
Definition: lineedit.h:30
uchar buf[GSC_SHELL_MAX_LINE_COLUMS+1]
編集中文字列
Definition: lineedit.h:31
ラインエディタ
エスケープシーケンス1バイト目
Definition: lineedit.c:42
#define CR
lineedit.stat
Definition: lineedit.c:37
void init_lineedit(struct st_lineedit *le)
lineeditを初期化する
Definition: lineedit.c:51
文字列処理
エスケープシーケンス未受信
Definition: lineedit.c:41
int do_lineedit(struct st_lineedit *le, uchar ch)
リターンを受けるまでの1行編集を行う 1文字づつデータを入れる
Definition: lineedit.c:71
unsigned int strleng(const uchar *str)
文字列長
Definition: str.c:657
int cputc(unsigned char td)
標準出力より1文字を出力する
Definition: console.c:163
void set_str_lineedit(struct st_lineedit *le, uchar *str)
編集文字列を設定する
Definition: lineedit.c:308
コンソールI/O
void new_lineedit(struct st_lineedit *le)
編集中のエディタを初期化(コマンド実行後にバッファ破棄)
Definition: lineedit.c:290
#define GSC_SHELL_MAX_LINE_COLUMS
$gsc shellコマンドラインの最大文字数
Definition: lineedit.h:16
int stat
エスケープシーケンスデコード状態
Definition: lineedit.h:33
void draw_lineedit(struct st_lineedit *le)
表示する
Definition: lineedit.c:337