티스토리 뷰

심화

User Interface - UART 문자열 입력

Just4Fun 2017. 6. 29. 20:25

이번 글에서는 실제로 사용자가 하나씩 입력하는 문자를 버퍼에 저장하였다가, 사용자가 엔터키를 누르게 되었을 때 저장해 둔 문자열을 리턴해 주는 코드를 만드는 방법에 대해서 설명하도록 하겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#define CTRL_B      2
#define CTRL_C      3
#define CTRL_F      6
 
#define EOL         '\0'
#define ENTER       '\r'
#define BS          '\b'
#define ESC         0x1B
#define ESC2        '['
#define DELIMIT     '~'
#define DELETE      0x7F
#define UP_ARROW    'A'
#define DN_ARROW    'B'
#define RI_ARROW    'C'
#define LE_ARROW    'D'
 
 
static char command_buf[BD_CMD_BUF_SZ];
 
void *wait_command(void)
{
    char    *cp = command_buf;
    char    ch;
    int     len, i;
 
    *cp = EOL;
    while (1)
    {
        ch = getc();
        switch (ch)
        {
            case ENTER:
                putc('\n');
                return command_buf;
 
            case BS:        // back space
                if (cp > command_buf)
                {
                    puts("\b\x1B[K");
                    if (*cp)
                    {
                        len = strlen(--cp);
                        for (i=0; i<len; i++)
                            cp[i] = cp[i+1];
 
                        puts(cp);
                        printf("\x1B[%uD", len-1);
                    }
                    else
                    {
                        *(--cp) = EOL;
                    }
                }
                break;
 
            case DELETE:    // Delete
                if (*cp)
                {
                    len = strlen(cp);
                    for (i=0; i<len; i++)
                        cp[i] = cp[i+1];
                    cp[i+1] = EOL;
                    puts("\x1B[K");
                    puts(cp);
                    printf("\x1B[%uD", len-1);
                }
                break;
 
            case CTRL_B:    // Ctrl+B
                i = 0;
                if (cp > command_buf)
                {
                    --cp;
                    i++;
 
                    while (cp > command_buf && *cp == ' ')
                    {
                        --cp;
                        i++;
                    }
                    while (cp >= command_buf && *cp != ' ')
                    {
                        --cp;
                        i++;
                    }
 
                    ++cp;
                    --i;
                    printf("\x1B[%uD", i);
                }
                break;
 
            case CTRL_C:    // Ctrl+C
                command_buf[0] = EOL;
                putc('\n');
                return command_buf;
 
            case CTRL_F:    // Ctrl+F
                i = 0;
                char *end_cp = command_buf + strlen(command_buf);
                if (cp < end_cp)
                {
                    while (cp < end_cp && *cp != ' ')
                    {
                        ++cp;
                        i++;
                    }
                    while (cp < end_cp && *cp == ' ')
                    {
                        ++cp;
                        i++;
                    }
                    if (i)
                        printf("\x1B[%uC", i);
                }
                break;
 
            case ESC:       // Special Keys
                if (getc() != ESC2)
                    break;
 
                switch (getc())
                {
                    case UP_ARROW:
                        break;
 
                    case DN_ARROW:
                        break;
 
                    case RI_ARROW:
                        if (cp < (command_buf + strlen(command_buf)))
                        {
                            ++cp;
                            puts("\x1B[C");
                        }
                        break;
 
                    case LE_ARROW:
                        if (cp > command_buf)
                        {
                            --cp;
                            puts("\x1B[D");
                        }
                        break;
 
                    case '1':
                        ch = getc();
                        if (ch == DELIMIT) // KEY_HOME
                        {
                            len = cp - command_buf;
                            if (len)
                            {
                                printf("\x1B[%uD", len);
                                cp = command_buf;
                            }
                            break;
                        }
 
                        if (getc() != DELIMIT)
                            break;
 
                        switch (ch)
                        {
                            case '1': // KEY_F1;
                                break;
 
                            case '2': // KEY_F2;
                                break;
 
                            case '3': // KEY_F3;
                                break;
 
                            case '4': // KEY_F4;
                                break;
 
                            case '5': // KEY_F5;
                                break;
 
                            case '7': // KEY_F6;
                                break;
 
                            case '8': // KEY_F7;
                                break;
 
                            case '9': // KEY_F8;
                                break;
                        }
                        break;
 
                    case '2':
                        ch = getc();
                        if (ch == DELIMIT) // KEY_INS;
                        {
                            break;
                        }
 
                        if (getc() != DELIMIT)
                            break;
 
 
                        switch (ch)
                        {
                            case '0': // KEY_F9;
                                break;
 
                            case '1': // KEY_F10;
                                break;
 
                            case '3': // KEY_F11;
                                break;
 
                            case '4': // KEY_F12;
                                break;
                        }
                        break;
 
                    case '4': // KEY_END;
                        if (getc() == DELIMIT)
                        {
                            len = strlen(cp);
                            if (len)
                            {
                                printf("\x1B[%uC", len);
                                cp += len;
                            }
                        }
                        break;
 
                    case '5': // KEY_PGUP;
                        if (getc() == DELIMIT)
                        {
                        }
                        break;
 
                    case '6': // KEY_PGDN;
                        if (getc() == DELIMIT)
                        {
                        }
                        break;
                }
                break;
 
            default:
                if (strlen(command_buf) < (BD_CMD_BUF_SZ - 1))
                {
                    if (*cp)
                    {
                        len = strlen(cp);
                        for (i=len+1; i; i--)
                            cp[i] = cp[i-1];
                        *cp = ch;
 
                        puts("\x1B[K");
                        puts(cp);
                        printf("\x1B[%uD", len);
                        ++cp;
                    }
                    else
                    {
                        *cp++ = ch;
                        *cp = EOL;
                        putc(ch);
                    }
                }
                break;
        } // switch
    } // while
 
    return command_buf;
}

