]> git.decadent.org.uk Git - ion3.git/blob - mod_query/history.c
[svn-inject] Installing original source of ion3
[ion3.git] / mod_query / history.c
1 /*
2  * ion/mod_query/history.h
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
14 #include <ioncore/common.h>
15 #include <libextl/extl.h>
16
17 #include "history.h"
18
19
20 #define HISTORY_SIZE 1024
21
22
23 static int hist_head=HISTORY_SIZE;
24 static int hist_count=0;
25 static char *hist[HISTORY_SIZE];
26
27
28 int get_index(int i)
29 {
30     if(i<0 || i>=hist_count)
31         return -1;
32     return (hist_head+i)%HISTORY_SIZE;
33 }
34     
35
36 /*EXTL_DOC
37  * Push an entry into line editor history.
38  */
39 EXTL_EXPORT
40 bool mod_query_history_push(const char *str)
41 {
42     char *s=scopy(str);
43     
44     if(s==NULL)
45         return FALSE;
46     
47     mod_query_history_push_(s);
48     
49     return TRUE;
50 }
51
52
53 void mod_query_history_push_(char *str)
54 {
55     int ndx=mod_query_history_search(str, 0, FALSE);
56     
57     if(ndx==0){
58         return; /* First entry already */
59     }else if(ndx>0){
60         int i, j;
61         i=get_index(ndx);
62         free(hist[i]);
63         while(++ndx<hist_count){
64             j=get_index(ndx);
65             hist[i]=hist[j];
66             i=j;
67         }
68         hist_count--;
69     }
70     
71     hist_head--;
72     if(hist_head<0)
73         hist_head=HISTORY_SIZE-1;
74     
75     if(hist_count==HISTORY_SIZE)
76         free(hist[hist_head]);
77     else
78         hist_count++;
79     
80     hist[hist_head]=str;
81 }
82
83
84 /*EXTL_DOC
85  * Get entry at index \var{n} in line editor history, 0 being the latest.
86  */
87 EXTL_SAFE
88 EXTL_EXPORT
89 const char *mod_query_history_get(int n)
90 {
91     int i=get_index(n);
92     return (i<0 ? NULL : hist[i]);
93 }
94
95
96 /*EXTL_DOC
97  * Clear line editor history.
98  */
99 EXTL_EXPORT
100 void mod_query_history_clear()
101 {
102     while(hist_count!=0){
103         free(hist[hist_head]);
104         hist_count--;
105         if(++hist_head==HISTORY_SIZE)
106             hist_head=0;
107     }
108     hist_head=HISTORY_SIZE;
109 }
110
111
112
113 static bool match(const char *h, const char *b)
114 {
115     const char *h_;
116     
117     if(b==NULL)
118         return TRUE;
119     
120     /* Special case: search in any context. */
121     if(*b=='*' && *(b+1)==':'){
122         b=b+2;
123         h_=strchr(h, ':');
124         if(h_!=NULL)
125             h=h_+1;
126     }
127         
128     return (strncmp(h, b, strlen(b))==0);
129 }
130
131
132 static const char *skip_colon(const char *s)
133 {
134     const char *p=strchr(s, ':');
135     return (p!=NULL ? p+1 : s);
136 }
137
138
139 /*EXTL_DOC
140  * Try to find matching history entry. Returns -1 if none was
141  * found. The parameter \var{from} specifies where to start 
142  * searching from, and \var{bwd} causes backward search from
143  * that point.
144  */
145 EXTL_SAFE
146 EXTL_EXPORT
147 int mod_query_history_search(const char *s, int from, bool bwd)
148 {
149     while(1){
150         int i=get_index(from);
151         if(i<0)
152             return -1;
153         if(match(hist[i], s))
154             return from;
155         if(bwd)
156             from--;
157         else
158             from++;
159     }
160 }
161
162
163 uint mod_query_history_complete(const char *s, char ***h_ret)
164 {
165     char **h=ALLOC_N(char *, hist_count);
166     int i, n=0;
167     
168     if(h==NULL)
169         return 0;
170     
171     for(i=0; i<hist_count; i++){
172         int j=get_index(i);
173         if(j<0)
174             break;
175         if(match(hist[j], s)){
176             h[n]=scopy(skip_colon(hist[j]));
177             if(h[n]!=NULL)
178                 n++;
179         }
180     }
181     
182     if(n==0)
183         free(h);
184     else
185         *h_ret=h;
186     
187     return n;
188 }
189
190
191 /*EXTL_DOC
192  * Return table of history entries.
193  */
194 EXTL_SAFE
195 EXTL_EXPORT
196 ExtlTab mod_query_history_table()
197 {
198     ExtlTab tab=extl_create_table();
199     int i;
200
201     for(i=0; i<hist_count; i++){
202         int j=get_index(i);
203         extl_table_seti_s(tab, i+1, hist[j]);
204     }
205     
206     return tab;
207 }