~ubuntu-branches/ubuntu/gutsy/irssi/gutsy-backports

« back to all changes in this revision

Viewing changes to src/fe-text/gui-entry.c

  • Committer: Bazaar Package Importer
  • Author(s): David Pashley
  • Date: 2005-12-10 21:25:51 UTC
  • Revision ID: james.westby@ubuntu.com-20051210212551-5qwm108g7inyu2f2
Tags: upstream-0.8.10
ImportĀ upstreamĀ versionĀ 0.8.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "misc.h"
 
23
#include "utf8.h"
 
24
#include "formats.h"
 
25
 
 
26
#include "gui-entry.h"
 
27
#include "gui-printtext.h"
 
28
#include "term.h"
 
29
 
 
30
const unichar empty_str[] = { 0 };
 
31
 
 
32
GUI_ENTRY_REC *active_entry;
 
33
 
 
34
static void entry_text_grow(GUI_ENTRY_REC *entry, int grow_size)
 
35
{
 
36
        if (entry->text_len+grow_size < entry->text_alloc)
 
37
                return;
 
38
 
 
39
        entry->text_alloc = nearest_power(entry->text_alloc+grow_size);
 
40
        entry->text = g_realloc(entry->text,
 
41
                                sizeof(unichar) * entry->text_alloc);
 
42
}
 
43
 
 
44
GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8)
 
45
{
 
46
        GUI_ENTRY_REC *rec;
 
47
 
 
48
        rec = g_new0(GUI_ENTRY_REC, 1);
 
49
        rec->xpos = xpos;
 
50
        rec->ypos = ypos;
 
51
        rec->width = width;
 
52
        rec->text_alloc = 1024;
 
53
        rec->text = g_new(unichar, rec->text_alloc);
 
54
        rec->text[0] = '\0';
 
55
        rec->utf8 = utf8;
 
56
        return rec;
 
57
}
 
58
 
 
59
void gui_entry_destroy(GUI_ENTRY_REC *entry)
 
60
{
 
61
        g_return_if_fail(entry != NULL);
 
62
 
 
63
        if (active_entry == entry)
 
64
                gui_entry_set_active(NULL);
 
65
 
 
66
        g_free(entry->text);
 
67
        g_free(entry->prompt);
 
68
        g_free(entry);
 
69
}
 
70
 
 
71
/* big5 functions */
 
72
#define big5_width(ch) ((ch)>0xff ? 2:1)
 
73
 
 
74
void unichars_to_big5(const unichar *str, char *out)
 
75
{
 
76
        for (; *str != '\0'; str++) {
 
77
                if (*str > 0xff)
 
78
                        *out++ = (*str >> 8) & 0xff;
 
79
                *out++ = *str & 0xff;
 
80
        }
 
81
        *out = '\0';
 
82
}
 
83
 
 
84
int strlen_big5(const unsigned char *str)
 
85
{
 
86
        int len=0;
 
87
 
 
88
        if (term_type != TERM_TYPE_BIG5)
 
89
                return strlen(str);
 
90
 
 
91
        while (*str != '\0') {
 
92
                if (is_big5(str[0], str[1]))
 
93
                        str++;
 
94
                len++;
 
95
                str++;
 
96
        }
 
97
        return len;
 
98
}
 
99
 
 
100
void big5_to_unichars(const char *str, unichar *out)
 
101
{
 
102
        const unsigned char *p = (const unsigned char *) str;
 
103
 
 
104
        while (*p != '\0') {
 
105
                if (is_big5(p[0], p[1])) {
 
106
                        *out++ = p[0] << 8 | p[1];
 
107
                        p += 2;
 
108
                } else {
 
109
                        *out++ = *p++;
 
110
                }
 
111
        }
 
112
        *out = '\0';
 
113
}
 
114
 
 
115
/* ----------------------------- */
 
116
 
 
117
static int pos2scrpos(GUI_ENTRY_REC *entry, int pos)
 
118
{
 
119
        unichar *p;
 
120
        int xpos = 0;
 
121
 
 
122
        for (p = entry->text; p - entry->text < pos; p++) {
 
123
                if (term_type == TERM_TYPE_BIG5)
 
124
                        xpos += big5_width(*p);
 
125
                else if (entry->utf8)
 
126
                        xpos += utf8_width(*p);
 
127
                else
 
128
                        xpos++;
 
129
        }
 
130
        return xpos;
 
131
}
 
