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