4 * Copyright (c) Tuomo Valkonen 1999-2005.
6 * Ion is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
14 #include <libtu/minmax.h>
15 #include <ioncore/common.h>
16 #include <ioncore/selection.h>
17 #include <ioncore/strings.h>
23 #define EDLN_ALLOCUNIT 16
25 #define UPDATE(X) edln->ui_update(edln->uiptr, X, EDLN_UPDATE_STAT)
26 #define UPDATE_MOVED(X) edln->ui_update(edln->uiptr, X, EDLN_UPDATE_MOVED)
27 #define UPDATE_NEW() edln->ui_update(edln->uiptr, 0, EDLN_UPDATE_NEW)
30 #define ISALNUM iswalnum
31 #define CHAR_AT(P, N) str_wchar_at(P, N)
37 static bool edln_pspc(Edln
*edln
, int n
)
42 if(edln
->palloced
<edln
->psize
+1+n
){
44 pa
|=(EDLN_ALLOCUNIT
-1);
50 memmove(np
, edln
->p
, edln
->point
*sizeof(char));
51 memmove(np
+edln
->point
+n
, edln
->p
+edln
->point
,
52 (edln
->psize
-edln
->point
+1)*sizeof(char));
57 memmove(edln
->p
+edln
->point
+n
, edln
->p
+edln
->point
,
58 (edln
->psize
-edln
->point
+1)*sizeof(char));
61 if(edln
->mark
>edln
->point
)
71 static bool edln_rspc(Edln
*edln
, int n
)
76 if(n
+edln
->point
>=edln
->psize
)
77 n
=edln
->psize
-edln
->point
;
82 if((edln
->psize
+1-n
)<(edln
->palloced
&~(EDLN_ALLOCUNIT
-1))){
83 pa
=edln
->palloced
&~(EDLN_ALLOCUNIT
-1);
89 memmove(np
, edln
->p
, edln
->point
*sizeof(char));
90 memmove(np
+edln
->point
, edln
->p
+edln
->point
+n
,
91 (edln
->psize
-edln
->point
+1-n
)*sizeof(char));
97 memmove(edln
->p
+edln
->point
, edln
->p
+edln
->point
+n
,
98 (edln
->psize
-edln
->point
+1-n
)*sizeof(char));
102 if(edln
->mark
>edln
->point
)
110 static void edln_clearstr(Edln
*edln
)
121 static bool edln_initstr(Edln
*edln
, const char *p
)
125 al
=(l
+1)|(EDLN_ALLOCUNIT
-1);
127 edln
->p
=ALLOC_N(char, al
);
140 static bool edln_setstr(Edln
*edln
, const char *p
)
143 return edln_initstr(edln
, p
);
153 bool edln_insch(Edln
*edln
, char ch
)
155 if(edln_pspc(edln
, 1)){
156 edln
->p
[edln
->point
]=ch
;
158 UPDATE_MOVED(edln
->point
-1);
165 bool edln_ovrch(Edln
*edln
, char ch
)
168 return edln_insch(edln
, ch
);
173 bool edln_insstr(Edln
*edln
, const char *str
)
182 return edln_insstr_n(edln
, str
, l
);
186 bool edln_insstr_n(Edln
*edln
, const char *str
, int l
)
188 if(!edln_pspc(edln
, l
))
191 memmove(&(edln
->p
[edln
->point
]), str
, l
);
193 UPDATE_MOVED(edln
->point
-l
);
205 static int do_edln_back(Edln
*edln
)
207 int l
=str_prevoff(edln
->p
, edln
->point
);
213 void edln_back(Edln
*edln
)
217 /*if(edln->point!=p)*/
218 UPDATE_MOVED(edln
->point
);
222 static int do_edln_forward(Edln
*edln
)
224 int l
=str_nextoff(edln
->p
, edln
->point
);
230 void edln_forward(Edln
*edln
)
233 do_edln_forward(edln
);
234 /*if(edln->point!=p)*/
239 void edln_bol(Edln
*edln
)
248 void edln_eol(Edln
*edln
)
252 if(edln
->point
!=edln
->psize
){
253 edln
->point
=edln
->psize
;
259 void edln_bskip_word(Edln
*edln
)
264 while(edln
->point
>0){
265 n
=do_edln_back(edln
);
266 c
=CHAR_AT(edln
->p
+edln
->point
, n
);
270 UPDATE_MOVED(edln
->point
);
274 while(edln
->point
>0){
276 n
=do_edln_back(edln
);
277 c
=CHAR_AT(edln
->p
+edln
->point
, n
);
284 UPDATE_MOVED(edln
->point
);
288 void edln_skip_word(Edln
*edln
)
290 int oldp
=edln
->point
;
293 while(edln
->point
<edln
->psize
){
294 c
=CHAR_AT(edln
->p
+edln
->point
, edln
->psize
-edln
->point
);
297 if(do_edln_forward(edln
)==0)
304 while(edln
->point
<edln
->psize
){
305 c
=CHAR_AT(edln
->p
+edln
->point
, edln
->psize
-edln
->point
);
308 if(do_edln_forward(edln
)==0)
315 void edln_set_point(Edln
*edln
, int point
)
321 else if(point
>edln
->psize
)
339 void edln_delete(Edln
*edln
)
341 int left
=edln
->psize
-edln
->point
;
347 l
=str_nextoff(edln
->p
, edln
->point
);
356 void edln_backspace(Edln
*edln
)
361 n
=do_edln_back(edln
);
364 UPDATE_MOVED(edln
->point
);
368 void edln_kill_to_eol(Edln
*edln
)
370 edln_rspc(edln
, edln
->psize
-edln
->point
);
375 void edln_kill_to_bol(Edln
*edln
)
386 void edln_kill_line(Edln
*edln
)
389 edln_kill_to_eol(edln
);
394 void edln_kill_word(Edln
*edln
)
396 int oldp
=edln
->point
;
398 edln_skip_word(edln
);
400 if(edln
->point
==oldp
)
411 void edln_bkill_word(Edln
*edln
)
413 int oldp
=edln
->point
;
415 edln_bskip_word(edln
);
417 if(edln
->point
==oldp
)
420 edln_rspc(edln
, oldp
-edln
->point
);
431 static void do_set_mark(Edln
*edln
, int nm
)
436 UPDATE(m
< edln
->point
? m
: edln
->point
);
440 void edln_set_mark(Edln
*edln
)
442 do_set_mark(edln
, edln
->point
);
446 void edln_clear_mark(Edln
*edln
)
448 do_set_mark(edln
, -1);
452 static void edln_do_copy(Edln
*edln
, bool del
)
456 if(edln
->mark
<0 || edln
->point
==edln
->mark
)
459 if(edln
->point
<edln
->mark
){
467 ioncore_set_selection_n(edln
->p
+beg
, end
-beg
);
471 edln_rspc(edln
, end
-beg
);
479 void edln_cut(Edln
*edln
)
481 edln_do_copy(edln
, TRUE
);
485 void edln_copy(Edln
*edln
)
487 edln_do_copy(edln
, FALSE
);
497 bool edln_set_context(Edln
*edln
, const char *str
)
499 char *s
=scat(str
, ":"), *cp
;
505 while(cp
!=NULL
&& *(cp
+1)!='\0'){
510 if(edln
->context
!=NULL
)
518 static void edln_do_set_hist(Edln
*edln
, int e
, bool match
)
520 const char *str
=mod_query_history_get(e
), *s2
;
524 edln
->tmp_palloced
=edln
->palloced
;
528 /* Skip context label */
534 edln_setstr(edln
, str
);
536 ? minof(edln
->point
, edln
->psize
)
539 edln
->modified
=FALSE
;
545 static int search(Edln
*edln
, int from
, bool bwd
, bool match
)
549 if(match
&& edln
->point
>0){
551 char tmp
=edln
->p
[edln
->point
];
552 edln
->p
[edln
->point
]='\0';
553 tmpstr
=scat(edln
->context
? edln
->context
: "*:", edln
->p
);
554 edln
->p
[edln
->point
]=tmp
;
556 return edln
->histent
;
557 e
=mod_query_history_search(tmpstr
, from
, bwd
);
560 e
=mod_query_history_search(edln
->context
, from
, bwd
);
567 void edln_history_prev(Edln
*edln
, bool match
)
569 int e
=search(edln
, edln
->histent
+1, FALSE
, match
);
571 edln_do_set_hist(edln
, e
, match
);
575 void edln_history_next(Edln
*edln
, bool match
)
582 e
=search(edln
, edln
->histent
-1, TRUE
, match
);
585 edln_do_set_hist(edln
, e
, match
);
591 edln
->palloced
=edln
->tmp_palloced
;
593 edln
->psize
=(edln
->p
==NULL
? 0 : strlen(edln
->p
));
594 edln
->point
=edln
->psize
;
608 bool edln_init(Edln
*edln
, const char *p
)
613 if(!edln_initstr(edln
, p
))
616 edln
->point
=edln
->psize
;
619 edln
->modified
=FALSE
;
620 edln
->completion_handler
=NULL
;
628 void edln_deinit(Edln
*edln
)
634 if(edln
->tmp_p
!=NULL
){
638 if(edln
->context
!=NULL
){
645 static const char *ctx(Edln
*edln
)
647 if(edln
->context
!=NULL
)
648 return edln
->context
;
654 char* edln_finish(Edln
*edln
)
656 char *p
=edln
->p
, *hist
;
659 libtu_asprintf(&hist
, "%s%s", ctx(edln
), p
);
661 mod_query_history_push_(hist
);
665 edln
->psize
=edln
->palloced
=0;
668 return str_stripws(p
);