132
 
 
133
static int scrpos2pos(GUI_ENTRY_REC *entry, int pos)
 
134
{
 
135
        int i, width, xpos;
 
136
 
 
137
        for (i = 0, xpos = 0; entry->text[i]; i++) {
 
138
                unichar *p = entry->text+i;
 
139
 
 
140
                if (term_type == TERM_TYPE_BIG5)
 
141
                        width = big5_width(*p);
 
142
                else if (entry->utf8)
 
143
                        width = utf8_width(*p);
 
144
                else
 
145
                        width = 1;
 
146
 
 
147
                if (xpos + width > pos)
 
148
                        break;
 
149
                xpos += width;
 
150
        }
 
151
 
 
152
        if (xpos == pos)
 
153
                return i;
 
154
        else
 
155
                return i-1;
 
156
}
 
157
 
 
158
/* Fixes the cursor position in screen */
 
159
static void gui_entry_fix_cursor(GUI_ENTRY_REC *entry)
 
160
{
 
161
        int old_scrstart;
 
162
 
 
163
        /* assume prompt len == prompt scrlen */
 
164
        int start = pos2scrpos(entry, entry->scrstart);
 
165
        int now = pos2scrpos(entry, entry->pos);
 
166
 
 
167
        old_scrstart = entry->scrstart;
 
168
        if (now-start < entry->width - 2 - entry->promptlen && now-start > 0)
 
169
                entry->scrpos = now-start;
 
170
        else if (now < entry->width - 1 - entry->promptlen) {
 
171
                entry->scrstart = 0;
 
172
                entry->scrpos = now;
 
173
        } else {
 
174
                entry->scrstart = scrpos2pos(entry, now-(entry->width -
 
175
                                                         entry->promptlen)*2/3);
 
176
                start = pos2scrpos(entry, entry->scrstart);
 
177
                entry->scrpos = now - start;
 
178
        }
 
179
 
 
180
        if (old_scrstart != entry->scrstart)
 
181
                entry->redraw_needed_from = 0;
 
182
}
 
183
 
 
184
static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos)
 
185
{
 
186
        const unichar *p;
 
187
        int xpos, end_xpos;
 
188
 
 
189
        xpos = entry->xpos + entry->promptlen + 
 
190
                pos2scrpos(entry, pos + entry->scrstart) - 
 
191
                pos2scrpos(entry, entry->scrstart);
 
192
        end_xpos = entry->xpos + entry->width;
 
193
 
 
194
        if (xpos > end_xpos)
 
195
                return;
 
196
 
 
197
        term_set_color(root_window, ATTR_RESET);
 
198
        term_move(root_window, xpos, entry->ypos);
 
199
 
 
200
        p = entry->scrstart + pos < entry->text_len ?
 
201
                entry->text + entry->scrstart + pos : empty_str;
 
202
        for (; *p != '\0'; p++) {
 
203
                if (entry->hidden)
 
204
                        xpos++;
 
205
                else if (term_type == TERM_TYPE_BIG5)
 
206
                        xpos += big5_width(*p);
 
207
                else if (entry->utf8)
 
208
                        xpos += utf8_width(*p);
 
209
                else
 
210
                        xpos++;
 
211
 
 
212
                if (xpos > end_xpos)
 
213
                        break;
 
214
 
 
215
                if (entry->hidden)
 
216
                        term_addch(root_window, ' ');
 
217
                else if (*p >= 32 && (entry->utf8 || (*p & 127) >= 32))
 
218
                        term_add_unichar(root_window, *p);
 
219
                else {
 
220
                        term_set_color(root_window, ATTR_RESET|ATTR_REVERSE);
 
221
                        term_addch(root_window, *p+'A'-1);
 
222
                        term_set_color(root_window, ATTR_RESET);
 
223
                }
 
224
        }
 
225
 
 
226
        /* clear the rest of the input line */
 
227
        if (end_xpos == term_width)
 
228
                term_clrtoeol(root_window);
 
229
        else {
 
230
                while (xpos < end_xpos) {
 
231
                        term_addch(root_window, ' ');
 
232
                        xpos++;
 
233
                }
 
234
        }
 
235
}
 
236
 
 
237
static void gui_entry_draw(GUI_ENTRY_REC *entry)
 