코드가 꽤 길지만 앞에서 설명한 글을 참고하면 특정 키가 눌러졌을때에 해당하는 코드는 그렇게 길지 않으므로 조금만 분석하면 쉽게 이해할 수 있을 것이다.

주요 기능들에 대해서 간단히 설명하면 다음과 같다.

엔터키를 누르면 입력이 끝났음을 알려주는 것이므로 문자열 버퍼의 시작 주소를 리턴해 주도록 하고 있다.

백스페이스와 delete 키는 입력 중인 문자열을 수정하기 위하여 사용된다.  백스페이스키는 현재 커서가 위치하고 있는 바로 앞의 글자를 지우고 커서 뒤에 있는 문자열을 한글자씩 앞으로 당기는 기능을 수행한다.  이에 반해 delete 키는 현재 커서 위치에 있는 글자를 하나 지우고 커서 뒤에 있는 글자들을 한칸씩 앞으로 당기게 된다.

왼쪽 화살표와 오른쪽 화살표는 각각 커서를 한칸만 왼쪽 혹은 오른쪽으로 이동 시킨다.

Home 키는 입력중인 문자열의 시작 부분으로 커서를 옮기게 하고, End 키는 입력중인 문자열의 마지막 위치로 커서를 옮겨주는 기능을 수행한다.

Ctrl+B와 Ctrl+F 키는 커서를 한 단어씩 옮기도록 한다.

Ctrl+C는 입력 중인 동작을 취소할 때 사용한다.

사용자가 문자를 입력한 후 엔터키를 눌렀을 때 해당 문자열이 그대로 출력되는 것을 볼 수 있다.

코드에서 구현된 다양한 특수 키들을 눌러 보면서 입력 중인 문자들을 수정하거나 커서를 옮겨 보면서 제대로 동작되는지 확인해서 코드에 문제가 없는지 검증해 보도록 한다.


ui_command.zip


'심화' 카테고리의 다른 글

User Interface - 메뉴 방식  (0) 2017.07.08
User Interface - argc, argv  (0) 2017.07.07
User Interface - UART 특수키 처리  (0) 2017.06.24
megaOS - 13. Mailbox  (1) 2016.11.13
megaOS - 12. Flag  (0) 2016.11.08
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함