imported irssi.
[silc.git] / apps / irssi / src / fe-text / gui-entry.c
1 /*
2  gui-entry.c : irssi
3
4     Copyright (C) 1999 Timo Sirainen
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "module.h"
22 #include "formats.h"
23
24 #include "gui-printtext.h"
25 #include "screen.h"
26
27 static GString *entry;
28 static int promptlen, permanent_prompt, pos, scrstart, scrpos;
29 static int prompt_hidden;
30 static char *prompt;
31
32 static void entry_screenpos(void)
33 {
34         if (pos-scrstart < COLS-2-promptlen && pos-scrstart > 0) {
35                 scrpos = pos-scrstart;
36                 return;
37         }
38
39         if (pos < COLS-1-promptlen) {
40                 scrstart = 0;
41                 scrpos = pos;
42         } else {
43                 scrpos = (COLS-promptlen)*2/3;
44                 scrstart = pos-scrpos;
45         }
46 }
47
48 static void entry_update(void)
49 {
50         char *p;
51         int n, len;
52
53         len = entry->len-scrstart > COLS-1-promptlen ?
54                 COLS-1-promptlen : entry->len-scrstart;
55
56         set_color(stdscr, 0);
57         move(LINES-1, promptlen);
58
59         for (p = entry->str+scrstart, n = 0; n < len; n++, p++) {
60                 if (prompt_hidden)
61                         addch(' ');
62                 else if ((unsigned char) *p >= 32)
63                         addch((unsigned char) *p);
64                 else {
65                         set_color(stdscr, ATTR_REVERSE);
66                         addch(*p+'A'-1);
67                         set_color(stdscr, 0);
68                 }
69         }
70         clrtoeol();
71
72         move_cursor(LINES-1, scrpos+promptlen);
73         screen_refresh(NULL);
74 }
75
76 void gui_entry_set_prompt(const char *str)
77 {
78         if (str != NULL) {
79                 if (permanent_prompt) return;
80
81                 g_free_not_null(prompt);
82                 prompt = g_strdup(str);
83                 promptlen = format_get_length(prompt);
84         }
85
86         if (prompt != NULL)
87                 gui_printtext(0, LINES-1, prompt);
88
89         entry_screenpos();
90         entry_update();
91 }
92
93 void gui_entry_set_perm_prompt(const char *str)
94 {
95         g_return_if_fail(str != NULL);
96
97         g_free_not_null(prompt);
98         prompt = g_strdup(str);
99         promptlen = format_get_length(prompt);
100
101         permanent_prompt = TRUE;
102         gui_entry_set_prompt(NULL);
103 }
104
105 void gui_entry_set_hidden(int hidden)
106 {
107         prompt_hidden = hidden;
108 }
109
110 void gui_entry_remove_perm_prompt(void)
111 {
112         permanent_prompt = FALSE;
113 }
114
115 void gui_entry_set_text(const char *str)
116 {
117         g_return_if_fail(str != NULL);
118
119         g_string_assign(entry, str);
120         pos = entry->len;
121
122         entry_screenpos();
123         entry_update();
124 }
125
126 char *gui_entry_get_text(void)
127 {
128         return entry->str;
129 }
130
131 void gui_entry_insert_text(const char *str)
132 {
133         g_return_if_fail(str != NULL);
134
135         g_string_insert(entry, pos, str);
136         pos += strlen(str);
137
138         entry_screenpos();
139         entry_update();
140 }
141
142 void gui_entry_insert_char(char chr)
143 {
144         g_string_insert_c(entry, pos, chr);
145         pos++;
146
147         entry_screenpos();
148         entry_update();
149 }
150
151 void gui_entry_erase(int size)
152 {
153         if (pos < size) return;
154
155 #ifdef WANT_BIG5
156         if (is_big5(entry->str[pos-2], entry->str[pos-1]))
157                 size++;
158 #endif WANT_BIG5
159
160         pos -= size;
161         g_string_erase(entry, pos, size);
162
163         entry_screenpos();
164         entry_update();
165 }
166
167 void gui_entry_erase_word(void)
168 {
169         int to;
170         
171         if (pos == 0) return;
172
173         to = pos - 1;
174
175         while (entry->str[to] == ' ' && to > 0)
176                 to--;
177
178         while (entry->str[to] != ' ' && to > 0)
179                 to--;
180
181         if (entry->str[to] == ' ' && to > 0) 
182                 to++;
183
184         g_string_erase(entry, to, pos - to);
185         pos = to;
186
187         entry_screenpos();
188         entry_update();
189 }
190
191 void gui_entry_erase_next_word(void)
192 {
193         int to = pos;
194         
195         if (pos == entry->len) return;
196
197         while (entry->str[to] == ' ' && to < entry->len)
198                 to++;
199
200         while (entry->str[to] != ' ' && to < entry->len)
201                 to++;
202
203         g_string_erase(entry, pos, to - pos);
204
205         entry_screenpos();
206         entry_update();
207 }
208
209 int gui_entry_get_pos(void)
210 {
211         return pos;
212 }
213
214 void gui_entry_set_pos(int p)
215 {
216         if (p >= 0 && p <= entry->len)
217                 pos = p;
218
219         entry_screenpos();
220         entry_update();
221 }
222
223 void gui_entry_move_pos(int p)
224 {
225 #ifdef WANT_BIG5
226         if (p > 0 && is_big5 (entry->str[pos], entry->str[pos+1]))
227                 p++;
228         else if (p < 0 && is_big5 (entry->str[pos-1], entry->str[pos]))
229                 p--;
230 #endif WANT_BIG5
231
232         if (pos+p >= 0 && pos+p <= entry->len)
233                 pos += p;
234
235         entry_screenpos();
236         entry_update();
237 }
238
239 static void gui_entry_move_words_left(int count)
240 {
241         if (pos == 0) return;
242
243         while (count > 0 && pos > 0) {
244                 while (pos > 0 && entry->str[pos-1] == ' ')
245                         pos--;
246                 while (pos > 0 && entry->str[pos-1] != ' ')
247                         pos--;
248                 count--;
249         }
250 }
251
252 static void gui_entry_move_words_right(int count)
253 {
254         if (pos == entry->len) return;
255
256         while (count > 0 && pos < entry->len) {
257                 while (pos < entry->len && entry->str[pos] != ' ')
258                         pos++;
259                 while (pos < entry->len && entry->str[pos] == ' ')
260                         pos++;
261                 count--;
262         }
263 }
264
265 void gui_entry_move_words(int count)
266 {
267         if (count < 0)
268                 gui_entry_move_words_left(-count);
269         else if (count > 0)
270                 gui_entry_move_words_right(count);
271
272         entry_screenpos();
273         entry_update();
274 }
275
276 void gui_entry_redraw(void)
277 {
278         gui_entry_set_prompt(NULL);
279
280         entry_screenpos();
281         entry_update();
282 }
283
284 void gui_entry_init(void)
285 {
286         entry = g_string_new(NULL);
287
288         pos = scrpos = 0;
289         prompt = NULL; promptlen = 0;
290         permanent_prompt = FALSE;
291         prompt_hidden = FALSE;
292 }
293
294 void gui_entry_deinit(void)
295 {
296         if (prompt != NULL) g_free(prompt);
297         g_string_free(entry, TRUE);
298 }