238
{
 
239
        if (entry->redraw_needed_from >= 0) {
 
240
                gui_entry_draw_from(entry, entry->redraw_needed_from);
 
241
                entry->redraw_needed_from = -1;
 
242
        }
 
243
 
 
244
        term_move_cursor(entry->xpos + entry->scrpos + entry->promptlen,
 
245
                         entry->ypos);
 
246
        term_refresh(NULL);
 
247
}
 
248
 
 
249
static void gui_entry_redraw_from(GUI_ENTRY_REC *entry, int pos)
 
250
{
 
251
        pos -= entry->scrstart;
 
252
        if (pos < 0) pos = 0;
 
253
 
 
254
        if (entry->redraw_needed_from == -1 ||
 
255
            entry->redraw_needed_from > pos)
 
256
                entry->redraw_needed_from = pos;
 
257
}
 
258
 
 
259
void gui_entry_move(GUI_ENTRY_REC *entry, int xpos, int ypos, int width)
 
260
{
 
261
        int old_width;
 
262
 
 
263
        g_return_if_fail(entry != NULL);
 
264
 
 
265
        if (entry->xpos != xpos || entry->ypos != ypos) {
 
266
                /* position in screen changed - needs a full redraw */
 
267
                entry->xpos = xpos;
 
268
                entry->ypos = ypos;
 
269
                entry->width = width;
 
270
                gui_entry_redraw(entry);
 
271
                return;
 
272
        }
 
273
 
 
274
        if (entry->width == width)
 
275
                return; /* no changes */
 
276
 
 
277
        if (width > entry->width) {
 
278
                /* input line grew - need to draw text at the end */
 
279
                old_width = width;
 
280
                entry->width = width;
 
281
                gui_entry_redraw_from(entry, old_width);
 
282
        } else {
 
283
                /* input line shrinked - make sure the cursor
 
284
                   is inside the input line */
 
285
                entry->width = width;
 
286
                if (entry->pos - entry->scrstart >
 
287
                    entry->width-2 - entry->promptlen) {
 
288
                        gui_entry_fix_cursor(entry);
 
289
                }
 
290
        }
 
291
 
 
292
        gui_entry_draw(entry);
 
293
}
 
294
 
 
295
void gui_entry_set_active(GUI_ENTRY_REC *entry)
 
296
{
 
297
        active_entry = entry;
 
298
 
 
299
        if (entry != NULL) {
 
300
                term_move_cursor(entry->xpos + entry->scrpos +
 
301
                                 entry->promptlen, entry->ypos);
 
302
                term_refresh(NULL);
 
303
        }
 
304
}
 
305
 
 
306
void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const char *str)
 
307
{
 
308
        int oldlen;
 
309
 
 
310
        g_return_if_fail(entry != NULL);
 
311
 
 
312
        oldlen = entry->promptlen;
 
313
        if (str != NULL) {
 
314
                g_free_not_null(entry->prompt);
 
315
                entry->prompt = g_strdup(str);
 
316
                entry->promptlen = format_get_length(str);
 
317
        }
 
318
 
 
319
        if (entry->prompt != NULL)
 
320
                gui_printtext(entry->xpos, entry->ypos, entry->prompt);
 
321
 
 
322
        if (entry->promptlen != oldlen) {
 
323
                gui_entry_fix_cursor(entry);
 
324
                gui_entry_draw(entry);
 
325
        }
 
326
}
 
327
 
 
328
void gui_entry_set_hidden(GUI_ENTRY_REC *entry, int hidden)
 
329
{
 
330
        g_return_if_fail(entry != NULL);
 
331
 
 
332
        entry->hidden = hidden;
 
333
}
 
334
 
 
335
void gui_entry_set_utf8(GUI_ENTRY_REC *entry, int utf8)
 
336
{
 
337
        g_return_if_fail(entry != NULL);
 
338
 
 
339
        entry->utf8 = utf8;
 
340
}
 
341
 
 
342
void gui_entry_set_text(GUI_ENTRY_REC *entry, const char *str)
 
343
{
 
344
        g_return_if_fail(entry != NULL);
 
345
        g_return_if_fail(str != NULL);
 
346
 
 
347
        entry->text_len = 0;
 
348
        entry->pos = 0;
 
349
        entry->text[0] = '\0';
 
350
 
 
351
        gui_entry_insert_text(entry, str);
 
352
}
 
353
 
 
354
char *gui_entry_get_text(GUI_ENTRY_REC *entry)
 
