1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: hist.c 807 2007-11-09 01:21:33Z hubert@u.washington.edu $";
3 #endif
4
5 /*
6 * ========================================================================
7 * Copyright 2013-2021 Eduardo Chappa
8 * Copyright 2006-2007 University of Washington
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * ========================================================================
17 */
18
19
20 #include "../pith/headers.h"
21 #include "../pith/conf.h"
22 #include "../pith/hist.h"
23
24
25 void
init_hist(HISTORY_S ** history,int histsize)26 init_hist(HISTORY_S **history, int histsize)
27 {
28 size_t l;
29
30 if(!history)
31 return;
32
33 if(!*history){
34 l = sizeof(**history) + histsize * sizeof(ONE_HIST_S);
35 *history = (HISTORY_S *) fs_get(l);
36 memset(*history, 0, l);
37 (*history)->histsize = histsize;
38 (*history)->origindex = histsize - 1;
39 add_to_histlist(history);
40 }
41
42 (*history)->curindex = (*history)->origindex;
43 }
44
45
46 void
free_hist(HISTORY_S ** history)47 free_hist(HISTORY_S **history)
48 {
49 int i;
50
51 if(history && *history){
52 for(i = 0; i < (*history)->histsize; i++)
53 if((*history)->hist[i]){
54 if((*history)->hist[i]->str)
55 fs_give((void **) &(*history)->hist[i]->str);
56 (*history)->hist[i]->cntxt = NULL; /* taken care of elsewhere */
57 fs_give((void **) &(*history)->hist[i]);
58 }
59
60 fs_give((void **) history);
61 }
62 }
63
64 char *
hist_in_pos(int pos,char ** list,int llen,HISTORY_S * hist,int n)65 hist_in_pos(int pos, char **list, int llen, HISTORY_S *hist, int n)
66 {
67 if(pos < 0 || pos > llen + n)
68 return NULL;
69
70 if(pos < llen)
71 return list[pos];
72
73 hist->curindex = (hist->origindex + n - pos + llen) % hist->histsize;
74 return((hist->hist[hist->curindex] && hist->hist[hist->curindex]->str)
75 ? hist->hist[hist->curindex]->str : NULL);
76 }
77
78 char *
get_prev_hist(HISTORY_S * history,char * savethis,unsigned saveflags,void * cntxt)79 get_prev_hist(HISTORY_S *history, char *savethis, unsigned saveflags, void *cntxt)
80 {
81 int nextcurindex;
82 size_t l;
83
84 if(!(history && history->histsize > 0))
85 return NULL;
86
87 nextcurindex = (history->curindex + 1) % history->histsize;
88
89 /* already at start of history */
90 if(nextcurindex == history->origindex
91 || !(history->hist[nextcurindex] && history->hist[nextcurindex]->str
92 && history->hist[nextcurindex]->str[0]))
93 return NULL;
94
95 /* save what user typed */
96 if(history->curindex == history->origindex){
97 if(!savethis)
98 savethis = "";
99
100 if(!history->hist[history->origindex]){
101 history->hist[history->origindex] = (ONE_HIST_S *) fs_get(sizeof(ONE_HIST_S));
102 memset(history->hist[history->origindex], 0, sizeof(ONE_HIST_S));
103 }
104
105 if(history->hist[history->origindex]->str){
106 if(strlen(history->hist[history->origindex]->str) < (l=strlen(savethis)))
107 fs_resize((void **) &history->hist[history->origindex]->str, l+1);
108
109 strncpy(history->hist[history->origindex]->str, savethis, l+1);
110 history->hist[history->origindex]->str[l] = '\0';
111 }
112 else
113 history->hist[history->origindex]->str = cpystr(savethis);
114
115 history->hist[history->origindex]->flags = saveflags;
116
117 history->hist[history->origindex]->cntxt = cntxt;
118 }
119
120 history->curindex = nextcurindex;
121
122 return((history->hist[history->curindex] && history->hist[history->curindex]->str)
123 ? history->hist[history->curindex]->str : NULL);
124 }
125
126
127 char *
get_next_hist(HISTORY_S * history,char * savethis,unsigned saveflags,void * cntxt)128 get_next_hist(HISTORY_S *history, char *savethis, unsigned saveflags, void *cntxt)
129 {
130 if(!(history && history->histsize > 0))
131 return NULL;
132
133 /* already at end (most recent) of history */
134 if(history->curindex == history->origindex)
135 return NULL;
136
137 history->curindex = (history->curindex + history->histsize - 1) % history->histsize;
138
139 return((history->hist[history->curindex] && history->hist[history->curindex]->str)
140 ? history->hist[history->curindex]->str : NULL);
141 }
142
143
144 void
save_hist(HISTORY_S * history,char * savethis,unsigned saveflags,void * cntxt)145 save_hist(HISTORY_S *history, char *savethis, unsigned saveflags, void *cntxt)
146 {
147 size_t l;
148 int plusone;
149
150 if(!(history && history->histsize > 0))
151 return;
152
153 plusone = (history->origindex + 1) % history->histsize;
154
155 if(!history->hist[history->origindex]){
156 history->hist[history->origindex] = (ONE_HIST_S *) fs_get(sizeof(ONE_HIST_S));
157 memset(history->hist[history->origindex], 0, sizeof(ONE_HIST_S));
158 }
159
160 if(savethis && savethis[0]
161 && (!history->hist[history->origindex]->str
162 || strcmp(history->hist[history->origindex]->str, savethis)
163 || history->hist[history->origindex]->flags != saveflags
164 || history->hist[history->origindex]->cntxt != cntxt)
165 && !(history->hist[plusone] && history->hist[plusone]->str
166 && !strcmp(history->hist[plusone]->str, savethis)
167 && history->hist[history->origindex]->flags == saveflags
168 && history->hist[history->origindex]->cntxt == cntxt)){
169 if(history->hist[history->origindex]->str){
170 if(strlen(history->hist[history->origindex]->str) < (l=strlen(savethis)))
171 fs_resize((void **) &history->hist[history->origindex]->str, l+1);
172
173 strncpy(history->hist[history->origindex]->str, savethis, l+1);
174 history->hist[history->origindex]->str[l] = '\0';
175 }
176 else{
177 history->hist[history->origindex]->str = cpystr(savethis);
178 }
179
180 history->hist[history->origindex]->flags = saveflags;
181 history->hist[history->origindex]->cntxt = cntxt;
182
183 history->origindex = (history->origindex + history->histsize - 1) % history->histsize;
184 if(history->hist[history->origindex] && history->hist[history->origindex]->str)
185 history->hist[history->origindex]->str[0] = '\0';
186 }
187 }
188
189
190 /*
191 * Returns count of items entered into history.
192 */
193 int
items_in_hist(HISTORY_S * history)194 items_in_hist(HISTORY_S *history)
195 {
196 int i, cnt = 0;
197
198 if(history && history->histsize > 0)
199 for(i = 0; i < history->histsize; i++)
200 if(history->hist[i] && history->hist[i]->str)
201 cnt++;
202
203 return(cnt);
204 }
205
206
207 static HISTORY_S **histlist[100];
208
209 void
add_to_histlist(HISTORY_S ** history)210 add_to_histlist(HISTORY_S **history)
211 {
212 int i;
213
214 if(history){
215 /* find empty slot */
216 for(i = 0; i < 100; i++)
217 if(!histlist[i])
218 break;
219
220 if(i < 100)
221 histlist[i] = history;
222 }
223 }
224
225
226 void
free_histlist(void)227 free_histlist(void)
228 {
229 int i;
230
231 for(i = 0; i < 100; i++)
232 if(histlist[i])
233 free_hist(histlist[i]);
234 }
235