4 * Copyright (c) Tuomo Valkonen 1999-2007.
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
26 edln->ui_update(edln->uiptr, X, 0)
28 #define UPDATE_MOVED(X) \
29 edln->ui_update(edln->uiptr, X, EDLN_UPDATE_MOVED)
31 #define UPDATE_CHANGED(X) \
32 edln->ui_update(edln->uiptr, X, \
33 EDLN_UPDATE_MOVED|EDLN_UPDATE_CHANGED)
35 #define UPDATE_CHANGED_NOMOVE(X) \
36 edln->ui_update(edln->uiptr, X, \
39 #define UPDATE_NEW() \
40 edln->ui_update(edln->uiptr, 0, \
41 EDLN_UPDATE_NEW|EDLN_UPDATE_MOVED|EDLN_UPDATE_CHANGED)
44 #define ISALNUM iswalnum
45 #define CHAR_AT(P, N) str_wchar_at(P, N)
51 static bool edln_pspc(Edln *edln, int n)
56 if(edln->palloced<edln->psize+1+n){
58 pa|=(EDLN_ALLOCUNIT-1);
64 memmove(np, edln->p, edln->point*sizeof(char));
65 memmove(np+edln->point+n, edln->p+edln->point,
66 (edln->psize-edln->point+1)*sizeof(char));
71 memmove(edln->p+edln->point+n, edln->p+edln->point,
72 (edln->psize-edln->point+1)*sizeof(char));
75 if(edln->mark>edln->point)
85 static bool edln_rspc(Edln *edln, int n)
90 if(n+edln->point>=edln->psize)
91 n=edln->psize-edln->point;
96 if((edln->psize+1-n)<(edln->palloced&~(EDLN_ALLOCUNIT-1))){
97 pa=edln->palloced&~(EDLN_ALLOCUNIT-1);
103 memmove(np, edln->p, edln->point*sizeof(char));
104 memmove(np+edln->point, edln->p+edln->point+n,
105 (edln->psize-edln->point+1-n)*sizeof(char));
111 memmove(edln->p+edln->point, edln->p+edln->point+n,
112 (edln->psize-edln->point+1-n)*sizeof(char));
116 if(edln->mark>edln->point)
124 static void edln_clearstr(Edln *edln)
135 static bool edln_initstr(Edln *edln, const char *p)
139 al=(l+1)|(EDLN_ALLOCUNIT-1);
141 edln->p=ALLOC_N(char, al);
154 static bool edln_setstr(Edln *edln, const char *p)
157 return edln_initstr(edln, p);
167 bool edln_insstr(Edln *edln, const char *str)
176 return edln_insstr_n(edln, str, l, TRUE, TRUE);
180 bool edln_insstr_n(Edln *edln, const char *str, int l,
181 bool update, bool movepoint)
183 if(!edln_pspc(edln, l))
186 memmove(&(edln->p[edln->point]), str, l);
190 UPDATE_CHANGED(edln->point-l);
193 UPDATE_CHANGED_NOMOVE(edln->point-l);
206 bool edln_transpose_chars(Edln *edln)
211 if((edln->point==0) || (edln->psize<2))
215 if(edln->point==edln->psize)
216 pos=pos-str_prevoff(edln->p, edln->point);
218 off1=str_nextoff(edln->p, pos);
219 off2=str_prevoff(edln->p, pos);
221 buf=ALLOC_N(char, off2);
224 memmove(buf, &(edln->p[pos-off2]), off2);
225 memmove(&(edln->p[pos-off2]), &(edln->p[pos]), off1);
226 memmove(&(edln->p[pos-off2+off1]), buf, off2);
229 if(edln->point!=edln->psize)
237 bool edln_transpose_words(Edln *edln)
239 int m1, m2, m3, m4, off1, off2, oldp;
242 if((edln->point==edln->psize) || (edln->psize<3))
246 edln_bskip_word(edln);
248 edln_skip_word(edln);
250 edln_skip_word(edln);
254 edln_bskip_word(edln);
262 buf=ALLOC_N(char, m4-m1);
265 memmove(buf, &(edln->p[m3]), off1);
266 memmove(buf+off1, &(edln->p[m2]), off2);
267 memmove(buf+off1+off2, &(edln->p[m1]), m2-m1);
268 memmove(&(edln->p[m1]), buf, m4-m1);
277 UPDATE_MOVED(edln->point);
288 static int do_edln_back(Edln *edln)
290 int l=str_prevoff(edln->p, edln->point);
296 void edln_back(Edln *edln)
300 /*if(edln->point!=p)*/
301 UPDATE_MOVED(edln->point);
305 static int do_edln_forward(Edln *edln)
307 int l=str_nextoff(edln->p, edln->point);
313 void edln_forward(Edln *edln)
316 do_edln_forward(edln);
317 /*if(edln->point!=p)*/
322 void edln_bol(Edln *edln)
331 void edln_eol(Edln *edln)
335 if(edln->point!=edln->psize){
336 edln->point=edln->psize;
342 void edln_bskip_word(Edln *edln)
347 while(edln->point>0){
348 n=do_edln_back(edln);
349 c=CHAR_AT(edln->p+edln->point, n);
353 UPDATE_MOVED(edln->point);
357 while(edln->point>0){
359 n=do_edln_back(edln);
360 c=CHAR_AT(edln->p+edln->point, n);
367 UPDATE_MOVED(edln->point);
371 void edln_skip_word(Edln *edln)
373 int oldp=edln->point;
376 while(edln->point<edln->psize){
377 c=CHAR_AT(edln->p+edln->point, edln->psize-edln->point);
380 if(do_edln_forward(edln)==0)
387 while(edln->point<edln->psize){
388 c=CHAR_AT(edln->p+edln->point, edln->psize-edln->point);
391 if(do_edln_forward(edln)==0)
398 void edln_set_point(Edln *edln, int point)
404 else if(point>edln->psize)
422 void edln_delete(Edln *edln)
424 int left=edln->psize-edln->point;
430 l=str_nextoff(edln->p, edln->point);
435 UPDATE_CHANGED_NOMOVE(edln->point);
439 void edln_backspace(Edln *edln)
444 n=do_edln_back(edln);
447 UPDATE_CHANGED(edln->point);
451 void edln_kill_to_eol(Edln *edln)
453 edln_rspc(edln, edln->psize-edln->point);
454 UPDATE_CHANGED_NOMOVE(edln->point);
458 void edln_kill_to_bol(Edln *edln)
469 void edln_kill_line(Edln *edln)
472 edln_kill_to_eol(edln);
477 void edln_kill_word(Edln *edln)
479 int oldp=edln->point;
481 edln_skip_word(edln);
483 if(edln->point==oldp)
490 UPDATE_CHANGED_NOMOVE(oldp);
494 void edln_bkill_word(Edln *edln)
496 int oldp=edln->point;
498 edln_bskip_word(edln);
500 if(edln->point==oldp)
503 edln_rspc(edln, oldp-edln->point);
504 UPDATE_CHANGED(edln->point);
514 static void do_set_mark(Edln *edln, int nm)
519 UPDATE(m < edln->point ? m : edln->point);
523 void edln_set_mark(Edln *edln)
525 do_set_mark(edln, edln->point);
529 void edln_clear_mark(Edln *edln)
531 do_set_mark(edln, -1);
535 static void edln_do_copy(Edln *edln, bool del)
539 if(edln->mark<0 || edln->point==edln->mark)
542 if(edln->point<edln->mark){
550 ioncore_set_selection_n(edln->p+beg, end-beg);
554 edln_rspc(edln, end-beg);
562 void edln_cut(Edln *edln)
564 edln_do_copy(edln, TRUE);
568 void edln_copy(Edln *edln)
570 edln_do_copy(edln, FALSE);
580 bool edln_set_context(Edln *edln, const char *str)
582 char *s=scat(str, ":"), *cp;
588 while(cp!=NULL && *(cp+1)!='\0'){
593 if(edln->context!=NULL)
601 static void edln_do_set_hist(Edln *edln, int e, bool match)
603 const char *str=mod_query_history_get(e), *s2;
607 edln->tmp_palloced=edln->palloced;
611 /* Skip context label */
617 edln_setstr(edln, str);
619 ? minof(edln->point, edln->psize)
622 edln->modified=FALSE;
628 static char *history_search_str(Edln *edln)
631 char tmp=edln->p[edln->point];
632 edln->p[edln->point]='\0';
633 sstr=scat(edln->context ? edln->context : "*:", edln->p);
634 edln->p[edln->point]=tmp;
639 static int search(Edln *edln, int from, bool bwd, bool match)
643 if(match && edln->point>0){
644 char *tmpstr=history_search_str(edln);
646 return edln->histent;
647 e=mod_query_history_search(tmpstr, from, bwd, FALSE);
650 e=mod_query_history_search(edln->context, from, bwd, FALSE);
657 void edln_history_prev(Edln *edln, bool match)
659 int e=search(edln, edln->histent+1, FALSE, match);
661 edln_do_set_hist(edln, e, match);
665 void edln_history_next(Edln *edln, bool match)
672 e=search(edln, edln->histent-1, TRUE, match);
675 edln_do_set_hist(edln, e, match);
681 edln->palloced=edln->tmp_palloced;
683 edln->psize=(edln->p==NULL ? 0 : strlen(edln->p));
684 edln->point=edln->psize;
692 uint edln_history_matches(Edln *edln, char ***h_ret)
694 char *tmpstr=history_search_str(edln);
702 ret=mod_query_history_complete(tmpstr, h_ret);
716 bool edln_init(Edln *edln, const char *p)
721 if(!edln_initstr(edln, p))
724 edln->point=edln->psize;
727 edln->modified=FALSE;
735 void edln_deinit(Edln *edln)
741 if(edln->tmp_p!=NULL){
745 if(edln->context!=NULL){
752 static const char *ctx(Edln *edln)
754 if(edln->context!=NULL)
755 return edln->context;
761 char* edln_finish(Edln *edln)
763 char *p=edln->p, *hist;
766 libtu_asprintf(&hist, "%s%s", ctx(edln), p);
768 mod_query_history_push_(hist);
772 edln->psize=edln->palloced=0;
775 return str_stripws(p);