355
{
 
356
        char *buf;
 
357
        int i;
 
358
 
 
359
        g_return_val_if_fail(entry != NULL, NULL);
 
360
 
 
361
        buf = g_malloc(entry->text_len*6 + 1);
 
362
        if (entry->utf8)
 
363
                utf16_to_utf8(entry->text, buf);
 
364
        else {
 
365
                if (term_type == TERM_TYPE_BIG5)
 
366
                        unichars_to_big5(entry->text, buf);
 
367
                else
 
368
                        for (i = 0; i <= entry->text_len; i++)
 
369
                                buf[i] = entry->text[i];
 
370
        }
 
371
        return buf;
 
372
}
 
373
 
 
374
void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str)
 
375
{
 
376
        unichar chr;
 
377
        int i, len;
 
378
 
 
379
        g_return_if_fail(entry != NULL);
 
380
        g_return_if_fail(str != NULL);
 
381
 
 
382
        gui_entry_redraw_from(entry, entry->pos);
 
383
 
 
384
        len = !entry->utf8 ? strlen_big5(str) : strlen_utf8(str);
 
385
        entry_text_grow(entry, len);
 
386
 
 
387
        /* make space for the string */
 
388
        g_memmove(entry->text + entry->pos + len, entry->text + entry->pos,
 
389
                  (entry->text_len-entry->pos + 1) * sizeof(unichar));
 
390
 
 
391
        if (!entry->utf8) {
 
392
                if (term_type == TERM_TYPE_BIG5) {
 
393
                        chr = entry->text[entry->pos + len];
 
394
                        big5_to_unichars(str, entry->text + entry->pos);
 
395
                        entry->text[entry->pos + len] = chr;
 
396
                } else {
 
397
                        for (i = 0; i < len; i++)
 
398
                                entry->text[entry->pos + i] = str[i];
 
399
                }
 
400
        } else {
 
401
                chr = entry->text[entry->pos+len];
 
402
                utf8_to_utf16(str, entry->text+entry->pos);
 
403
                entry->text[entry->pos+len] = chr;
 
404
        }
 
405
 
 
406
        entry->text_len += len;
 
407
        entry->pos += len;
 
408
 
 
409
        gui_entry_fix_cursor(entry);
 
410
        gui_entry_draw(entry);
 
411
}
 
412
 
 
413
void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr)
 
414
{
 
415
        g_return_if_fail(entry != NULL);
 
416
 
 
417
        if (chr == 0 || chr == 13 || chr == 10)
 
418
                return; /* never insert NUL, CR or LF characters */
 
419
 
 
420
        gui_entry_redraw_from(entry, entry->pos);
 
421
 
 
422
        entry_text_grow(entry, 1);
 
423
 
 
424
        /* make space for the string */
 
425
        g_memmove(entry->text + entry->pos + 1, entry->text + entry->pos,
 
426
                  (entry->text_len-entry->pos + 1) * sizeof(unichar));
 
427
 
 
428
        entry->text[entry->pos] = chr;
 
429
        entry->text_len++;
 
430
        entry->pos++;
 
431
 
 
432
        gui_entry_fix_cursor(entry);
 
433
        gui_entry_draw(entry);
 
434
}
 
435
 
 
436
char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry)
 
437
{
 
438
        char *buf;
 
439
        int i;
 
440
 
 
441
        g_return_val_if_fail(entry != NULL, NULL);
 
442
 
 
443
        if (entry->cutbuffer == NULL)
 
444
                return NULL;
 
445
 
 
446
        buf = g_malloc(entry->cutbuffer_len*6 + 1);
 
447
        if (entry->utf8)
 
448
                utf16_to_utf8(entry->cutbuffer, buf);
 
449
        else if (term_type == TERM_TYPE_BIG5) {
 
450
                unichars_to_big5(entry->cutbuffer, buf);
 
451
        } else {
 
452
                for (i = 0; i <= entry->cutbuffer_len; i++)
 
453
                        buf[i] = entry->cutbuffer[i];
 
454
        }
 
455
        return buf;
 
456
}
 
457
 
 
458
void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer)
 
459
{
 
460
        int newpos, size = 0;
 
461
 
 
462
        g_return_if_fail(entry != NULL);
 
463
 
 
464
        for (newpos = gui_entry_get_pos(entry); newpos > pos; size++)
 
465
                newpos = newpos - 1;
 
466
        gui_entry_erase(entry, size, update_cutbuffer);
 
467
}
 
468
 
 
469
void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer)
 
