1 /*
2 * Copyright 2008-2013 Various Authors
3 * Copyright 2005 Timo Hirvonen
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "cmdline.h"
20 #include "uchar.h"
21 #include "xmalloc.h"
22
23 struct cmdline cmdline;
24
25 const char cmdline_word_delimiters[] = " ";
26 const char cmdline_filename_delimiters[] = "/";
27
cmdline_init(void)28 void cmdline_init(void)
29 {
30 cmdline.blen = 0;
31 cmdline.clen = 0;
32 cmdline.bpos = 0;
33 cmdline.cpos = 0;
34 cmdline.size = 128;
35 cmdline.line = xnew(char, cmdline.size);
36 cmdline.line[0] = 0;
37 }
38
cmdline_insert_ch(uchar ch)39 void cmdline_insert_ch(uchar ch)
40 {
41 int size;
42
43 size = u_char_size(ch);
44 if (cmdline.blen + size > cmdline.size) {
45 cmdline.size *= 2;
46 cmdline.line = xrenew(char, cmdline.line, cmdline.size);
47 }
48 memmove(cmdline.line + cmdline.bpos + size,
49 cmdline.line + cmdline.bpos,
50 cmdline.blen - cmdline.bpos + 1);
51 u_set_char_raw(cmdline.line, &cmdline.bpos, ch);
52 cmdline.cpos++;
53 cmdline.blen += size;
54 cmdline.clen++;
55 }
56
cmdline_backspace(void)57 void cmdline_backspace(void)
58 {
59 int bpos, size;
60
61 if (cmdline.bpos == 0)
62 return;
63
64 bpos = cmdline.bpos;
65 u_prev_char_pos(cmdline.line, &bpos);
66 size = cmdline.bpos - bpos;
67
68 memmove(cmdline.line + bpos,
69 cmdline.line + cmdline.bpos,
70 cmdline.blen - cmdline.bpos + 1);
71 cmdline.bpos -= size;
72 cmdline.cpos--;
73 cmdline.blen -= size;
74 cmdline.clen--;
75 }
76
cmdline_backspace_to_bol(void)77 void cmdline_backspace_to_bol(void)
78 {
79 while (cmdline.bpos)
80 cmdline_backspace();
81 }
82
cmdline_delete_ch(void)83 void cmdline_delete_ch(void)
84 {
85 uchar ch;
86 int size, bpos;
87
88 if (cmdline.bpos == cmdline.blen)
89 return;
90 bpos = cmdline.bpos;
91 ch = u_get_char(cmdline.line, &bpos);
92 size = u_char_size(ch);
93 cmdline.blen -= size;
94 cmdline.clen--;
95 memmove(cmdline.line + cmdline.bpos,
96 cmdline.line + cmdline.bpos + size,
97 cmdline.blen - cmdline.bpos + 1);
98 }
99
cmdline_set_text(const char * text)100 void cmdline_set_text(const char *text)
101 {
102 int len = strlen(text);
103
104 if (len >= cmdline.size) {
105 while (len >= cmdline.size)
106 cmdline.size *= 2;
107 cmdline.line = xrenew(char, cmdline.line, cmdline.size);
108 }
109 memcpy(cmdline.line, text, len + 1);
110 cmdline.cpos = u_strlen_safe(cmdline.line);
111 cmdline.bpos = len;
112 cmdline.clen = cmdline.cpos;
113 cmdline.blen = len;
114 }
115
cmdline_clear(void)116 void cmdline_clear(void)
117 {
118 cmdline.blen = 0;
119 cmdline.clen = 0;
120 cmdline.bpos = 0;
121 cmdline.cpos = 0;
122 cmdline.line[0] = 0;
123 }
124
cmdline_clear_end(void)125 void cmdline_clear_end(void)
126 {
127 cmdline.line[cmdline.bpos] = 0;
128
129 cmdline.clen = u_strlen_safe(cmdline.line);
130 cmdline.blen = strlen(cmdline.line);
131 }
132
cmdline_move_left(void)133 void cmdline_move_left(void)
134 {
135 if (cmdline.bpos > 0) {
136 cmdline.cpos--;
137 u_prev_char_pos(cmdline.line, &cmdline.bpos);
138 }
139 }
140
cmdline_move_right(void)141 void cmdline_move_right(void)
142 {
143 if (cmdline.bpos < cmdline.blen) {
144 u_get_char(cmdline.line, &cmdline.bpos);
145 cmdline.cpos++;
146 }
147 }
148
cmdline_move_home(void)149 void cmdline_move_home(void)
150 {
151 cmdline.cpos = 0;
152 cmdline.bpos = 0;
153 }
154
cmdline_move_end(void)155 void cmdline_move_end(void)
156 {
157 cmdline.cpos = cmdline.clen;
158 cmdline.bpos = cmdline.blen;
159 }
160
next_word(const char * str,int bpos,int * cdiff,const char * delim,int direction)161 static int next_word(const char *str, int bpos, int *cdiff, const char *delim, int direction)
162 {
163 int skip_delim = 1;
164 while ((direction > 0) ? str[bpos] : (bpos > 0)) {
165 uchar ch;
166 int oldp = bpos;
167
168 if (direction > 0) {
169 ch = u_get_char(str, &bpos);
170 } else {
171 u_prev_char_pos(str, &bpos);
172 oldp = bpos;
173 ch = u_get_char(str, &oldp);
174 }
175
176 if (u_strchr(delim, ch)) {
177 if (!skip_delim) {
178 bpos -= bpos - oldp;
179 break;
180 }
181 } else
182 skip_delim = 0;
183
184 *cdiff += direction;
185 }
186 return bpos;
187 }
188
cmdline_forward_word(const char * delim)189 void cmdline_forward_word(const char *delim)
190 {
191 cmdline.bpos = next_word(cmdline.line, cmdline.bpos, &cmdline.cpos, delim, +1);
192 }
193
cmdline_backward_word(const char * delim)194 void cmdline_backward_word(const char *delim)
195 {
196 cmdline.bpos = next_word(cmdline.line, cmdline.bpos, &cmdline.cpos, delim, -1);
197 }
198
cmdline_delete_word(const char * delim)199 void cmdline_delete_word(const char *delim)
200 {
201 int bpos, cdiff = 0;
202
203 bpos = next_word(cmdline.line, cmdline.bpos, &cdiff, delim, +1);
204
205 memmove(cmdline.line + cmdline.bpos,
206 cmdline.line + bpos,
207 cmdline.blen - bpos + 1);
208 cmdline.blen -= bpos - cmdline.bpos;
209 cmdline.clen -= cdiff;
210 }
211
cmdline_backward_delete_word(const char * delim)212 void cmdline_backward_delete_word(const char *delim)
213 {
214 int bpos, cdiff = 0;
215
216 bpos = next_word(cmdline.line, cmdline.bpos, &cdiff, delim, -1);
217
218 cmdline.blen += bpos - cmdline.bpos;
219 memmove(cmdline.line + bpos,
220 cmdline.line + cmdline.bpos,
221 cmdline.blen - bpos + 1);
222 cmdline.bpos = bpos;
223 cmdline.clen += cdiff;
224 cmdline.cpos += cdiff;
225 }
226