4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
11 #include <libtu/minmax.h>
12 #include <ioncore/common.h>
13 #include <ioncore/selection.h>
14 #include <ioncore/strings.h>
20 #define EDLN_ALLOCUNIT 16
23 edln->ui_update(edln->uiptr, X, 0)
25 #define UPDATE_MOVED(X) \
26 edln->ui_update(edln->uiptr, X, EDLN_UPDATE_MOVED)
28 #define UPDATE_CHANGED(X) \
29 edln->ui_update(edln->uiptr, X, \
30 EDLN_UPDATE_MOVED|EDLN_UPDATE_CHANGED)
32 #define UPDATE_CHANGED_NOMOVE(X) \
33 edln->ui_update(edln->uiptr, X, \
36 #define UPDATE_NEW() \
37 edln->ui_update(edln->uiptr, 0, \
38 EDLN_UPDATE_NEW|EDLN_UPDATE_MOVED|EDLN_UPDATE_CHANGED)
41 #define ISALNUM iswalnum
42 #define CHAR_AT(P, N) str_wchar_at(P, N)
48 static bool edln_pspc(Edln
*edln
, int n
)
53 if(edln
->palloced
<edln
->psize
+1+n
){
55 pa
|=(EDLN_ALLOCUNIT
-1);
61 memmove(np
, edln
->p
, edln
->point
*sizeof(char));
62 memmove(np
+edln
->point
+n
, edln
->p
+edln
->point
,
63 (edln
->psize
-edln
->point
+1)*sizeof(char));
68 memmove(edln
->p
+edln
->point
+n
, edln
->p
+edln
->point
,
69 (edln
->psize
-edln
->point
+1)*sizeof(char));
72 if(edln
->mark
>edln
->point
)
82 static bool edln_rspc(Edln
*edln
, int n
)
87 if(n
+edln
->point
>=edln
->psize
)
88 n
=edln
->psize
-edln
->point
;
93 if((edln
->psize
+1-n
)<(edln
->palloced
&~(EDLN_ALLOCUNIT
-1))){
94 pa
=edln
->palloced
&~(EDLN_ALLOCUNIT
-1);
100 memmove(np
, edln
->p
, edln
->point
*sizeof(char));
101 memmove(np
+edln
->point
, edln
->p
+edln
->point
+n
,
102 (edln
->psize
-edln
->point
+1-n
)*sizeof(char));
108 memmove(edln
->p
+edln
->point
, edln
->p
+edln
->point
+n
,
109 (edln
->psize
-edln
->point
+1-n
)*sizeof(char));
113 if(edln
->mark
>edln
->point
)
121 static void edln_clearstr(Edln
*edln
)
132 static bool edln_initstr(Edln
*edln
, const char *p
)
136 al
=(l
+1)|(EDLN_ALLOCUNIT
-1);
138 edln
->p
=ALLOC_N(char, al
);
151 static bool edln_setstr(Edln
*edln
, const char *p
)
154 return edln_initstr(edln
, p
);
164 bool edln_insstr(Edln
*edln
, const char *str
)
173 return edln_insstr_n(edln
, str
, l
, TRUE
, TRUE
);
177 bool edln_insstr_n(Edln
*edln
, const char *str
, int l
,
178 bool update
, bool movepoint
)
180 if(!edln_pspc(edln
, l
))
183 memmove(&(edln
->p
[edln
->point
]), str
, l
);
187 UPDATE_CHANGED(edln
->point
-l
);
190 UPDATE_CHANGED_NOMOVE(edln
->point
-l
);
203 bool edln_transpose_chars(Edln
*edln
)
208 if((edln
->point
==0) || (edln
->psize
<2))
212 if(edln
->point
==edln
->psize
)
213 pos
=pos
-str_prevoff(edln
->p
, edln
->point
);
215 off1
=str_nextoff(edln
->p
, pos
);
216 off2
=str_prevoff(edln
->p
, pos
);
218 buf
=ALLOC_N(char, off2
);
221 memmove(buf
, &(edln
->p
[pos
-off2
]), off2
);
222 memmove(&(edln
->p
[pos
-off2
]), &(edln
->p
[pos
]), off1
);
223 memmove(&(edln
->p
[pos
-off2
+off1
]), buf
, off2
);
226 if(edln
->point
!=edln
->psize
)
234 bool edln_transpose_words(Edln
*edln
)
236 int m1
, m2
, m3
, m4
, off1
, off2
, oldp
;
239 if((edln
->point
==edln
->psize
) || (edln
->psize
<3))
243 edln_bskip_word(edln
);
245 edln_skip_word(edln
);
247 edln_skip_word(edln
);
251 edln_bskip_word(edln
);
259 buf
=ALLOC_N(char, m4
-m1
);
262 memmove(buf
, &(edln
->p
[m3
]), off1
);
263 memmove(buf
+off1
, &(edln
->p
[m2
]), off2
);
264 memmove(buf
+off1
+off2
, &(edln
->p
[m1
]), m2
-m1
);
265 memmove(&(edln
->p
[m1
]), buf
, m4
-m1
);
274 UPDATE_MOVED(edln
->point
);
285 static int do_edln_back(Edln
*edln
)
287 int l
=str_prevoff(edln
->p
, edln
->point
);
293 void edln_back(Edln
*edln
)
297 /*if(edln->point!=p)*/
298 UPDATE_MOVED(edln
->point
);
302 static int do_edln_forward(Edln
*edln
)
304 int l
=str_nextoff(edln
->p
, edln
->point
);
310 void edln_forward(Edln
*edln
)
313 do_edln_forward(edln
);
314 /*if(edln->point!=p)*/
319 void edln_bol(Edln
*edln
)
328 void edln_eol(Edln
*edln
)
332 if(edln
->point
!=edln
->psize
){
333 edln
->point
=edln
->psize
;
339 void edln_bskip_word(Edln
*edln
)
344 while(edln
->point
>0){
345 n
=do_edln_back(edln
);
346 c
=CHAR_AT(edln
->p
+edln
->point
, n
);
350 UPDATE_MOVED(edln
->point
);
354 while(edln
->point
>0){
356 n
=do_edln_back(edln
);
357 c
=CHAR_AT(edln
->p
+edln
->point
, n
);
364 UPDATE_MOVED(edln
->point
);
368 void edln_skip_word(Edln
*edln
)
370 int oldp
=edln
->point
;
373 while(edln
->point
<edln
->psize
){
374 c
=CHAR_AT(edln
->p
+edln
->point
, edln
->psize
-edln
->point
);
377 if(do_edln_forward(edln
)==0)
384 while(edln
->point
<edln
->psize
){
385 c
=CHAR_AT(edln
->p
+edln
->point
, edln
->psize
-edln
->point
);
388 if(do_edln_forward(edln
)==0)
395 void edln_set_point(Edln
*edln
, int point
)
401 else if(point
>edln
->psize
)
419 void edln_delete(Edln
*edln
)
421 int left
=edln
->psize
-edln
->point
;
427 l
=str_nextoff(edln
->p
, edln
->point
);
432 UPDATE_CHANGED_NOMOVE(edln
->point
);
436 void edln_backspace(Edln
*edln
)
441 n
=do_edln_back(edln
);
444 UPDATE_CHANGED(edln
->point
);
448 void edln_kill_to_eol(Edln
*edln
)
450 edln_rspc(edln
, edln
->psize
-edln
->point
);
451 UPDATE_CHANGED_NOMOVE(edln
->point
);
455 void edln_kill_to_bol(Edln
*edln
)
466 void edln_kill_line(Edln
*edln
)
469 edln_kill_to_eol(edln
);
474 void edln_kill_word(Edln
*edln
)
476 int oldp
=edln
->point
;
478 edln_skip_word(edln
);
480 if(edln
->point
==oldp
)
487 UPDATE_CHANGED_NOMOVE(oldp
);
491 void edln_bkill_word(Edln
*edln
)
493 int oldp
=edln
->point
;
495 edln_bskip_word(edln
);
497 if(edln
->point
==oldp
)
500 edln_rspc(edln
, oldp
-edln
->point
);
501 UPDATE_CHANGED(edln
->point
);
511 static void do_set_mark(Edln
*edln
, int nm
)
516 UPDATE(m
< edln
->point
? m
: edln
->point
);
520 void edln_set_mark(Edln
*edln
)
522 do_set_mark(edln
, edln
->point
);
526 void edln_clear_mark(Edln
*edln
)
528 do_set_mark(edln
, -1);
532 static void edln_do_copy(Edln
*edln
, bool del
)
536 if(edln
->mark
<0 || edln
->point
==edln
->mark
)
539 if(edln
->point
<edln
->mark
){
547 ioncore_set_selection_n(edln
->p
+beg
, end
-beg
);
551 edln_rspc(edln
, end
-beg
);
559 void edln_cut(Edln
*edln
)
561 edln_do_copy(edln
, TRUE
);
565 void edln_copy(Edln
*edln
)
567 edln_do_copy(edln
, FALSE
);
577 bool edln_set_context(Edln
*edln
, const char *str
)
579 char *s
=scat(str
, ":"), *cp
;
585 while(cp
!=NULL
&& *(cp
+1)!='\0'){
590 if(edln
->context
!=NULL
)
598 static void edln_do_set_hist(Edln
*edln
, int e
, bool match
)
600 const char *str
=mod_query_history_get(e
), *s2
;
604 edln
->tmp_palloced
=edln
->palloced
;
608 /* Skip context label */
614 edln_setstr(edln
, str
);
616 ? minof(edln
->point
, edln
->psize
)
619 edln
->modified
=FALSE
;
625 static char *history_search_str(Edln
*edln
)
628 char tmp
=edln
->p
[edln
->point
];
629 edln
->p
[edln
->point
]='\0';
630 sstr
=scat(edln
->context
? edln
->context
: "*:", edln
->p
);
631 edln
->p
[edln
->point
]=tmp
;
636 static int search(Edln
*edln
, int from
, bool bwd
, bool match
)
640 if(match
&& edln
->point
>0){
641 char *tmpstr
=history_search_str(edln
);
643 return edln
->histent
;
644 e
=mod_query_history_search(tmpstr
, from
, bwd
, FALSE
);
647 e
=mod_query_history_search(edln
->context
, from
, bwd
, FALSE
);
654 void edln_history_prev(Edln
*edln
, bool match
)
656 int e
=search(edln
, edln
->histent
+1, FALSE
, match
);
658 edln_do_set_hist(edln
, e
, match
);
662 void edln_history_next(Edln
*edln
, bool match
)
669 e
=search(edln
, edln
->histent
-1, TRUE
, match
);
672 edln_do_set_hist(edln
, e
, match
);
678 edln
->palloced
=edln
->tmp_palloced
;
680 edln
->psize
=(edln
->p
==NULL
? 0 : strlen(edln
->p
));
681 edln
->point
=edln
->psize
;
689 uint
edln_history_matches(Edln
*edln
, char ***h_ret
)
691 char *tmpstr
=history_search_str(edln
);
699 ret
=mod_query_history_complete(tmpstr
, h_ret
);
713 bool edln_init(Edln
*edln
, const char *p
)
718 if(!edln_initstr(edln
, p
))
721 edln
->point
=edln
->psize
;
724 edln
->modified
=FALSE
;
732 void edln_deinit(Edln
*edln
)
738 if(edln
->tmp_p
!=NULL
){
742 if(edln
->context
!=NULL
){
749 static const char *ctx(Edln
*edln
)
751 if(edln
->context
!=NULL
)
752 return edln
->context
;
758 char* edln_finish(Edln
*edln
)
760 char *p
=edln
->p
, *hist
;
763 libtu_asprintf(&hist
, "%s%s", ctx(edln
), p
);
765 mod_query_history_push_(hist
);
769 edln
->psize
=edln
->palloced
=0;
772 return str_stripws(p
);