470
{
 
471
        g_return_if_fail(entry != NULL);
 
472
 
 
473
        if (entry->pos < size)
 
474
                return;
 
475
 
 
476
        if (update_cutbuffer) {
 
477
                /* put erased text to cutbuffer */
 
478
                if (entry->cutbuffer == NULL || entry->cutbuffer_len < size) {
 
479
                        g_free(entry->cutbuffer);
 
480
                        entry->cutbuffer = g_new(unichar, size+1);
 
481
                }
 
482
 
 
483
                entry->cutbuffer_len = size;
 
484
                entry->cutbuffer[size] = '\0';
 
485
                memcpy(entry->cutbuffer, entry->text + entry->pos - size,
 
486
                       size * sizeof(unichar));
 
487
        }
 
488
 
 
489
        if (size == 0) {
 
490
                /* we just wanted to clear the cutbuffer */
 
491
                return;
 
492
        }
 
493
 
 
494
        g_memmove(entry->text + entry->pos - size, entry->text + entry->pos,
 
495
                  (entry->text_len-entry->pos+1) * sizeof(unichar));
 
496
 
 
497
        entry->pos -= size;
 
498
        entry->text_len -= size;
 
499
 
 
500
        gui_entry_redraw_from(entry, entry->pos);
 
501
        gui_entry_fix_cursor(entry);
 
502
        gui_entry_draw(entry);
 
503
}
 
504
 
 
505
void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space)
 
506
{
 
507
        int to;
 
508
 
 
509
        g_return_if_fail(entry != NULL);
 
510
        if (entry->pos == 0)
 
511
                return;
 
512
 
 
513
        to = entry->pos - 1;
 
514
 
 
515
        if (to_space) {
 
516
                while (entry->text[to] == ' ' && to > 0)
 
517
                        to--;
 
518
                while (entry->text[to] != ' ' && to > 0)
 
519
                        to--;
 
520
        } else {
 
521
                while (!i_isalnum(entry->text[to]) && to > 0)
 
522
                        to--;
 
523
                while (i_isalnum(entry->text[to]) && to > 0)
 
524
                        to--;
 
525
        }
 
526
        if (to > 0) to++;
 
527
 
 
528
        gui_entry_erase(entry, entry->pos-to, TRUE);
 
529
}
 
530
 
 
531
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
 
532
{
 
533
        int to, size;
 
534
 
 
535
        g_return_if_fail(entry != NULL);
 
536
        if (entry->pos == entry->text_len)
 
537
                return;
 
538
 
 
539
        to = entry->pos;
 
540
        if (to_space) {
 
541
                while (entry->text[to] == ' ' && to < entry->text_len)
 
542
                        to++;
 
543
                while (entry->text[to] != ' ' && to < entry->text_len)
 
544
                        to++;
 
545
        } else {
 
546
                while (!i_isalnum(entry->text[to]) && to < entry->text_len)
 
547
                        to++;
 
548
                while (i_isalnum(entry->text[to]) && to < entry->text_len)
 
549
                        to++;
 
550
        }
 
551
 
 
552
        size = to-entry->pos;
 
553
        entry->pos = to;
 
554
        gui_entry_erase(entry, size, TRUE);
 
555
}
 
556
 
 
557
void gui_entry_transpose_chars(GUI_ENTRY_REC *entry)
 
558
{
 
559
        unichar chr;
 
560
 
 
561
        if (entry->pos == 0 || entry->text_len < 2)
 
562
                return;
 
563
 
 
564
        if (entry->pos == entry->text_len)
 
565
                entry->pos--;
 
566
 
 
567
        /* swap chars */
 
568
        chr = entry->text[entry->pos];
 
569
        entry->text[entry->pos] = entry->text[entry->pos-1];
 
570
        entry->text[entry->pos-1] = chr;
 
571
 
 
572
        entry->pos++;
 
573
 
 
574
        gui_entry_redraw_from(entry, entry->pos-2);
 
575
        gui_entry_fix_cursor(entry);
 
576
        gui_entry_draw(entry);
 
577
}
 
578
 
 
579
void gui_entry_transpose_words(GUI_ENTRY_REC *entry)
 
