4 * Copyright (c) Tuomo Valkonen 1999-2008.
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);