1 |
commit: 6deb584ee8b64b44b90d81bf58fb853cafebbf61 |
2 |
Author: Sven Eden <sven.eden <AT> gmx <DOT> de> |
3 |
AuthorDate: Thu Jan 31 18:26:24 2013 +0000 |
4 |
Commit: Sven Eden <sven.eden <AT> gmx <DOT> de> |
5 |
CommitDate: Thu Jan 31 18:26:24 2013 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/ufed.git;a=commit;h=6deb584e |
7 |
|
8 |
Added support for the new data model to ufed-curses-checklist.c, which made the reading of the input and the generation of the flag list a lot easier and more convenient. |
9 |
|
10 |
--- |
11 |
ufed-curses-checklist.c | 722 ++++++++++++++++++++--------------------------- |
12 |
1 files changed, 305 insertions(+), 417 deletions(-) |
13 |
|
14 |
diff --git a/ufed-curses-checklist.c b/ufed-curses-checklist.c |
15 |
index 8c9b408..5950796 100644 |
16 |
--- a/ufed-curses-checklist.c |
17 |
+++ b/ufed-curses-checklist.c |
18 |
@@ -11,28 +11,16 @@ |
19 |
|
20 |
#include "ufed-curses-help.h" |
21 |
|
22 |
-/* internal types */ |
23 |
-struct flag { |
24 |
- struct item item; |
25 |
- char *name; |
26 |
- char on; |
27 |
- char state[5]; |
28 |
- bool *isInstalled; |
29 |
- char **pkgs; |
30 |
- char **descr; |
31 |
-}; |
32 |
- |
33 |
- |
34 |
/* internal members */ |
35 |
-static struct flag *flags; |
36 |
-static int descriptionleft; |
37 |
-static char *fayt; |
38 |
-static struct item **faytsave; |
39 |
-static size_t maxDescWidth = 0; |
40 |
-static char *lineBuf = NULL; |
41 |
+static int descriptionleft = 0; |
42 |
+static char* fayt = NULL; |
43 |
+static sFlag** faytsave = NULL; |
44 |
+static size_t maxDescWidth = 0; |
45 |
+static char* lineBuf = NULL; |
46 |
+static sFlag* flags = NULL; |
47 |
|
48 |
#define mkKey(x) x, sizeof(x)-1 |
49 |
-static const struct key keys[] = { |
50 |
+static const sKey keys[] = { |
51 |
{ '?', mkKey("Help (?)") }, |
52 |
{ '\n', mkKey("Save (Return/Enter)") }, |
53 |
{ '\033', mkKey("Cancel (Esc)") }, |
54 |
@@ -52,20 +40,16 @@ static void free_flags(void); |
55 |
|
56 |
|
57 |
/* external members */ |
58 |
-enum mask showMasked = show_unmasked; //!< Set whether to show masked, unmasked or both flags |
59 |
-enum order pkgOrder = pkgs_left; //!< Set whether to display package lists left or right of the description |
60 |
-enum scope showScope = show_all; //!< Set whether global, local or all flags are shown |
61 |
-int lineCountGlobal; |
62 |
-int lineCountGlobalInstalled; |
63 |
-int lineCountLocal; |
64 |
-int lineCountLocalInstalled; |
65 |
-int lineCountMasked; |
66 |
-int lineCountMaskedInstalled; |
67 |
-int lineCountMasked; |
68 |
+eMask e_mask = eMask_unmasked; |
69 |
+eOrder e_order = eOrder_left; |
70 |
+eScope e_scope = eScope_all; |
71 |
+eState e_state = eState_all; |
72 |
+sListStats listStats = { 0, 0, 0, 0, 0, 0 }; |
73 |
extern int bottomline, minwidth; |
74 |
|
75 |
/* static functions */ |
76 |
-static char *getline(FILE *fp) { |
77 |
+static char *getline(FILE *fp) |
78 |
+{ |
79 |
static size_t size = LINE_MAX; |
80 |
|
81 |
if (NULL == lineBuf) { |
82 |
@@ -104,167 +88,80 @@ static char *getline(FILE *fp) { |
83 |
return NULL; // never reached. |
84 |
} |
85 |
|
86 |
-static void read_flags(void) { |
87 |
- FILE *input = fdopen(3, "r"); |
88 |
- int lineNum = 0; |
89 |
- char *line = NULL; |
90 |
+static void read_flags(void) |
91 |
+{ |
92 |
+ FILE* input = fdopen(3, "r"); |
93 |
+ int lineNum = 0; |
94 |
+ char* line = NULL; |
95 |
+ int ndescr = 0; |
96 |
+ char endChar = 0; |
97 |
+ size_t fullWidth = 0; |
98 |
+ struct { |
99 |
+ int start, end; |
100 |
+ } name, desc, pkg, state; |
101 |
|
102 |
if(input == NULL) |
103 |
ERROR_EXIT(-1, "fdopen failed with error %d\n", errno); |
104 |
atexit(&free_flags); |
105 |
|
106 |
- // Initialize line count per type: |
107 |
- lineCountGlobal = 0; |
108 |
- lineCountGlobalInstalled = 0; |
109 |
- lineCountLocal = 0; |
110 |
- lineCountLocalInstalled = 0; |
111 |
- lineCountMasked = 0; |
112 |
- lineCountMaskedInstalled = 0; |
113 |
- lineCountMasked = 0; |
114 |
+ for(line = getline(input); line ; line = getline(input)) { |
115 |
+ name.start = name.end = -1; |
116 |
+ state.start = state.end = -1; |
117 |
|
118 |
- for(;;) { |
119 |
- struct { |
120 |
- int start, end; |
121 |
- } name, on, state, pkgs, desc; |
122 |
- int ndescr = 0; |
123 |
- struct flag *flag = NULL; |
124 |
- char descState = 0; |
125 |
- |
126 |
- line = getline(input); |
127 |
- if(NULL == line) |
128 |
- break; |
129 |
- if(sscanf(line, "%n%*s%n %n%*s%n (%n%*[ +-]%n) %d", |
130 |
+ if (sscanf(line, "%n%*s%n [%n%*[ +-]%n] %d", |
131 |
&name.start, &name.end, |
132 |
- &on.start, &on.end, |
133 |
&state.start, &state.end, |
134 |
&ndescr) != 1) |
135 |
- ERROR_EXIT(-1, "flag sscanf failed on line %d:\n\"%s\"\n", lineNum, line); |
136 |
- |
137 |
- /* Allocate memory for the struct and the arrays */ |
138 |
- // struct |
139 |
- if (NULL == (flag = (struct flag*)malloc(sizeof(struct flag)))) |
140 |
- ERROR_EXIT(-1, "Can not allocate %lu bytes for flag\n", sizeof(struct flag)); |
141 |
- // isInstalled |
142 |
- if (NULL == (flag->isInstalled = (bool*)calloc(ndescr, sizeof(bool)))) |
143 |
- ERROR_EXIT(-1, "Can not allocate %lu bytes for isInstalled array\n", ndescr * sizeof(bool)); |
144 |
- // name |
145 |
- if (NULL == (flag->name = (char*)calloc(name.end - name.start + 1, sizeof(char)))) |
146 |
- ERROR_EXIT(-1, "Can not allocate %lu bytes for flag name\n", |
147 |
- (name.end - name.start + 1) * sizeof(char)); |
148 |
- // pkgs |
149 |
- if (NULL == (flag->pkgs = (char**)calloc(ndescr, sizeof(char*)))) |
150 |
- ERROR_EXIT(-1, "Can not allocate %lu bytes for pkg array\n", ndescr * sizeof(char*)); |
151 |
- // descr |
152 |
- if (NULL == (flag->descr = (char**)calloc(ndescr, sizeof(char*)))) |
153 |
- ERROR_EXIT(-1, "Can not allocate %lu bytes for descr array\n", ndescr * sizeof(char*)); |
154 |
- |
155 |
- /* note position and name of the flag */ |
156 |
- flag->item.listline = lineNum; |
157 |
- flag->item.currline = 0; |
158 |
+ ERROR_EXIT(-1, "Flag read failed on line %d:\n\"%s\"\n", lineNum + 1, line); |
159 |
+ |
160 |
+ // Check stats |
161 |
+ if ((state.end - state.start) != 2) |
162 |
+ ERROR_EXIT(-1, "Illegal flag stats on line %d:\n\"%s\"\n", lineNum + 1, line); |
163 |
+ |
164 |
+ // Create a new flag |
165 |
+ line[name.end] = '\0'; |
166 |
+ line[state.end] = '\0'; |
167 |
+ sFlag* newFlag = addFlag(&flags, &line[name.start], lineNum, ndescr, &line[state.start]); |
168 |
|
169 |
/* The minimum width of the left side display is: |
170 |
- * Space + Selection + Space + name + Space + Mask brackets. |
171 |
+ * Space + Selection + Space + name + Space + Mask brackets/Force plus. |
172 |
* = 1 + 3 + 1 + strlen(name) + 1 + 2 |
173 |
* = strlen(name) + 8 |
174 |
*/ |
175 |
- if(name.end - name.start + 8 > minwidth) |
176 |
+ if( (name.end - name.start + 8) > minwidth) |
177 |
minwidth = name.end - name.start + 8; |
178 |
- strncpy(flag->name, &line[name.start], name.end - name.start); |
179 |
- |
180 |
- /* check and save current flag setting from configuration */ |
181 |
- line[on.end] = '\0'; |
182 |
- if(!strcmp(&line[on.start], "on")) |
183 |
- flag->on = '+'; |
184 |
- else if(!strcmp(&line[on.start], "off")) |
185 |
- flag->on = '-'; |
186 |
- else if(!strcmp(&line[on.start], "def")) |
187 |
- flag->on = ' '; |
188 |
- else |
189 |
- ERROR_EXIT(-1, "flag->on can not be determined with \"%s\"\n", &line[on.start]); |
190 |
- |
191 |
- /* check and set flag state */ |
192 |
- if(state.end - state.start != 2) |
193 |
- ERROR_EXIT(-1, "state length is %d (must be 2)\n", state.end - state.start); |
194 |
- strncpy(flag->state, &line[state.start], 2); |
195 |
- |
196 |
- /* check and set flag item height */ |
197 |
- flag->item.ndescr = ndescr; |
198 |
|
199 |
/* read description(s) and determine flag status */ |
200 |
- flag->item.isMasked = false; |
201 |
- flag->item.isGlobal = false; |
202 |
for (int i = 0; i < ndescr; ++i) { |
203 |
- pkgs.start = pkgs.end = -1; |
204 |
- desc.start = desc.end = -1; |
205 |
+ desc.start = desc.end = -1; |
206 |
+ pkg.start = pkg.end = -1; |
207 |
+ state.start = state.end = -1; |
208 |
|
209 |
line = getline(input); |
210 |
if (!line) break; |
211 |
|
212 |
- /* There are two possible layouts: |
213 |
- * a: "g [description]" for global flag descriptions and |
214 |
- * b: "x (pkg(s)) [description]" for local flag descriptions |
215 |
- * We therefore need two sscanf attempts. Use b first, as |
216 |
- * it is more common. |
217 |
- */ |
218 |
- if ((sscanf(line, "(%n%*[^)]%n) [%n%*[^]]%n] %c", |
219 |
- &pkgs.start, &pkgs.end, |
220 |
- &desc.start, &desc.end, |
221 |
- &descState) !=1 ) |
222 |
- &&(sscanf(line, "[%n%*[^]]%n] %c", |
223 |
+ if ( (sscanf(line, "\t%n%*[^\t]%n\t (%n%*[^)]%n) [%n%*[ +-]%n%c", |
224 |
&desc.start, &desc.end, |
225 |
- &descState) !=1)) |
226 |
- ERROR_EXIT(-1, "desc sscanf failed on line\n\"%s\"\n", line); |
227 |
- |
228 |
- // Set general state of the flag |
229 |
- flag->isInstalled[i] = false; |
230 |
- if ('g' == descState) { |
231 |
- flag->item.isGlobal = true; |
232 |
- ++lineCountGlobal; |
233 |
- } |
234 |
- else if ('G' == descState) { |
235 |
- flag->item.isGlobal = true; |
236 |
- flag->isInstalled[i] = true; |
237 |
- ++lineCountGlobalInstalled; |
238 |
- } |
239 |
- else if ('l' == descState) { |
240 |
- ++lineCountLocal; |
241 |
- } |
242 |
- else if ('L' == descState) { |
243 |
- flag->isInstalled[i] = true; |
244 |
- ++lineCountLocalInstalled; |
245 |
- } |
246 |
- else if ('M' == descState) { |
247 |
- flag->item.isMasked = true; |
248 |
- flag->isInstalled[i] = true; |
249 |
- ++lineCountMaskedInstalled; |
250 |
- } |
251 |
- else if ('m' == descState) { |
252 |
- flag->item.isMasked = true; |
253 |
- ++lineCountMasked; |
254 |
- } |
255 |
- |
256 |
- // Save packages |
257 |
- if (pkgs.start > -1) { |
258 |
- int pkgLen = pkgs.end - pkgs.start; |
259 |
- if (NULL == (flag->pkgs[i] = (char*)calloc(pkgLen + 1, sizeof(char))) ) |
260 |
- ERROR_EXIT(-1, "Unable to allocate %lu bytes for pkg list %d\n", |
261 |
- sizeof(char) * (pkgLen + 1), i); |
262 |
- strncpy(flag->pkgs[i], &line[pkgs.start], pkgLen); |
263 |
- } else |
264 |
- flag->pkgs[i] = NULL; |
265 |
- |
266 |
- // Save description |
267 |
- if (desc.start > -1) { |
268 |
- int descLen = desc.end - desc.start; |
269 |
- if (NULL == (flag->descr[i] = (char*)calloc(descLen + 1, sizeof(char))) ) |
270 |
- ERROR_EXIT(-1, "Unable to allocate %lu bytes for description %d\n", |
271 |
- sizeof(char) * (descLen + 1), i); |
272 |
- strncpy(flag->descr[i], &line[desc.start], descLen); |
273 |
+ &pkg.start, &pkg.end, |
274 |
+ &state.start, &state.end, |
275 |
+ &endChar) != 1) |
276 |
+ || (']' != endChar) ) |
277 |
+ ERROR_EXIT(-1, "Description read failed on line %d\n\"%s\"\n", lineNum + 1, line); |
278 |
+ |
279 |
+ // Check stats |
280 |
+ if ((state.end - state.start) != 5) |
281 |
+ ERROR_EXIT(-1, "Illegal description stats on line %d:\n\"%s\"\n", lineNum + 1, line); |
282 |
+ |
283 |
+ // Add description line to flag: |
284 |
+ line[desc.end] = '\0'; |
285 |
+ line[state.end] = '\0'; |
286 |
+ if ( (pkg.end - pkg.start) > 1) { |
287 |
+ line[pkg.end] = '\0'; |
288 |
+ fullWidth = addFlagDesc(newFlag, &line[pkg.start], &line[desc.start], &line[state.start]); |
289 |
} else |
290 |
- ERROR_EXIT(-1, "Flag %s has no description at line %d\n", flag->name, i); |
291 |
+ fullWidth = addFlagDesc(newFlag, NULL, &line[desc.start], &line[state.start]); |
292 |
|
293 |
// Note new max length if this line is longest: |
294 |
- size_t fullWidth = 1 + strlen(flag->descr[i]) + (flag->pkgs[i] ? strlen(flag->pkgs[i]) + 3 : 0); |
295 |
if (fullWidth > maxDescWidth) |
296 |
maxDescWidth = fullWidth; |
297 |
|
298 |
@@ -272,50 +169,30 @@ static void read_flags(void) { |
299 |
++lineNum; |
300 |
} // loop through description lines |
301 |
|
302 |
- /* Save flag in our linked list */ |
303 |
- if(flags==NULL) { |
304 |
- flag->item.prev = (struct item *) flag; |
305 |
- flag->item.next = (struct item *) flag; |
306 |
- flags = flag; |
307 |
- } else { |
308 |
- flag->item.next = (struct item *) flags; |
309 |
- flag->item.prev = flags->item.prev; |
310 |
- flags->item.prev->next = (struct item *) flag; |
311 |
- flags->item.prev = (struct item *) flag; |
312 |
- } |
313 |
+ // Add line data to the list stats |
314 |
+ addLineStats(newFlag, &listStats); |
315 |
} // loop while input given |
316 |
|
317 |
fclose(input); |
318 |
|
319 |
- if(flags==NULL) { |
320 |
- fputs("No input!\n", stderr); |
321 |
- exit(-1); |
322 |
- } |
323 |
+ if(flags == NULL) |
324 |
+ ERROR_EXIT(-1, "Unable to start: %s\n", "No Input!"); |
325 |
|
326 |
// Save the last line, it is needed in several places |
327 |
bottomline = lineNum; |
328 |
} |
329 |
|
330 |
-static void free_flags(void) { |
331 |
- struct flag *flag = flags; |
332 |
+static void free_flags(void) |
333 |
+{ |
334 |
+ sFlag* flag = flags->prev; |
335 |
|
336 |
// Clear all flags |
337 |
- if(flag != NULL) { |
338 |
- flag->item.prev->next = NULL; |
339 |
- do { |
340 |
- void *p = flag; |
341 |
- for (int i = 0; i < flag->item.ndescr; ++i) { |
342 |
- if (flag->pkgs[i]) free(flag->pkgs[i]); |
343 |
- if (flag->descr[i]) free(flag->descr[i]); |
344 |
- } |
345 |
- if (flag->name) free(flag->name); |
346 |
- if (flag->isInstalled) free(flag->isInstalled); |
347 |
- if (flag->pkgs) free(flag->pkgs); |
348 |
- if (flag->descr) free(flag->descr); |
349 |
- flag = (struct flag *) flag->item.next; |
350 |
- free(p); |
351 |
- } while(flag != NULL); |
352 |
- flags = NULL; |
353 |
+ while (flags) { |
354 |
+ if (flag) |
355 |
+ destroyFlag(&flags, &flag); |
356 |
+ else |
357 |
+ destroyFlag(&flags, &flags); |
358 |
+ flag = flags ? flags->prev ? flags->prev : flags : NULL; |
359 |
} |
360 |
|
361 |
// Clear line buffer |
362 |
@@ -324,16 +201,16 @@ static void free_flags(void) { |
363 |
} |
364 |
|
365 |
|
366 |
-static int drawflag(struct item *item, bool highlight) { |
367 |
- struct flag *flag = (struct flag *) item; |
368 |
+static int drawflag(sFlag* flag, bool highlight) |
369 |
+{ |
370 |
char buf[wWidth(List)+1]; |
371 |
char desc[maxDescWidth]; |
372 |
int idx = 0; |
373 |
int usedY = 0; |
374 |
- int line = flag->item.currline; |
375 |
+ int line = flag->currline; |
376 |
|
377 |
// Return early if there is nothing to display: |
378 |
- if (!isLegalItem(&flag->item)) |
379 |
+ if (!isFlagLegal(flag)) |
380 |
return 0; |
381 |
|
382 |
/* Determine with which description to start. |
383 |
@@ -342,7 +219,7 @@ static int drawflag(struct item *item, bool highlight) { |
384 |
* themselves. |
385 |
*/ |
386 |
if (line < 0) { |
387 |
- if (-line < getItemHeight(&flag->item)) { |
388 |
+ if (-line < getFlagHeight(flag)) { |
389 |
idx = -line; |
390 |
line = 0; |
391 |
usedY = idx; |
392 |
@@ -353,53 +230,65 @@ static int drawflag(struct item *item, bool highlight) { |
393 |
|
394 |
memset(buf, 0, sizeof(char) * (wWidth(List)+1)); |
395 |
|
396 |
- /* print the selection, name and state of the flag */ |
397 |
- sprintf(buf, " %c%c%c %s%s%s%-*s ", |
398 |
- /* State of selection */ |
399 |
- flag->on == ' ' ? '(' : '[', |
400 |
- flag->on == ' ' |
401 |
- ? flag->on == ' ' |
402 |
- ? flag->state[0] : ' ' |
403 |
- : flag->on, |
404 |
- flag->on == ' ' ? ')' : ']', |
405 |
- /* name */ |
406 |
- flag->item.isMasked ? "(" : "", flag->name, flag->item.isMasked ? ")" : "", |
407 |
- /* distance */ |
408 |
- (int)(minwidth - (flag->item.isMasked ? 4 : 6) - strlen(flag->name)), " "); |
409 |
- // At this point buf is filled up to minwidth |
410 |
- |
411 |
- /* print descriptions according to filters |
412 |
- * TODO: Implement installed/all filters |
413 |
- */ |
414 |
- if(idx < flag->item.ndescr) { |
415 |
- for(;;) { |
416 |
- // Filter global description if it is not wanted: |
417 |
- if (!idx && (show_local == showScope) && flag->item.isGlobal) { |
418 |
- ++idx; |
419 |
+ // print descriptions according to filters |
420 |
+ if(idx < flag->ndesc) { |
421 |
+ int lHeight = wHeight(List); |
422 |
+ for( ; (idx < flag->ndesc) && (line < lHeight); ++idx) { |
423 |
+ // Continue if any of the filters apply: |
424 |
+ if (!isDescLegal(flag, idx)) |
425 |
continue; |
426 |
- } |
427 |
|
428 |
- // Break on local descriptions if they are not wanted: |
429 |
- if (idx && (show_global == showScope)) |
430 |
- break; |
431 |
- |
432 |
- // Display flag state |
433 |
- bool isGlobalDesc = flag->item.isGlobal && !flag->pkgs[idx] ? true : false; |
434 |
- sprintf(buf + minwidth, " %s %c%c ", |
435 |
- flag->state, |
436 |
- isGlobalDesc ? ' ' : flag->item.isMasked ? 'M' : 'L', |
437 |
- flag->isInstalled[idx] ? '*' : ' '); |
438 |
+ if (!buf[0]) { |
439 |
+ /* print the selection, name and state of the flag */ |
440 |
+ char prefix[2] = { 0, 0 }; |
441 |
+ char postfix[2] = { 0, 0 }; |
442 |
+ int postlen = 5; |
443 |
+ if (isDescForced(flag, idx)) { |
444 |
+ prefix[0] = '+'; |
445 |
+ postfix[0] = '+'; |
446 |
+ postlen = 3; |
447 |
+ } else if (isDescMasked(flag, idx)) { |
448 |
+ prefix[0] = '('; |
449 |
+ postfix[0] = ')'; |
450 |
+ postlen = 3; |
451 |
+ } |
452 |
+ sprintf(buf, " %c%c%c %s%s%s%-*s ", |
453 |
+ /* State of selection */ |
454 |
+ flag->stateConf == ' ' ? '(' : '[', |
455 |
+ flag->stateConf, |
456 |
+ flag->stateConf == ' ' ? ')' : ']', |
457 |
+ /* name */ |
458 |
+ prefix, flag->name, postfix, |
459 |
+ /* distance */ |
460 |
+ (int)(minwidth - postlen - strlen(flag->name)), " "); |
461 |
+ // At this point buf is filled up to minwidth |
462 |
+ } // End of generating left side mask display |
463 |
+ |
464 |
+ /* Display flag state |
465 |
+ * The order in which the states are to be displayed is: |
466 |
+ * 1. make.defaults |
467 |
+ * 2. package.use |
468 |
+ * 3. make.conf |
469 |
+ * 4. global/local |
470 |
+ * 5. installed/not installed |
471 |
+ */ |
472 |
+ sprintf(buf + minwidth, " %c%c%c %c%c ", |
473 |
+ flag->stateDefault, |
474 |
+ flag->desc[idx].statePackage, |
475 |
+ flag->stateConf, |
476 |
+ flag->desc[idx].isGlobal ? ' ' : 'L', |
477 |
+ flag->desc[idx].isInstalled ? 'i' : ' '); |
478 |
|
479 |
// Assemble description line: |
480 |
memset(desc, 0, maxDescWidth * sizeof(char)); |
481 |
- if (flag->pkgs[idx]) { |
482 |
- if (pkgs_left == pkgOrder) |
483 |
- sprintf(desc, "(%s) %s", flag->pkgs[idx], flag->descr[idx]); |
484 |
+ if (flag->desc[idx].pkg) { |
485 |
+ if (e_order == eOrder_left) |
486 |
+ sprintf(desc, "(%s) %s", flag->desc[idx].pkg, flag->desc[idx].desc); |
487 |
else |
488 |
- sprintf(desc, "%s (%s)", flag->descr[idx], flag->pkgs[idx]); |
489 |
+ sprintf(desc, "%s (%s)", flag->desc[idx].desc, flag->desc[idx].pkg); |
490 |
} |
491 |
else |
492 |
- sprintf(desc, "%s", flag->descr[idx]); |
493 |
+ sprintf(desc, "%s", flag->desc[idx].desc); |
494 |
|
495 |
// Now display the description line according to its horizontal position |
496 |
sprintf(buf + minwidth + 8, "%-*.*s", |
497 |
@@ -418,224 +307,223 @@ static int drawflag(struct item *item, bool highlight) { |
498 |
// Finally put the line on the screen |
499 |
mvwaddstr(win(List), line, 0, buf); |
500 |
mvwaddch(win(List), line, minwidth, ACS_VLINE); // Before state |
501 |
- mvwaddch(win(List), line, minwidth + 3, ACS_VLINE); // Between state and scope |
502 |
- mvwaddch(win(List), line, minwidth + 6, ACS_VLINE); // After scope |
503 |
+ mvwaddch(win(List), line, minwidth + 4, ACS_VLINE); // Between state and scope |
504 |
+ mvwaddch(win(List), line, minwidth + 7, ACS_VLINE); // After scope |
505 |
++line; |
506 |
- ++idx; |
507 |
++usedY; |
508 |
- if((idx < flag->item.ndescr) && (line < wHeight(List)) ) { |
509 |
+ if(((idx + 1) < flag->ndesc) && (line < lHeight) ) { |
510 |
char *p; |
511 |
for(p = buf; p != buf + minwidth; p++) |
512 |
*p = ' '; |
513 |
- continue; |
514 |
} |
515 |
- break; |
516 |
} |
517 |
} else { |
518 |
memset(buf+minwidth, ' ', wWidth(List)-minwidth); |
519 |
buf[wWidth(List)] = '\0'; |
520 |
waddstr(win(List), buf); |
521 |
} |
522 |
+ |
523 |
if(highlight) |
524 |
- wmove(win(List), max(flag->item.currline, 0), 2); |
525 |
+ wmove(win(List), max(flag->currline, 0), 2); |
526 |
wnoutrefresh(win(List)); |
527 |
+ |
528 |
return usedY; |
529 |
} |
530 |
|
531 |
-static int callback(struct item **currentitem, int key) { |
532 |
- if(*fayt!='\0' && key!=KEY_BACKSPACE && (key==' ' || key!=(unsigned char) key || !isprint(key))) { |
533 |
- *fayt = '\0'; |
534 |
- wattrset(win(Input), COLOR_PAIR(3)); |
535 |
- mvwhline(win(Input), 0, 0, ' ', wWidth(Input)); |
536 |
- mvwaddch(win(Input), 0, minwidth, ACS_VLINE); // Before state |
537 |
- mvwaddch(win(Input), 0, minwidth + 3, ACS_VLINE); // Between state and scope |
538 |
- mvwaddch(win(Input), 0, minwidth + 6, ACS_VLINE); // After scope |
539 |
- wmove(win(Input), 0, 0); |
540 |
- wrefresh(win(Input)); |
541 |
+static int callback(sFlag** curr, int key) |
542 |
+{ |
543 |
+ WINDOW* wInp = win(Input); |
544 |
+ WINDOW* wLst = win(List); |
545 |
+ size_t fLen = 0; |
546 |
+ if ( fayt[0] |
547 |
+ && (key != KEY_BACKSPACE) |
548 |
+ && (key != KEY_DC) |
549 |
+ && (key != 0177) |
550 |
+ && ( (key == ' ') || (key != (unsigned char)key) || !isprint(key)) ) { |
551 |
+ fayt[0] = '\0'; |
552 |
+ drawStatus(true); |
553 |
+ wrefresh(wInp); |
554 |
} |
555 |
- if(descriptionleft!=0 && key!=KEY_LEFT && key!=KEY_RIGHT) { |
556 |
+ |
557 |
+ // Reset possible side scrolling of the current flags description first |
558 |
+ if(descriptionleft && (key != KEY_LEFT) && (key != KEY_RIGHT) ) { |
559 |
descriptionleft = 0; |
560 |
- drawflag(*currentitem, TRUE); |
561 |
+ drawflag(*curr, TRUE); |
562 |
} |
563 |
+ |
564 |
switch(key) { |
565 |
- default: |
566 |
- if(key==(unsigned char) key && isprint(key)) { |
567 |
- struct item *item = *currentitem; |
568 |
- int n = strlen(fayt); |
569 |
- if(strncasecmp(((struct flag *) item)->name, fayt, n)!=0) |
570 |
- n--; |
571 |
- fayt[n] = (char) key; |
572 |
- faytsave[n] = *currentitem; |
573 |
- n++; |
574 |
- fayt[n] = '\0'; |
575 |
- |
576 |
- /* if the current flag already matches the input string, |
577 |
- * then update the input area only. |
578 |
- */ |
579 |
- if(strncasecmp(((struct flag *) item)->name, fayt, n)==0) { |
580 |
- wattrset(win(Input), COLOR_PAIR(3) | A_BOLD); |
581 |
- mvwaddstr(win(Input), 0, 0, fayt); |
582 |
- wrefresh(win(Input)); |
583 |
- } |
584 |
- /* if the current flag does not match, search one that does. */ |
585 |
- else { |
586 |
- do item = item->next; |
587 |
- while( (item != *currentitem) |
588 |
- && ( ( strncasecmp(((struct flag *) item)->name, fayt, n) |
589 |
- || !isLegalItem(item)) ) ); |
590 |
- |
591 |
- /* if there was no match (or the match is filtered), |
592 |
- * update the input area to show that there is no match |
593 |
- */ |
594 |
- if (item == *currentitem) { |
595 |
- if (item != *currentitem) |
596 |
- item = *currentitem; |
597 |
- wattrset(win(Input), COLOR_PAIR(4) | A_BOLD | A_REVERSE); |
598 |
- mvwaddstr(win(Input), 0, 0, fayt); |
599 |
- wmove(win(Input), 0, n-1); |
600 |
- wnoutrefresh(win(List)); |
601 |
- wrefresh(win(Input)); |
602 |
- } else { |
603 |
- drawflag(*currentitem, FALSE); |
604 |
- *currentitem = item; |
605 |
- scrollcurrent(); |
606 |
- drawflag(*currentitem, TRUE); |
607 |
- wattrset(win(Input), COLOR_PAIR(3) | A_BOLD); |
608 |
- mvwaddstr(win(Input), 0, 0, fayt); |
609 |
- wnoutrefresh(win(List)); |
610 |
- wrefresh(win(Input)); |
611 |
- } |
612 |
- } |
613 |
- } |
614 |
- break; |
615 |
- case KEY_BACKSPACE: { |
616 |
- int n = strlen(fayt); |
617 |
- if(n==0) |
618 |
+ case KEY_DC: |
619 |
+ case 0177: |
620 |
+ case KEY_BACKSPACE: |
621 |
+ fLen = strlen(fayt); |
622 |
+ if(0 == fLen) |
623 |
break; |
624 |
- n--; |
625 |
- fayt[n] = '\0'; |
626 |
- drawflag(*currentitem, FALSE); |
627 |
- *currentitem = faytsave[n]; |
628 |
+ fayt[--fLen] = '\0'; |
629 |
+ drawflag(*curr, FALSE); |
630 |
+ *curr = faytsave[fLen]; |
631 |
scrollcurrent(); |
632 |
- drawflag(*currentitem, TRUE); |
633 |
- wattrset(win(Input), COLOR_PAIR(3) | A_BOLD); |
634 |
- mvwaddstr(win(Input), 0, 0, fayt); |
635 |
- whline(win(Input), ' ', 2); |
636 |
- if(n==0) { |
637 |
- wmove(win(List), (*currentitem)->currline, 2); |
638 |
- wnoutrefresh(win(Input)); |
639 |
- wrefresh(win(List)); |
640 |
+ drawflag(*curr, TRUE); |
641 |
+ wattrset(wInp, COLOR_PAIR(5) | A_BOLD); |
642 |
+ mvwaddstr(wInp, 0, 0, fayt); |
643 |
+ whline(wInp, ' ', 2); |
644 |
+ if(fLen == 0) |
645 |
+ wmove(wLst, (*curr)->currline, 2); |
646 |
+ wnoutrefresh(wLst); |
647 |
+ wrefresh(wInp); |
648 |
+ break; |
649 |
+ case '\n': |
650 |
+ case KEY_ENTER: |
651 |
+ if(yesno("Save and exit? (Y/N) ")) |
652 |
+ return 0; |
653 |
+ break; |
654 |
+ case '\033': |
655 |
+ if(yesno("Cancel? (Y/N) ")) |
656 |
+ return 1; |
657 |
+ break; |
658 |
+ case ' ': |
659 |
+ // Masked flags can be turned off, nothing else |
660 |
+ if ( (*curr)->globalMasked ) { |
661 |
+ if (' ' != (*curr)->stateConf) |
662 |
+ (*curr)->stateConf = ' '; |
663 |
} else { |
664 |
- wnoutrefresh(win(List)); |
665 |
- wrefresh(win(Input)); |
666 |
+ switch ((*curr)->stateConf) { |
667 |
+ case '+': |
668 |
+ (*curr)->stateConf = '-'; |
669 |
+ break; |
670 |
+ case '-': |
671 |
+ (*curr)->stateConf = ' '; |
672 |
+ break; |
673 |
+ default: |
674 |
+ (*curr)->stateConf = '+'; |
675 |
+ break; |
676 |
+ } |
677 |
} |
678 |
+ if (*curr != flags) { |
679 |
+ drawflag(*curr, TRUE); |
680 |
+ wmove(wLst, (*curr)->currline, 2); |
681 |
+ wrefresh(wLst); |
682 |
+ } else |
683 |
+ drawFlags(); |
684 |
+ break; |
685 |
+ case KEY_LEFT: |
686 |
+ if(descriptionleft>0) |
687 |
+ descriptionleft--; |
688 |
+ drawflag(*curr, TRUE); |
689 |
+ wmove(wLst, (*curr)->currline, 2); |
690 |
+ wrefresh(wLst); |
691 |
+ break; |
692 |
+ case KEY_RIGHT: |
693 |
+ descriptionleft++; |
694 |
+ drawflag(*curr, TRUE); |
695 |
+ wmove(wLst, (*curr)->currline, 2); |
696 |
+ wrefresh(wLst); |
697 |
break; |
698 |
- } |
699 |
- case '\n': |
700 |
- case KEY_ENTER: |
701 |
- if(yesno("Save and exit? (Y/N) ")) |
702 |
- return 0; |
703 |
- break; |
704 |
- case '\033': |
705 |
- if(yesno("Cancel? (Y/N) ")) |
706 |
- return 1; |
707 |
- break; |
708 |
- case ' ': { |
709 |
- // Masked flags can be turned off, nothing else |
710 |
- if ( (*currentitem)->isMasked |
711 |
- && (' ' != ((struct flag *) *currentitem)->on) ) |
712 |
- ((struct flag *) *currentitem)->on = ' '; |
713 |
- else { |
714 |
- switch (((struct flag *) *currentitem)->on) { |
715 |
- case '+': |
716 |
- ((struct flag *) *currentitem)->on = '-'; |
717 |
- break; |
718 |
- case '-': |
719 |
- ((struct flag *) *currentitem)->on = ' '; |
720 |
- break; |
721 |
- default: |
722 |
- ((struct flag *) *currentitem)->on = '+'; |
723 |
- break; |
724 |
- } |
725 |
- } |
726 |
- if (*currentitem != &flags->item) { |
727 |
- drawflag(*currentitem, TRUE); |
728 |
- wmove(win(List), (*currentitem)->currline, 2); |
729 |
- wrefresh(win(List)); |
730 |
- } else { |
731 |
- drawitems(); |
732 |
- } |
733 |
- break; |
734 |
- } |
735 |
- case KEY_LEFT: |
736 |
- if(descriptionleft>0) |
737 |
- descriptionleft--; |
738 |
- drawflag(*currentitem, TRUE); |
739 |
- wmove(win(List), (*currentitem)->currline, 2); |
740 |
- wrefresh(win(List)); |
741 |
- break; |
742 |
- case KEY_RIGHT: |
743 |
- descriptionleft++; |
744 |
- drawflag(*currentitem, TRUE); |
745 |
- wmove(win(List), (*currentitem)->currline, 2); |
746 |
- wrefresh(win(List)); |
747 |
- break; |
748 |
#ifdef NCURSES_MOUSE_VERSION |
749 |
- case KEY_MOUSE: |
750 |
- // Masked flags can be turned off, nothing else |
751 |
- if ( (*currentitem)->isMasked |
752 |
- && (' ' != ((struct flag *) *currentitem)->on) ) |
753 |
- ((struct flag *) *currentitem)->on = ' '; |
754 |
- else { |
755 |
- switch (((struct flag *) *currentitem)->on) { |
756 |
- case '+': |
757 |
- ((struct flag *) *currentitem)->on = '-'; |
758 |
- break; |
759 |
- case '-': |
760 |
- ((struct flag *) *currentitem)->on = ' '; |
761 |
- break; |
762 |
- default: |
763 |
- ((struct flag *) *currentitem)->on = '+'; |
764 |
- break; |
765 |
+ case KEY_MOUSE: |
766 |
+ // Masked flags can be turned off, nothing else |
767 |
+ if ( (*curr)->globalMasked ) { |
768 |
+ if (' ' != (*curr)->stateConf) |
769 |
+ (*curr)->stateConf = ' '; |
770 |
+ } else { |
771 |
+ switch ((*curr)->stateConf) { |
772 |
+ case '+': |
773 |
+ (*curr)->stateConf = '-'; |
774 |
+ break; |
775 |
+ case '-': |
776 |
+ (*curr)->stateConf = ' '; |
777 |
+ break; |
778 |
+ default: |
779 |
+ (*curr)->stateConf = '+'; |
780 |
+ break; |
781 |
+ } |
782 |
} |
783 |
- } |
784 |
- if (*currentitem != &flags->item) { |
785 |
- drawflag(*currentitem, TRUE); |
786 |
- wmove(win(List), (*currentitem)->currline, 2); |
787 |
- wrefresh(win(List)); |
788 |
- } else { |
789 |
- drawitems(); |
790 |
- } |
791 |
- break; |
792 |
+ if (*curr != flags) { |
793 |
+ drawflag(*curr, TRUE); |
794 |
+ wmove(wLst, (*curr)->currline, 2); |
795 |
+ wrefresh(wLst); |
796 |
+ } else { |
797 |
+ drawFlags(); |
798 |
+ } |
799 |
+ break; |
800 |
#endif |
801 |
- case '?': |
802 |
- help(); |
803 |
- break; |
804 |
+ case '?': |
805 |
+ help(); |
806 |
+ break; |
807 |
+ default: |
808 |
+ if( (key == (unsigned char) key) && isprint(key)) { |
809 |
+ sFlag* flag = *curr; |
810 |
+ fLen = strlen(fayt); |
811 |
+ if(fLen && strncasecmp(flag->name, fayt, fLen)) |
812 |
+ --fLen; |
813 |
+ fayt[fLen] = (char) key; |
814 |
+ faytsave[fLen] = *curr; |
815 |
+ fayt[++fLen] = '\0'; |
816 |
+ |
817 |
+ /* if the current flag already matches the input string, |
818 |
+ * then update the input area only. |
819 |
+ */ |
820 |
+ if(!strncasecmp(flag->name, fayt, fLen)) { |
821 |
+ wattrset(wInp, COLOR_PAIR(5) | A_BOLD); |
822 |
+ mvwaddstr(wInp, 0, 0, fayt); |
823 |
+ wrefresh(wInp); |
824 |
+ } |
825 |
+ /* if the current flag does not match, search one that does. */ |
826 |
+ else { |
827 |
+ do flag = flag->next; |
828 |
+ while( (flag != *curr) |
829 |
+ && ( ( strncasecmp(flag->name, fayt, fLen) |
830 |
+ || !isFlagLegal(flag)) ) ); |
831 |
+ |
832 |
+ /* if there was no match (or the match is filtered), |
833 |
+ * update the input area to show that there is no match |
834 |
+ */ |
835 |
+ if (flag == *curr) { |
836 |
+ wattrset(wInp, COLOR_PAIR(4) | A_BOLD | A_REVERSE); |
837 |
+ mvwaddstr(wInp, 0, 0, fayt); |
838 |
+ wmove(wInp, 0, fLen - 1); |
839 |
+ wnoutrefresh(wLst); |
840 |
+ wrefresh(wInp); |
841 |
+ } else { |
842 |
+ drawflag(*curr, FALSE); |
843 |
+ *curr = flag; |
844 |
+ scrollcurrent(); |
845 |
+ drawflag(*curr, TRUE); |
846 |
+ wattrset(wInp, COLOR_PAIR(5) | A_BOLD); |
847 |
+ mvwaddstr(wInp, 0, 0, fayt); |
848 |
+ wnoutrefresh(wLst); |
849 |
+ wrefresh(wInp); |
850 |
+ } |
851 |
+ } |
852 |
+ } |
853 |
+ break; |
854 |
} |
855 |
return -1; |
856 |
} |
857 |
|
858 |
-int main(void) { |
859 |
+int main(void) |
860 |
+{ |
861 |
int result; |
862 |
|
863 |
read_flags(); |
864 |
- fayt = malloc((minwidth-11+2) * sizeof *fayt); |
865 |
- faytsave = malloc((minwidth-11+2) * sizeof *faytsave); |
866 |
+ fayt = (char*) calloc(minwidth, sizeof(*fayt)); |
867 |
+ faytsave = (sFlag**)calloc(minwidth, sizeof(*faytsave)); |
868 |
if(fayt==NULL || faytsave==NULL) |
869 |
- exit(-1); |
870 |
+ ERROR_EXIT(-1, "Unable to allocate %lu bytes for search buffer.\n", |
871 |
+ (minwidth * sizeof(*fayt)) + (minwidth * sizeof(*faytsave))); |
872 |
fayt[0] = '\0'; |
873 |
|
874 |
initcurses(); |
875 |
|
876 |
- result=maineventloop("Select desired USE flags from the list below:", |
877 |
- &callback, &drawflag, (struct item *) flags, keys); |
878 |
+ result = maineventloop("Select desired USE flags from the list below:", |
879 |
+ &callback, &drawflag, flags, keys, true); |
880 |
+ |
881 |
cursesdone(); |
882 |
|
883 |
- if(result==0) { |
884 |
+ if(0 == result) { |
885 |
FILE *output = fdopen(4, "w"); |
886 |
- struct flag *flag = flags; |
887 |
+ sFlag *flag = flags; |
888 |
do { |
889 |
- switch(flag->on) |
890 |
+ switch(flag->stateConf) |
891 |
{ |
892 |
case '+': |
893 |
fprintf(output, "%s\n", flag->name); |
894 |
@@ -644,8 +532,8 @@ int main(void) { |
895 |
fprintf(output, "-%s\n", flag->name); |
896 |
break; |
897 |
} |
898 |
- flag = (struct flag *) flag->item.next; |
899 |
- } while(flag!=flags); |
900 |
+ flag = flag->next; |
901 |
+ } while(flag != flags); |
902 |
fclose(output); |
903 |
} |