580
{
 
581
        int spos1, epos1, spos2, epos2;
 
582
 
 
583
        /* find last position */
 
584
        epos2 = entry->pos;
 
585
        while (epos2 < entry->text_len && !i_isalnum(entry->text[epos2]))
 
586
                epos2++;
 
587
        while (epos2 < entry->text_len &&  i_isalnum(entry->text[epos2]))
 
588
                epos2++;
 
589
 
 
590
        /* find other position */
 
591
        spos2 = epos2;
 
592
        while (spos2 > 0 && !i_isalnum(entry->text[spos2-1]))
 
593
                spos2--;
 
594
        while (spos2 > 0 &&  i_isalnum(entry->text[spos2-1]))
 
595
                spos2--;
 
596
 
 
597
        epos1 = spos2;
 
598
        while (epos1 > 0 && !i_isalnum(entry->text[epos1-1]))
 
599
                epos1--;
 
600
 
 
601
        spos1 = epos1;
 
602
        while (spos1 > 0 && i_isalnum(entry->text[spos1-1]))
 
603
                spos1--;
 
604
 
 
605
        /* do wordswap if any found */
 
606
        if (spos1 < epos1 && epos1 < spos2 && spos2 < epos2) {
 
607
                unichar *first, *sep, *second;
 
608
                int i;
 
609
 
 
610
                first  = (unichar *) g_malloc( (epos1 - spos1) * sizeof(unichar) );
 
611
                sep    = (unichar *) g_malloc( (spos2 - epos1) * sizeof(unichar) );
 
612
                second = (unichar *) g_malloc( (epos2 - spos2) * sizeof(unichar) );
 
613
 
 
614
                for (i = spos1; i < epos1; i++)
 
615
                        first[i-spos1] = entry->text[i];
 
616
                for (i = epos1; i < spos2; i++)
 
617
                        sep[i-epos1] = entry->text[i];
 
618
                for (i = spos2; i < epos2; i++)
 
619
                        second[i-spos2] = entry->text[i];
 
620
 
 
621
                entry->pos = spos1;
 
622
                for (i = 0; i < epos2-spos2; i++)
 
623
                        entry->text[entry->pos++] = second[i];
 
624
                for (i = 0; i < spos2-epos1; i++)
 
625
                        entry->text[entry->pos++] = sep[i];
 
626
                for (i = 0; i < epos1-spos1; i++)
 
627
                        entry->text[entry->pos++] = first[i];
 
628
 
 
629
                g_free(first);
 
630
                g_free(sep);
 
631
                g_free(second);
 
632
 
 
633
        }
 
634
        
 
635
        gui_entry_redraw_from(entry, spos1);
 
636
        gui_entry_fix_cursor(entry);
 
637
        gui_entry_draw(entry);
 
638
}
 
639
 
 
640
void gui_entry_capitalize_word(GUI_ENTRY_REC *entry)
 
641
{
 
642
        int pos = entry->pos;
 
643
        while (pos < entry->text_len && !i_isalnum(entry->text[pos]))
 
644
                pos++;
 
645
 
 
646
        if (pos < entry->text_len) {
 
647
                entry->text[pos] = i_toupper(entry->text[pos]);
 
648
                pos++;
 
649
        }
 
650
 
 
651
        while (pos < entry->text_len && i_isalnum(entry->text[pos])) {
 
652
                entry->text[pos] = i_tolower(entry->text[pos]);
 
653
                pos++;
 
654
        }
 
655
 
 
656
        gui_entry_redraw_from(entry, entry->pos);
 
657
        entry->pos = pos;
 
658
        gui_entry_fix_cursor(entry);
 
659
        gui_entry_draw(entry);
 
660
}
 
661
 
 
662
void gui_entry_downcase_word(GUI_ENTRY_REC *entry)
 
663
{
 
664
        int pos = entry->pos;
 
665
        while (pos < entry->text_len && !i_isalnum(entry->text[pos]))
 
666
                pos++;
 
667
 
 
668
        while (pos < entry->text_len && i_isalnum(entry->text[pos])) {
 
669
                entry->text[pos] = i_tolower(entry->text[pos]);
 
670
                pos++;
 
671
        }
 
672
 
 
673
        gui_entry_redraw_from(entry, entry->pos);
 
674
        entry->pos = pos;
 
675
        gui_entry_fix_cursor(entry);
 
676
        gui_entry_draw(entry);
 
677
}
 
678
 
 
679
void gui_entry_upcase_word(GUI_ENTRY_REC *entry)
 
