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