1 /* HISTORY.C    (c) Copyright Volker Bandke, 2003-2009               */
2 /*              Hercules Command History Processor                   */
3 
4 #include "hstdinc.h"
5 
6 #include "hercules.h"
7 #include "history.h"
8 
9 #define HISTORY_MAX 10
10 
11 #define CMD_SIZE 256  /* 32767 is way toooooo much */
12 
13 typedef struct history {
14   int number;
15   char *cmdline;
16   struct history *prev;
17   struct history *next;
18 } HISTORY;
19 
20 
21 BYTE history_count;          /* for line numbering */
22 
23 HISTORY *history_lines;      /* points to the beginning of history list (oldest command) */
24 HISTORY *history_lines_end;  /* points to the end of history list (most recent command) */
25 HISTORY *history_ptr;        /* points to last command retrieved by key press */
26 HISTORY *backup;             /* used for backuping last removed command */
27 
28 /* these 2 are used in panel.c to see if there was history command requested and
29    returns that command */
30 char *historyCmdLine;
31 int history_requested = 0;
32 
copy_to_historyCmdLine(char * cmdline)33 void copy_to_historyCmdLine(char* cmdline)
34 {
35   if (historyCmdLine) free(historyCmdLine);
36   historyCmdLine = malloc(strlen(cmdline)+1);
37   strcpy(historyCmdLine, cmdline);
38 }
39 
40 /* initialize environment */
history_init()41 int history_init() {
42   history_lines = NULL;
43   history_lines_end = NULL;
44   historyCmdLine = (char *) malloc(255);
45   history_requested = 0;
46   backup = NULL;
47   history_count = 0;
48   history_ptr = NULL;
49   return(0);
50 }
51 
52 /* add commandline to history list */
history_add(char * cmdline)53 int history_add(char *cmdline) {
54   HISTORY *tmp;
55 
56   /* if there is some backup line remaining, remove it */
57   if (backup != NULL) {
58     free(backup->cmdline);
59     free(backup);
60     backup = NULL;
61   }
62 
63   /* If last line is exactly the same as this line
64      ignore and return to caller */
65   if (history_lines != NULL && !strcmp(cmdline,history_lines_end->cmdline)) {
66       history_ptr = NULL;
67       return 0;
68   }
69 
70   /* allocate space and copy string */
71   tmp = (HISTORY*) malloc(sizeof(HISTORY));
72   tmp->cmdline = (char*) malloc(strlen(cmdline) + 1);
73   strcpy(tmp->cmdline, cmdline);
74   tmp->next = NULL;
75   tmp->prev = NULL;
76   tmp->number = ++history_count;
77 
78   if (history_lines == NULL) {
79     /* first in list */
80     history_lines = tmp;
81     history_lines_end = tmp;
82   }
83   else {
84     tmp->prev = history_lines_end;
85     history_lines_end->next = tmp;
86     history_lines_end = tmp;
87   }
88   history_ptr = NULL;
89 
90   if (history_count > HISTORY_MAX) {
91     /* if we are over maximum number of lines in history list, oldest one should be deleted
92        but we don't know whether history_remove will not be called, so oldest line is backuped and        not removed */
93     backup = history_lines;
94     history_lines = history_lines->next;
95     backup->next = NULL;
96     history_lines->prev = NULL;
97   }
98   return(0);
99 }
100 
101 /* show list of lines in history */
history_show()102 int history_show() {
103   HISTORY *tmp;
104   tmp = history_lines;
105   while (tmp != NULL) {
106     logmsg("%4d %s\n", tmp->number, tmp->cmdline);
107     tmp = tmp->next;
108   }
109   return(0);
110 }
111 
112 /* remove last line from history list (called only when history command was invoked) */
history_remove()113 int history_remove() {
114   HISTORY *tmp;
115 
116   if (history_lines == NULL)
117     return(0);
118   if (history_lines == history_lines_end) {
119     ASSERT(history_lines->next == NULL);
120     ASSERT(history_count == 1);
121     free(history_lines->cmdline);
122     free(history_lines);
123     history_lines = NULL;
124     history_lines_end = NULL;
125     history_count--;
126     return(0);
127   }
128   tmp = history_lines_end->prev;
129   tmp->next = NULL;
130   free(history_lines_end->cmdline);
131   free(history_lines_end);
132   history_count--;
133   history_lines_end = tmp;
134   if (backup != NULL) {
135     backup->next = history_lines;
136     history_lines->prev = backup;
137     history_lines = backup;
138     backup = NULL;
139   }
140   return(0);
141 }
142 
history_relative_line(int x)143 int history_relative_line(int x) {
144   HISTORY *tmp = history_lines_end;
145 
146   if (-x > HISTORY_MAX) {
147     logmsg("History limited to last %d commands\n", HISTORY_MAX);
148     return (-1);
149   }
150 
151   if (-x > history_count) {
152     logmsg("only %d commands in history\n", history_count);
153     return (-1);
154   }
155 
156   while (x<-1) {
157     tmp = tmp->prev;
158     x++;
159   }
160   copy_to_historyCmdLine(tmp->cmdline);
161   history_ptr = NULL;
162   return(0);
163 }
164 
history_absolute_line(int x)165 int history_absolute_line(int x) {
166   HISTORY *tmp = history_lines_end;
167   int lowlimit;
168 
169   if (history_count == 0) {
170     logmsg("history empty\n");
171     return -1;
172   }
173 
174   lowlimit = history_count - HISTORY_MAX;
175 
176   if (x > history_count || x <= lowlimit) {
177     logmsg("only commands %d-%d are in history\n", lowlimit<0? 1 : lowlimit + 1, history_count);
178     return (-1);
179   }
180 
181   while (tmp->number != x)
182     tmp = tmp->prev;
183 
184   copy_to_historyCmdLine(tmp->cmdline);
185   history_ptr = NULL;
186   return(0);
187 }
188 
history_next()189 int history_next() {
190   if (history_ptr == NULL) {
191     history_ptr = history_lines_end;
192     if (history_ptr == NULL)
193       return(-1);
194     copy_to_historyCmdLine(history_ptr->cmdline);
195     return(0);
196   }
197   if (history_ptr->next == NULL)
198     history_ptr = history_lines;
199   else
200     history_ptr = history_ptr->next;
201   copy_to_historyCmdLine(history_ptr->cmdline);
202   return(0);
203 }
204 
history_prev()205 int history_prev() {
206   if (history_ptr == NULL) {
207     history_ptr = history_lines_end;
208     if (history_ptr == NULL)
209       return(-1);
210     copy_to_historyCmdLine(history_ptr->cmdline);
211     return(0);
212   }
213   if (history_ptr->prev == NULL)
214     history_ptr = history_lines_end;
215   else
216     history_ptr = history_ptr->prev;
217   copy_to_historyCmdLine(history_ptr->cmdline);
218   return(0);
219 }
220