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