Add support for tab-completion when selecting by rule
[alpine.git] / pith / hist.c
blobedbe9c93041d22d9df93772c5f38e560f91b551c
1 /*
2 * ========================================================================
3 * Copyright 2013-2022 Eduardo Chappa
4 * Copyright 2006-2007 University of Washington
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
16 #include "../pith/headers.h"
17 #include "../pith/conf.h"
18 #include "../pith/hist.h"
21 void
22 init_hist(HISTORY_S **history, int histsize)
24 size_t l;
26 if(!history)
27 return;
29 if(!*history){
30 l = sizeof(**history) + histsize * sizeof(ONE_HIST_S);
31 *history = (HISTORY_S *) fs_get(l);
32 memset(*history, 0, l);
33 (*history)->histsize = histsize;
34 (*history)->origindex = histsize - 1;
35 add_to_histlist(history);
38 (*history)->curindex = (*history)->origindex;
42 void
43 free_hist(HISTORY_S **history)
45 int i;
47 if(history && *history){
48 for(i = 0; i < (*history)->histsize; i++)
49 if((*history)->hist[i]){
50 if((*history)->hist[i]->str)
51 fs_give((void **) &(*history)->hist[i]->str);
52 (*history)->hist[i]->cntxt = NULL; /* taken care of elsewhere */
53 fs_give((void **) &(*history)->hist[i]);
56 fs_give((void **) history);
60 char *
61 hist_in_pos(int pos, char **list, int llen, HISTORY_S *hist, int n)
63 if(pos < 0 || pos > llen + n)
64 return NULL;
66 if(pos < llen)
67 return list[pos];
69 hist->curindex = (hist->origindex + n - pos + llen) % hist->histsize;
70 return((hist->hist[hist->curindex] && hist->hist[hist->curindex]->str)
71 ? hist->hist[hist->curindex]->str : NULL);
74 char *
75 get_prev_hist(HISTORY_S *history, char *savethis, unsigned saveflags, void *cntxt)
77 int nextcurindex;
78 size_t l;
80 if(!(history && history->histsize > 0))
81 return NULL;
83 nextcurindex = (history->curindex + 1) % history->histsize;
85 /* already at start of history */
86 if(nextcurindex == history->origindex
87 || !(history->hist[nextcurindex] && history->hist[nextcurindex]->str
88 && history->hist[nextcurindex]->str[0]))
89 return NULL;
91 /* save what user typed */
92 if(history->curindex == history->origindex){
93 if(!savethis)
94 savethis = "";
96 if(!history->hist[history->origindex]){
97 history->hist[history->origindex] = (ONE_HIST_S *) fs_get(sizeof(ONE_HIST_S));
98 memset(history->hist[history->origindex], 0, sizeof(ONE_HIST_S));
101 if(history->hist[history->origindex]->str){
102 if(strlen(history->hist[history->origindex]->str) < (l=strlen(savethis)))
103 fs_resize((void **) &history->hist[history->origindex]->str, l+1);
105 strncpy(history->hist[history->origindex]->str, savethis, l+1);
106 history->hist[history->origindex]->str[l] = '\0';
108 else
109 history->hist[history->origindex]->str = cpystr(savethis);
111 history->hist[history->origindex]->flags = saveflags;
113 history->hist[history->origindex]->cntxt = cntxt;
116 history->curindex = nextcurindex;
118 return((history->hist[history->curindex] && history->hist[history->curindex]->str)
119 ? history->hist[history->curindex]->str : NULL);
123 char *
124 get_next_hist(HISTORY_S *history, char *savethis, unsigned saveflags, void *cntxt)
126 if(!(history && history->histsize > 0))
127 return NULL;
129 /* already at end (most recent) of history */
130 if(history->curindex == history->origindex)
131 return NULL;
133 history->curindex = (history->curindex + history->histsize - 1) % history->histsize;
135 return((history->hist[history->curindex] && history->hist[history->curindex]->str)
136 ? history->hist[history->curindex]->str : NULL);
140 void
141 save_hist(HISTORY_S *history, char *savethis, unsigned saveflags, void *cntxt)
143 size_t l;
144 int plusone;
146 if(!(history && history->histsize > 0))
147 return;
149 plusone = (history->origindex + 1) % history->histsize;
151 if(!history->hist[history->origindex]){
152 history->hist[history->origindex] = (ONE_HIST_S *) fs_get(sizeof(ONE_HIST_S));
153 memset(history->hist[history->origindex], 0, sizeof(ONE_HIST_S));
156 if(savethis && savethis[0]
157 && (!history->hist[history->origindex]->str
158 || strcmp(history->hist[history->origindex]->str, savethis)
159 || history->hist[history->origindex]->flags != saveflags
160 || history->hist[history->origindex]->cntxt != cntxt)
161 && !(history->hist[plusone] && history->hist[plusone]->str
162 && !strcmp(history->hist[plusone]->str, savethis)
163 && history->hist[history->origindex]->flags == saveflags
164 && history->hist[history->origindex]->cntxt == cntxt)){
165 if(history->hist[history->origindex]->str){
166 if(strlen(history->hist[history->origindex]->str) < (l=strlen(savethis)))
167 fs_resize((void **) &history->hist[history->origindex]->str, l+1);
169 strncpy(history->hist[history->origindex]->str, savethis, l+1);
170 history->hist[history->origindex]->str[l] = '\0';
172 else{
173 history->hist[history->origindex]->str = cpystr(savethis);
176 history->hist[history->origindex]->flags = saveflags;
177 history->hist[history->origindex]->cntxt = cntxt;
179 history->origindex = (history->origindex + history->histsize - 1) % history->histsize;
180 if(history->hist[history->origindex] && history->hist[history->origindex]->str)
181 history->hist[history->origindex]->str[0] = '\0';
187 * Returns count of items entered into history.
190 items_in_hist(HISTORY_S *history)
192 int i, cnt = 0;
194 if(history && history->histsize > 0)
195 for(i = 0; i < history->histsize; i++)
196 if(history->hist[i] && history->hist[i]->str)
197 cnt++;
199 return(cnt);
203 static HISTORY_S **histlist[100];
205 void
206 add_to_histlist(HISTORY_S **history)
208 int i;
210 if(history){
211 /* find empty slot */
212 for(i = 0; i < 100; i++)
213 if(!histlist[i])
214 break;
216 if(i < 100)
217 histlist[i] = history;
222 void
223 free_histlist(void)
225 int i;
227 for(i = 0; i < 100; i++)
228 if(histlist[i])
229 free_hist(histlist[i]);