Merge branch 'vendor/GCC44'
[dragonfly.git] / contrib / ncurses-5.4 / test / cardfile.c
blob08d33ed43cc0d8014e4a8f3a894215e8e95f943f
1 /****************************************************************************
2 * Copyright (c) 1999-2002,2003 Free Software Foundation, Inc. *
3 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
30 * Author: Thomas E. Dickey <dickey@clark.net> 1999
32 * $Id: cardfile.c,v 1.23 2003/04/26 16:43:56 tom Exp $
34 * File format: text beginning in column 1 is a title; other text is content.
37 #include <test.priv.h>
39 #if USE_LIBFORM && USE_LIBPANEL
41 #include <form.h>
42 #include <panel.h>
44 #define VISIBLE_CARDS 10
45 #define OFFSET_CARD 2
47 enum {
48 MY_CTRL_x = MAX_FORM_COMMAND
49 ,MY_CTRL_N
50 ,MY_CTRL_P
51 ,MY_CTRL_Q
52 ,MY_CTRL_W
55 typedef struct _card {
56 struct _card *link;
57 PANEL *panel;
58 FORM *form;
59 char *title;
60 char *content;
61 } CARD;
63 static CARD *all_cards;
64 static char default_name[] = "cardfile.dat";
66 #if !HAVE_STRDUP
67 #define strdup my_strdup
68 static char *
69 strdup(char *s)
71 char *p = (char *) malloc(strlen(s) + 1);
72 if (p)
73 strcpy(p, s);
74 return (p);
76 #endif /* not HAVE_STRDUP */
78 static const char *
79 skip(const char *buffer)
81 while (isspace(UChar(*buffer)))
82 buffer++;
83 return buffer;
86 static void
87 trim(char *buffer)
89 unsigned n = strlen(buffer);
90 while (n-- && isspace(UChar(buffer[n])))
91 buffer[n] = 0;
94 /*******************************************************************************/
96 static CARD *
97 add_title(const char *title)
99 CARD *card, *p, *q;
101 for (p = all_cards, q = 0; p != 0; q = p, p = p->link) {
102 int cmp = strcmp(p->title, title);
103 if (cmp == 0)
104 return p;
105 if (cmp > 0)
106 break;
109 card = (CARD *) calloc(1, sizeof(CARD));
110 card->title = strdup(title);
111 card->content = strdup("");
113 if (q == 0) {
114 card->link = all_cards;
115 all_cards = card;
116 } else {
117 card->link = q->link;
118 q->link = card;
121 return card;
124 static void
125 add_content(CARD * card, const char *content)
127 unsigned total, offset;
129 content = skip(content);
130 if ((total = strlen(content)) != 0) {
131 if ((offset = strlen(card->content)) != 0) {
132 total += 1 + offset;
133 card->content = (char *) realloc(card->content, total + 1);
134 strcpy(card->content + offset++, " ");
135 } else {
136 if (card->content != 0)
137 free(card->content);
138 card->content = (char *) malloc(total + 1);
140 strcpy(card->content + offset, content);
144 static CARD *
145 new_card(void)
147 CARD *card = add_title("");
148 add_content(card, "");
149 return card;
152 static CARD *
153 find_card(char *title)
155 CARD *card;
157 for (card = all_cards; card != 0; card = card->link)
158 if (!strcmp(card->title, title))
159 break;
161 return card;
164 static void
165 read_data(char *fname)
167 FILE *fp;
168 CARD *card = 0;
169 char buffer[BUFSIZ];
171 if ((fp = fopen(fname, "r")) != 0) {
172 while (fgets(buffer, sizeof(buffer), fp)) {
173 trim(buffer);
174 if (isspace(UChar(*buffer))) {
175 if (card == 0)
176 card = add_title("");
177 add_content(card, buffer);
178 } else if ((card = find_card(buffer)) == 0) {
179 card = add_title(buffer);
182 fclose(fp);
186 /*******************************************************************************/
188 static void
189 write_data(const char *fname)
191 FILE *fp;
192 CARD *p = 0;
193 int n;
195 if (!strcmp(fname, default_name))
196 fname = "cardfile.out";
198 if ((fp = fopen(fname, "w")) != 0) {
199 for (p = all_cards; p != 0; p = p->link) {
200 FIELD **f = form_fields(p->form);
201 for (n = 0; f[n] != 0; n++) {
202 char *s = field_buffer(f[n], 0);
203 if (s != 0
204 && (s = strdup(s)) != 0) {
205 trim(s);
206 fprintf(fp, "%s%s\n", n ? "\t" : "", s);
207 free(s);
211 fclose(fp);
215 /*******************************************************************************/
218 * Count the cards
220 static int
221 count_cards(void)
223 CARD *p;
224 int count = 0;
226 for (p = all_cards; p != 0; p = p->link)
227 count++;
229 return count;
233 * Shuffle the panels to keep them in a natural hierarchy.
235 static void
236 order_cards(CARD * first, int depth)
238 if (first) {
239 if (depth && first->link)
240 order_cards(first->link, depth - 1);
241 top_panel(first->panel);
246 * Return the next card in the list
248 static CARD *
249 next_card(CARD * now)
251 if (now->link)
252 now = now->link;
253 return now;
257 * Return the previous card in the list
259 static CARD *
260 prev_card(CARD * now)
262 CARD *p;
263 for (p = all_cards; p != 0; p = p->link)
264 if (p->link == now)
265 return p;
266 return now;
269 /*******************************************************************************/
271 static int
272 form_virtualize(WINDOW *w)
274 int c = wgetch(w);
276 switch (c) {
277 case CTRL('W'):
278 return (MY_CTRL_W);
279 case CTRL('N'):
280 return (MY_CTRL_N);
281 case CTRL('P'):
282 return (MY_CTRL_P);
283 case CTRL('Q'):
284 case 033:
285 return (MY_CTRL_Q);
287 case KEY_BACKSPACE:
288 return (REQ_DEL_PREV);
289 case KEY_DC:
290 return (REQ_DEL_CHAR);
291 case KEY_LEFT:
292 return (REQ_LEFT_CHAR);
293 case KEY_RIGHT:
294 return (REQ_RIGHT_CHAR);
296 case KEY_DOWN:
297 case KEY_NEXT:
298 return (REQ_NEXT_FIELD);
299 case KEY_UP:
300 case KEY_PREVIOUS:
301 return (REQ_PREV_FIELD);
303 default:
304 return (c);
308 static FIELD **
309 make_fields(CARD * p, int form_high, int form_wide)
311 FIELD **f = (FIELD **) calloc(3, sizeof(FIELD *));
313 f[0] = new_field(1, form_wide, 0, 0, 0, 0);
314 set_field_back(f[0], A_REVERSE);
315 set_field_buffer(f[0], 0, p->title);
316 field_opts_off(f[0], O_BLANK);
318 f[1] = new_field(form_high - 1, form_wide, 1, 0, 0, 0);
319 set_field_buffer(f[1], 0, p->content);
320 set_field_just(f[1], JUSTIFY_LEFT);
321 field_opts_off(f[1], O_BLANK);
323 f[2] = 0;
324 return f;
327 static void
328 show_legend(void)
330 erase();
331 move(LINES - 3, 0);
332 addstr("^Q/ESC -- exit form ^W -- writes data to file\n");
333 addstr("^N -- go to next card ^P -- go to previous card\n");
334 addstr("Arrow keys move left/right within a field, up/down between fields");
337 #if (defined(KEY_RESIZE) && HAVE_WRESIZE) || NO_LEAKS
338 static void
339 free_form_fields(FIELD ** f)
341 int n;
343 for (n = 0; f[n] != 0; ++n) {
344 free_field(f[n]);
346 free(f);
348 #endif
350 /*******************************************************************************/
352 static void
353 cardfile(char *fname)
355 WINDOW *win;
356 CARD *p;
357 CARD *top_card;
358 int visible_cards = count_cards();
359 int panel_wide = COLS - (visible_cards * OFFSET_CARD);
360 int panel_high = LINES - (visible_cards * OFFSET_CARD) - 5;
361 int form_wide = panel_wide - 2;
362 int form_high = panel_high - 2;
363 int y = (visible_cards - 1) * OFFSET_CARD;
364 int x = 0;
365 int ch = ERR;
366 int last_ch;
367 int finished = FALSE;
369 show_legend();
371 /* make a panel for each CARD */
372 for (p = all_cards; p != 0; p = p->link) {
374 win = newwin(panel_high, panel_wide, y, x);
375 keypad(win, TRUE);
376 p->panel = new_panel(win);
377 box(win, 0, 0);
379 p->form = new_form(make_fields(p, form_high, form_wide));
380 set_form_win(p->form, win);
381 set_form_sub(p->form, derwin(win, form_high, form_wide, 1, 1));
382 post_form(p->form);
384 y -= OFFSET_CARD;
385 x += OFFSET_CARD;
388 order_cards(top_card = all_cards, visible_cards);
390 while (!finished) {
391 update_panels();
392 doupdate();
394 last_ch = ch;
395 ch = form_virtualize(panel_window(top_card->panel));
396 switch (form_driver(top_card->form, ch)) {
397 case E_OK:
398 break;
399 case E_UNKNOWN_COMMAND:
400 switch (ch) {
401 case MY_CTRL_Q:
402 finished = TRUE;
403 break;
404 case MY_CTRL_P:
405 top_card = prev_card(top_card);
406 order_cards(top_card, visible_cards);
407 break;
408 case MY_CTRL_N:
409 top_card = next_card(top_card);
410 order_cards(top_card, visible_cards);
411 break;
412 case MY_CTRL_W:
413 form_driver(top_card->form, REQ_VALIDATION);
414 write_data(fname);
415 break;
416 #if defined(KEY_RESIZE) && HAVE_WRESIZE
417 case KEY_RESIZE:
418 /* resizeterm already did "something" reasonable, but it cannot
419 * know much about layout. So let's make it nicer.
421 panel_wide = COLS - (visible_cards * OFFSET_CARD);
422 panel_high = LINES - (visible_cards * OFFSET_CARD) - 5;
424 form_wide = panel_wide - 2;
425 form_high = panel_high - 2;
427 y = (visible_cards - 1) * OFFSET_CARD;
428 x = 0;
430 show_legend();
431 for (p = all_cards; p != 0; p = p->link) {
432 FIELD **oldf = form_fields(p->form);
433 WINDOW *olds = form_sub(p->form);
435 win = form_win(p->form);
437 /* move and resize the card as needed
438 * FIXME: if the windows are shrunk too much, this won't do
440 mvwin(win, y, x);
441 wresize(win, panel_high, panel_wide);
443 /* reconstruct each form. Forms are not resizable, and
444 * there appears to be no good way to reload the text in
445 * a resized window.
447 werase(win);
449 unpost_form(p->form);
450 free_form(p->form);
452 p->form = new_form(make_fields(p, form_high, form_wide));
453 set_form_win(p->form, win);
454 set_form_sub(p->form, derwin(win, form_high, form_wide,
455 1, 1));
456 post_form(p->form);
458 free_form_fields(oldf);
459 delwin(olds);
461 box(win, 0, 0);
463 y -= OFFSET_CARD;
464 x += OFFSET_CARD;
466 break;
467 #endif
468 default:
469 beep();
470 break;
472 break;
473 default:
474 flash();
475 break;
478 #if NO_LEAKS
479 while (all_cards != 0) {
480 FIELD **f;
481 int count;
483 p = all_cards;
484 all_cards = all_cards->link;
486 f = form_fields(p->form);
487 count = field_count(p->form);
489 unpost_form(p->form); /* ...so we can free it */
490 free_form(p->form); /* this also disconnects the fields */
492 free_form_fields(f);
494 del_panel(p->panel);
495 free(p->title);
496 free(p->content);
497 free(p);
499 #endif
502 /*******************************************************************************/
505 main(int argc, char *argv[])
507 int n;
509 setlocale(LC_ALL, "");
511 initscr();
512 cbreak();
513 noecho();
515 if (argc > 1) {
516 for (n = 1; n < argc; n++)
517 read_data(argv[n]);
518 if (count_cards() == 0)
519 new_card();
520 cardfile(argv[1]);
521 } else {
522 read_data(default_name);
523 if (count_cards() == 0)
524 new_card();
525 cardfile(default_name);
528 endwin();
530 ExitProgram(EXIT_SUCCESS);
532 #else
534 main(void)
536 printf("This program requires the curses form and panel libraries\n");
537 ExitProgram(EXIT_FAILURE);
539 #endif