]> git.decadent.org.uk Git - ion3.git/blob - mod_query/complete.c
[svn-inject] Installing original source of ion3
[ion3.git] / mod_query / complete.c
1 /*
2  * ion/mod_query/complete.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2006. 
5  *
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.
10  */
11
12 #include <string.h>
13 #include <ctype.h>
14 #include <string.h>
15 #include <limits.h>
16
17 #include <libtu/objp.h>
18 #include <ioncore/common.h>
19 #include "complete.h"
20 #include "edln.h"
21 #include "wedln.h"
22
23
24 /*{{{ Completion list processing */
25
26
27 static int str_common_part_l(const char *p1, const char *p2)
28 {
29     int i=0;
30     
31     while(1){
32         if(*p1=='\0' || *p1!=*p2)
33             break;
34         p1++; p2++; i++;
35     }
36     
37     return i;
38 }
39
40
41 /* Get length of part common to all completions
42  * and remove duplicates
43  */
44 static int get_common_part_rmdup(char **completions, int *ncomp)
45 {
46     int i, j, c=INT_MAX, c2;
47     
48     for(i=0, j=1; j<*ncomp; j++){
49         c2=str_common_part_l(completions[i], completions[j]);
50         if(c2<c)
51             c=c2;
52
53         if(completions[i][c2]=='\0' && completions[j][c2]=='\0'){
54             free(completions[j]);
55             completions[j]=NULL;
56             continue;
57         }
58         i++;
59         if(i!=j){
60             completions[i]=completions[j];
61             completions[j]=NULL;
62         }
63     }
64     *ncomp=i+1;
65     
66     return c;
67 }
68
69
70 static int compare(const void *p1, const void *p2)
71 {
72     const char **v1, **v2;
73     
74     v1=(const char **)p1;
75     v2=(const char **)p2;
76     return strcoll(*v1, *v2);
77 }
78
79
80 static void edln_reset(Edln *edln)
81 {
82     assert(edln->palloced>=1);
83     
84     edln->p[0]='\0';
85     edln->psize=0;
86     edln->point=0;
87     edln->mark=-1;
88     edln->histent=-1;
89 }
90
91
92 static void edln_do_set_completion(Edln *edln, const char *comp, int len,
93                                    const char *beg, const char *end)
94 {
95     edln_reset(edln);
96     
97     if(beg!=NULL)
98         edln_insstr_n(edln, beg, strlen(beg), FALSE, TRUE);
99     
100     if(len>0)
101         edln_insstr_n(edln, comp, len, FALSE, TRUE);
102         
103     if(end!=NULL)
104         edln_insstr_n(edln, end, strlen(end), FALSE, FALSE);
105     
106     if(edln->ui_update!=NULL){
107         edln->ui_update(edln->uiptr, 0,
108                         EDLN_UPDATE_MOVED|EDLN_UPDATE_CHANGED|
109                         EDLN_UPDATE_NEW);
110     }
111
112 }
113
114
115 void edln_set_completion(Edln *edln, const char *comp, 
116                          const char *beg, const char *end)
117 {
118     edln_do_set_completion(edln, comp, strlen(comp), beg, end);
119 }
120
121
122 int edln_do_completions(Edln *edln, char **completions, int ncomp,
123                         const char *beg, const char *end, bool setcommon,
124                         bool nosort)
125 {
126     int len;
127     int i;
128     
129     if(ncomp==0){
130         return 0;
131     }else if(ncomp==1){
132         len=strlen(completions[0]);
133     }else{
134         if(!nosort)
135             qsort(completions, ncomp, sizeof(char**), compare);
136         len=get_common_part_rmdup(completions, &ncomp);
137     }
138     
139     if(setcommon)
140         edln_do_set_completion(edln, completions[0], len, beg, end);
141     
142     return ncomp;
143 }
144
145
146 /*}}}*/
147
148
149 /*{{{ WComplProxy */
150
151
152 bool complproxy_init(WComplProxy *proxy, WEdln *wedln, int id, int cycle)
153 {
154     watch_init(&(proxy->wedln_watch));
155     if(!watch_setup(&(proxy->wedln_watch), (Obj*)wedln, NULL))
156         return FALSE;
157     
158     proxy->id=id;
159     proxy->cycle=cycle;
160     
161     return TRUE;
162 }
163
164
165 WComplProxy *create_complproxy(WEdln *wedln, int id, int cycle)
166 {
167     CREATEOBJ_IMPL(WComplProxy, complproxy, (p, wedln, id, cycle));
168 }
169
170
171 void complproxy_deinit(WComplProxy *proxy)
172 {
173     watch_reset(&(proxy->wedln_watch));
174 }
175
176
177 /*EXTL_DOC
178  * Set completion list of the \type{WEdln} that \var{proxy} refers to to
179  * \var{compls}, if it is still waiting for this completion run. The 
180  * numerical indexes of \var{compls} list the found completions. If the
181  * entry \var{common_beg} (\var{common_end}) exists, it gives an extra 
182  * common prefix (suffix) of all found completions.
183  */
184 EXTL_EXPORT_MEMBER
185 bool complproxy_set_completions(WComplProxy *proxy, ExtlTab compls)
186 {
187     WEdln *wedln=(WEdln*)proxy->wedln_watch.obj;
188     
189     if(wedln!=NULL){
190         if(wedln->compl_waiting_id==proxy->id){
191             wedln_set_completions(wedln, compls, proxy->cycle);
192             wedln->compl_current_id=proxy->id;
193             return TRUE;
194         }
195     }
196     
197     return FALSE;
198 }
199
200
201 EXTL_EXPORT
202 IMPLCLASS(WComplProxy, Obj, complproxy_deinit, NULL);
203
204
205 /*}}}*/
206