* Bug fix: Memory corruption when alpine searches for a string that is
[alpine.git] / pith / hist.c
blob24aa530ca18e3d1c9fd6a8a2372699f4642cfd94
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
5 /*
6 * ========================================================================
7 * Copyright 2013-2021 Eduardo Chappa
8 * Copyright 2006-2007 University of Washington
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
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
20 #include "../pith/headers.h"
21 #include "../pith/conf.h"
22 #include "../pith/hist.h"
25 void
26 init_hist(HISTORY_S **history, int histsize)
28 size_t l;
30 if(!history)
31 return;
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);
42 (*history)->curindex = (*history)->origindex;
46 void
47 free_hist(HISTORY_S **history)
49 int i;
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]);
60 fs_give((void **) history);
64 char *
65 hist_in_pos(int pos, char **list, int llen, HISTORY_S *hist, int n)
67 if(pos < 0 || pos > llen + n)
68 return NULL;
70 if(pos < llen)
71 return list[pos];
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);
78 char *
79 get_prev_hist(HISTORY_S *history, char *savethis, unsigned saveflags, void *cntxt)
81 int nextcurindex;
82 size_t l;
84 if(!(history && history->histsize > 0))
85 return NULL;
87 nextcurindex = (history->curindex + 1) % history->histsize;
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;
95 /* save what user typed */
96 if(history->curindex == history->origindex){
97 if(!savethis)
98 savethis = "";
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));
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);
109 strncpy(history->hist[history->origindex]->str, savethis, l+1);
110 history->hist[history->origindex]->str[l] = '\0';
112 else
113 history->hist[history->origindex]->str = cpystr(savethis);
115 history->hist[history->origindex]->flags = saveflags;
117 history->hist[history->origindex]->cntxt = cntxt;
120 history->curindex = nextcurindex;
122 return((history->hist[history->curindex] && history->hist[history->curindex]->str)
123 ? history->hist[history->curindex]->str : NULL);
127 char *
128 get_next_hist(HISTORY_S *history, char *savethis, unsigned saveflags, void *cntxt)
130 if(!(history && history->histsize > 0))
131 return NULL;
133 /* already at end (most recent) of history */
134 if(history->curindex == history->origindex)
135 return NULL;
137 history->curindex = (history->curindex + history->histsize - 1) % history->histsize;
139 return((history->hist[history->curindex] && history->hist[history->curindex]->str)
140 ? history->hist[history->curindex]->str : NULL);
144 void
145 save_hist(HISTORY_S *history, char *savethis, unsigned saveflags, void *cntxt)
147 size_t l;
148 int plusone;
150 if(!(history && history->histsize > 0))
151 return;
153 plusone = (history->origindex + 1) % history->histsize;
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));
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);
173 strncpy(history->hist[history->origindex]->str, savethis, l+1);
174 history->hist[history->origindex]->str[l] = '\0';
176 else{
177 history->hist[history->origindex]->str = cpystr(savethis);
180 history->hist[history->origindex]->flags = saveflags;
181 history->hist[history->origindex]->cntxt = cntxt;
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';
191 * Returns count of items entered into history.
194 items_in_hist(HISTORY_S *history)
196 int i, cnt = 0;
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++;
203 return(cnt);
207 static HISTORY_S **histlist[100];
209 void
210 add_to_histlist(HISTORY_S **history)
212 int i;
214 if(history){
215 /* find empty slot */
216 for(i = 0; i < 100; i++)
217 if(!histlist[i])
218 break;
220 if(i < 100)
221 histlist[i] = history;
226 void
227 free_histlist(void)
229 int i;
231 for(i = 0; i < 100; i++)
232 if(histlist[i])
233 free_hist(histlist[i]);