680
{
 
681
        int pos = entry->pos;
 
682
        while (pos < entry->text_len && !i_isalnum(entry->text[pos]))
 
683
                pos++;
 
684
 
 
685
        while (pos < entry->text_len && i_isalnum(entry->text[pos])) {
 
686
                entry->text[pos] = i_toupper(entry->text[pos]);
 
687
                pos++;
 
688
        }
 
689
 
 
690
        gui_entry_redraw_from(entry, entry->pos);
 
691
        entry->pos = pos;
 
692
        gui_entry_fix_cursor(entry);
 
693
        gui_entry_draw(entry);
 
694
}
 
695
 
 
696
int gui_entry_get_pos(GUI_ENTRY_REC *entry)
 
697
{
 
698
        g_return_val_if_fail(entry != NULL, 0);
 
699
 
 
700
        return entry->pos;
 
701
}
 
702
 
 
703
void gui_entry_set_pos(GUI_ENTRY_REC *entry, int pos)
 
704
{
 
705
        g_return_if_fail(entry != NULL);
 
706
 
 
707
        if (pos >= 0 && pos <= entry->text_len)
 
708
                entry->pos = pos;
 
709
 
 
710
        gui_entry_fix_cursor(entry);
 
711
        gui_entry_draw(entry);
 
712
}
 
713
 
 
714
void gui_entry_move_pos(GUI_ENTRY_REC *entry, int pos)
 
715
{
 
716
        g_return_if_fail(entry != NULL);
 
717
 
 
718
        if (entry->pos + pos >= 0 && entry->pos + pos <= entry->text_len)
 
719
                entry->pos += pos;
 
720
 
 
721
        gui_entry_fix_cursor(entry);
 
722
        gui_entry_draw(entry);
 
723
}
 
724
 
 
725
static void gui_entry_move_words_left(GUI_ENTRY_REC *entry, int count, int to_space)
 
726
{
 
727
        int pos;
 
728
 
 
729
        pos = entry->pos;
 
730
        while (count > 0 && pos > 0) {
 
731
                if (to_space) {
 
732
                        while (pos > 0 && entry->text[pos-1] == ' ')
 
733
                                pos--;
 
734
                        while (pos > 0 && entry->text[pos-1] != ' ')
 
735
                                pos--;
 
736
                } else {
 
737
                        while (pos > 0 && !i_isalnum(entry->text[pos-1]))
 
738
                                pos--;
 
739
                        while (pos > 0 &&  i_isalnum(entry->text[pos-1]))
 
740
                                pos--;
 
741
                }
 
742
                count--;
 
743
        }
 
744
 
 
745
        entry->pos = pos;
 
746
}
 
747
 
 
748
static void gui_entry_move_words_right(GUI_ENTRY_REC *entry, int count, int to_space)
 
749
{
 
750
        int pos;
 
751
 
 
752
        pos = entry->pos;
 
753
        while (count > 0 && pos < entry->text_len) {
 
754
                if (to_space) {
 
755
                        while (pos < entry->text_len && entry->text[pos] == ' ')
 
756
                                pos++;
 
757
                        while (pos < entry->text_len && entry->text[pos] != ' ')
 
758
                                pos++;
 
759
                } else {
 
760
                        while (pos < entry->text_len && !i_isalnum(entry->text[pos]))
 
761
                                pos++;
 
762
                        while (pos < entry->text_len &&  i_isalnum(entry->text[pos]))
 
763
                                pos++;
 
764
                }
 
765
                count--;
 
766
        }
 
767
 
 
768
        entry->pos = pos;
 
769
}
 
770
 
 
771
void gui_entry_move_words(GUI_ENTRY_REC *entry, int count, int to_space)
 
772
{
 
773
        g_return_if_fail(entry != NULL);
 
774
 
 
775
        if (count < 0)
 
776
                gui_entry_move_words_left(entry, -count, to_space);
 
777
        else if (count > 0)
 
778
                gui_entry_move_words_right(entry, count, to_space);
 
779
 
 
780
        gui_entry_fix_cursor(entry);
 
781
        gui_entry_draw(entry);
 
782
}
 
783
 
 
784
void gui_entry_redraw(GUI_ENTRY_REC *entry)
 
785
{
 
786
        g_return_if_fail(entry != NULL);
 
787
 
 
788
        gui_entry_set_prompt(entry, NULL);
 
789
        gui_entry_redraw_from(entry, 0);
 
790
        gui_entry_fix_cursor(entry);
 
791
        gui_entry_draw(entry);
 
792
}