Remove the RCSID macro
[openafs.git] / src / gtx / frame.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #ifdef AFS_HPUX_ENV
15 #include <sys/types.h>
16 #endif
17 #include <lwp.h>
18
19 #include <string.h>
20 #include <stdlib.h>
21
22 #include "gtxobjects.h"
23 #include "gtxwindows.h"
24 #include "gtxcurseswin.h"
25 #include "gtxinput.h"
26 #include "gtxkeymap.h"
27 #include "gtxframe.h"
28
29 static struct keymap_map *recursiveMap = 0;
30 static char menubuffer[1024];   /*Buffer for menu selections */
31 int gtxframe_exitValue = 0;     /*Program exit value */
32
33 int
34 gtxframe_CtrlUCmd(void *aparam, void *arock)
35 {
36     struct gwin *awindow = (struct gwin *) aparam;
37     struct gtx_frame *tframe;
38
39     tframe = awindow->w_frame;
40     if (!tframe->defaultLine)
41         return -1;
42     *(tframe->defaultLine) = 0;
43     return 0;
44 }
45
46 int
47 gtxframe_CtrlHCmd(void *aparam, void *arock)
48 {
49     struct gwin *awindow = (struct gwin *) aparam;
50     
51     register struct gtx_frame *tframe;
52     register char *tp;
53     register int pos;
54
55     tframe = awindow->w_frame;
56     if (!(tp = tframe->defaultLine))
57         return -1;
58     pos = strlen(tp);
59     if (pos == 0)
60         return 0;               /* rubout at the end of the line */
61     tp[pos - 1] = 0;
62     return 0;
63 }
64
65 int
66 gtxframe_RecursiveEndCmd(void *aparam, void *arock)
67 {
68     struct gwin *awindow = (struct gwin *) aparam;
69     
70     register struct gtx_frame *tframe;
71
72     tframe = awindow->w_frame;
73     tframe->flags |= GTXFRAME_RECURSIVEEND;
74     tframe->flags &= ~GTXFRAME_RECURSIVEERR;
75     return 0;
76 }
77
78 int
79 gtxframe_RecursiveErrCmd(void *aparam, void *arock)
80 {
81     struct gwin *awindow = (struct gwin *) aparam;
82     
83     register struct gtx_frame *tframe;
84
85     tframe = awindow->w_frame;
86     tframe->flags |= GTXFRAME_RECURSIVEEND;
87     tframe->flags |= GTXFRAME_RECURSIVEERR;
88     return 0;
89 }
90
91 int
92 gtxframe_SelfInsertCmd(void *aparam, void *rockparam)
93 {
94     struct gwin *awindow = (struct gwin *) aparam;
95     
96     int arock = (int) rockparam;
97     
98     register struct gtx_frame *tframe;
99     register int pos;
100     register char *tp;
101
102     tframe = awindow->w_frame;
103     if (!(tp = tframe->defaultLine))
104         return -1;
105     pos = strlen(tp);
106     tp[pos] = arock;            /* arock has char to insert */
107     tp[pos + 1] = 0;            /* null-terminate it, too */
108     return 0;
109 }
110
111 /* save map, setup recursive map and install it */
112 static int
113 SaveMap(struct gtx_frame *aframe)
114 {
115     char tstring[2];
116     register int i;
117
118     if (!recursiveMap) {
119         /* setup recursive edit map if not previously done */
120         recursiveMap = keymap_Create();
121         keymap_BindToString(recursiveMap, "\010", gtxframe_CtrlHCmd, NULL,
122                             NULL);
123         keymap_BindToString(recursiveMap, "\177", gtxframe_CtrlHCmd, NULL,
124                             NULL);
125         keymap_BindToString(recursiveMap, "\025", gtxframe_CtrlUCmd, NULL,
126                             NULL);
127         keymap_BindToString(recursiveMap, "\033", gtxframe_RecursiveEndCmd,
128                             NULL, NULL);
129         keymap_BindToString(recursiveMap, "\015", gtxframe_RecursiveEndCmd,
130                             NULL, NULL);
131         keymap_BindToString(recursiveMap, "\012", gtxframe_RecursiveEndCmd,
132                             NULL, NULL);
133         keymap_BindToString(recursiveMap, "\003", gtxframe_RecursiveErrCmd,
134                             NULL, NULL);
135         keymap_BindToString(recursiveMap, "\007", gtxframe_RecursiveErrCmd,
136                             NULL, NULL);
137
138         for (i = 040; i < 0177; i++) {
139             tstring[0] = i;
140             tstring[1] = 0;
141             keymap_BindToString(recursiveMap, tstring, gtxframe_SelfInsertCmd,
142                                 NULL, (void *)i);
143         }
144     }
145     aframe->savemap = aframe->keymap;
146     aframe->keymap = recursiveMap;
147     keymap_InitState(aframe->keystate, aframe->keymap);
148     return 0;
149 }
150
151 /* Restore map to previous value */
152 static int
153 RestoreMap(struct gtx_frame *aframe)
154 {
155     aframe->keymap = aframe->savemap;
156     aframe->savemap = (struct keymap_map *)0;
157     keymap_InitState(aframe->keystate, aframe->keymap);
158     return 0;
159 }
160
161 int
162 gtxframe_SetFrame(struct gwin *awin, struct gtx_frame *aframe)
163 {
164     if (awin->w_frame) {
165         /* Unthread this frame */
166         awin->w_frame->window = NULL;
167     }
168     awin->w_frame = aframe;
169     aframe->window = awin;      /* Set frame's window ptr */
170     return 0;
171 }
172
173 struct gtx_frame *
174 gtxframe_GetFrame(struct gwin *awin)
175 {
176     return awin->w_frame;
177 }
178
179 /* Add a menu string to display list */
180 int
181 gtxframe_AddMenu(struct gtx_frame *aframe, char *alabel, char *astring)
182 {
183     register struct gtxframe_menu *tmenu;
184
185     if (aframe->menus)
186         for (tmenu = aframe->menus; tmenu; tmenu = tmenu->next) {
187             if (strcmp(alabel, tmenu->name) == 0)
188                 break;
189     } else
190         tmenu = (struct gtxframe_menu *)0;
191     if (!tmenu) {
192         /* Handle everything but the command string, which is handled by the
193          * common-case code below */
194         tmenu = (struct gtxframe_menu *)malloc(sizeof(*tmenu));
195         if (tmenu == (struct gtxframe_menu *)0)
196             return (-1);
197         memset(tmenu, 0, sizeof(*tmenu));
198         tmenu->next = aframe->menus;
199         aframe->menus = tmenu;
200         tmenu->name = gtx_CopyString(alabel);
201     }
202
203     /*
204      * Common case: redo the string labels.  Note: at this point, tmenu
205      * points to a valid menu.
206      */
207     if (tmenu->cmdString)
208         free(tmenu->cmdString);
209     tmenu->cmdString = gtx_CopyString(astring);
210     return 0;
211 }
212
213 /* Delete a given menu from a frame*/
214 int
215 gtxframe_DeleteMenu(struct gtx_frame *aframe, char *alabel)
216 {
217     register struct gtxframe_menu *tm, **lm;
218
219     for (lm = &aframe->menus, tm = *lm; tm; lm = &tm->next, tm = *lm) {
220         if (strcmp(alabel, tm->name) == 0) {
221             /* found it, remove and return success */
222             *lm = tm->next;     /* unthread from list */
223             free(tm->name);
224             free(tm->cmdString);
225             free(tm);
226             return (0);
227         }
228     }
229     return (-1);                /* failed to find entry to delete */
230 }
231
232 /* Function to remove all known menus */
233 int
234 gtxframe_ClearMenus(struct gtx_frame *aframe)
235 {
236
237     register struct gtxframe_menu *tm, *nm;
238
239     if (aframe->menus != (struct gtxframe_menu *)0) {
240         for (tm = aframe->menus; tm; tm = nm) {
241             nm = tm->next;
242             free(tm->name);
243             free(tm->cmdString);
244             free(tm);
245         }
246     }
247
248     aframe->menus = (struct gtxframe_menu *)0;
249     return 0;
250 }
251
252 int
253 gtxframe_AskForString(struct gtx_frame *aframe, char *aprompt, 
254                       char *adefault, char *aresult, int aresultSize)
255 {
256     register int code;
257     register char *tp;
258
259     /* Ensure recursive-edit map is initialized */
260     SaveMap(aframe);
261
262     /* Set up display */
263     if (aframe->promptLine)
264         free(aframe->promptLine);
265     if (aframe->defaultLine)
266         free(aframe->defaultLine);
267     aframe->promptLine = gtx_CopyString(aprompt);
268     tp = aframe->defaultLine = (char *)malloc(1024);
269     if (tp == NULL)
270         return (-1);
271     if (adefault)
272         strcpy(tp, adefault);
273     else
274         *tp = 0;
275
276     /* Do recursive edit */
277     gtx_InputServer(aframe->window);
278     tp = aframe->defaultLine;   /* In case command reallocated it */
279
280     /* Back from recursive edit, check out what's happened */
281     if (aframe->flags & GTXFRAME_RECURSIVEERR) {
282         code = -1;
283         goto done;
284     }
285     code = strlen(tp);
286     if (code + 1 > aresultSize) {
287         code = -2;
288         goto done;
289     }
290     strcpy(aresult, tp);
291     code = 0;
292
293     /* Fall through to cleanup and return code */
294   done:
295     RestoreMap(aframe);
296     if (aframe->promptLine)
297         free(aframe->promptLine);
298     if (aframe->defaultLine)
299         free(aframe->defaultLine);
300     aframe->defaultLine = aframe->promptLine = NULL;
301     if (code)
302         gtxframe_DisplayString(aframe, "[Aborted]");
303     return (code);
304 }
305
306 int
307 gtxframe_DisplayString(struct gtx_frame *aframe, char *amsgLine)
308 {
309     if (aframe->messageLine)
310         free(aframe->messageLine);
311     aframe->messageLine = gtx_CopyString(amsgLine);
312     return 0;
313 }
314
315 /* Called by input processor to try to clear the dude */
316 int
317 gtxframe_ClearMessageLine(struct gtx_frame *aframe)
318 {
319     /* If we haven't shown message long enough yet, just return */
320     if (aframe->flags & GTXFRAME_NEWDISPLAY)
321         return (0);
322     if (aframe->messageLine)
323         free(aframe->messageLine);
324     aframe->messageLine = NULL;
325     return (0);
326 }
327
328 static int
329 ShowMessageLine(struct gtx_frame *aframe)
330 {
331     struct gwin_strparams strparms;
332     struct gwin_sizeparams sizeparms;
333     register char *tp;
334
335     if (!aframe->window)
336         return -1;
337
338     /* First, find window size */
339     WOP_GETDIMENSIONS(aframe->window, &sizeparms);
340
341     if (aframe->promptLine) {
342         memset(&strparms, 0, sizeof(strparms));
343         strparms.x = 0;
344         strparms.y = sizeparms.maxy - 1;
345         strparms.highlight = 1;
346         tp = strparms.s = (char *)malloc(1024);
347         strcpy(tp, aframe->promptLine);
348         strcat(tp, aframe->defaultLine);
349         WOP_DRAWSTRING(aframe->window, &strparms);
350         aframe->flags |= GTXFRAME_NEWDISPLAY;
351     } else if (aframe->messageLine) {
352         /* Otherwise we're visible, print the message at the bottom */
353         memset(&strparms, 0, sizeof(strparms));
354         strparms.highlight = 1;
355         strparms.x = 0;
356         strparms.y = sizeparms.maxy - 1;
357         strparms.s = aframe->messageLine;
358         WOP_DRAWSTRING(aframe->window, &strparms);
359         aframe->flags |= GTXFRAME_NEWDISPLAY;
360     }
361     return (0);
362 }
363
364 /* Exit function, returning whatever has been put in its argument */
365 int
366 gtxframe_ExitCmd(void *a_exitValuep, void *arock)
367 {                               /*gtxframe_ExitCmd */
368
369     int exitval;                /*Value we've been asked to exit with */
370
371     /* This next call should be type independent! */
372     gator_cursesgwin_cleanup(&gator_basegwin);
373
374     exitval = *((int *)(a_exitValuep));
375     exit(exitval);
376
377 }                               /*gtxframe_ExitCmd */
378
379 struct gtx_frame *
380 gtxframe_Create(void)
381 {
382     struct gtx_frame *tframe;
383     struct keymap_map *newkeymap;
384     struct keymap_state *newkeystate;
385
386     /*
387      * Allocate all the pieces first: frame, keymap, and key state.
388      */
389     tframe = (struct gtx_frame *)malloc(sizeof(struct gtx_frame));
390     if (tframe == (struct gtx_frame *)0) {
391         return ((struct gtx_frame *)0);
392     }
393
394     newkeymap = keymap_Create();
395     if (newkeymap == (struct keymap_map *)0) {
396         /*
397          * Get rid of the frame before exiting.
398          */
399         free(tframe);
400         return ((struct gtx_frame *)0);
401     }
402
403     newkeystate = (struct keymap_state *)
404         malloc(sizeof(struct keymap_state));
405     if (newkeystate == (struct keymap_state *)0) {
406         /*
407          * Get rid of the frame AND the keymap before exiting.
408          */
409         free(tframe);
410         free(newkeymap);
411         return ((struct gtx_frame *)0);
412     }
413
414     /*
415      * Now that all the pieces exist, fill them in and stick them in
416      * the right places.
417      */
418     memset(tframe, 0, sizeof(struct gtx_frame));
419     tframe->keymap = newkeymap;
420     tframe->keystate = newkeystate;
421     keymap_InitState(tframe->keystate, tframe->keymap);
422     keymap_BindToString(tframe->keymap, "\003", gtxframe_ExitCmd, "ExitCmd",
423                         (char *)(&gtxframe_exitValue));
424
425     /*
426      * At this point, we return successfully.
427      */
428     return (tframe);
429 }
430
431 int
432 gtxframe_Delete(struct gtx_frame *aframe)
433 {
434     keymap_Delete(aframe->keymap);
435     free(aframe->keystate);
436     if (aframe->messageLine)
437         free(aframe->messageLine);
438     free(aframe);
439     return 0;
440 }
441
442 int
443 gtxframe_Display(struct gtx_frame *aframe, struct gwin *awm)
444 {
445     register struct gtxframe_dlist *tlist;
446     register struct gtxframe_menu *tm;
447     struct gwin_strparams strparms;
448
449     /* Run through the menus, displaying them on the top line */
450     *menubuffer = 0;
451     for (tm = aframe->menus; tm; tm = tm->next) {
452         strcat(menubuffer, tm->name);
453         strcat(menubuffer, ":");
454         strcat(menubuffer, tm->cmdString);
455         strcat(menubuffer, " ");
456     }
457     if (menubuffer[0] != 0) {
458         memset(&strparms, 0, sizeof(strparms));
459         strparms.x = 0;
460         strparms.y = 0;
461         strparms.s = menubuffer;
462         strparms.highlight = 1;
463         WOP_DRAWSTRING(awm, &strparms);
464     }
465
466     /* Run through the display list, displaying all objects */
467     for (tlist = aframe->display; tlist; tlist = tlist->next) {
468         OOP_DISPLAY(((struct onode *)(tlist->data)));
469     }
470
471     /* Finally, show the message line */
472     ShowMessageLine(awm->w_frame);
473     return (0);
474 }
475
476 /* Add an object to a window's display list */
477 int
478 gtxframe_AddToList(struct gtx_frame *aframe, struct onode *aobj)
479 {
480     register struct gtxframe_dlist *tlist;
481
482     for (tlist = aframe->display; tlist; tlist = tlist->next) {
483         if (tlist->data == (char *)aobj) {
484             /*
485              * Don't add the same thing twice.
486              */
487             return (-1);
488         }
489     }
490
491     /*
492      * OK, it's not alreadyt there.  Create a new list object, fill it
493      * in, and splice it on.
494      */
495     tlist = (struct gtxframe_dlist *)malloc(sizeof(struct gtxframe_dlist));
496     if (tlist == (struct gtxframe_dlist *)0)
497         return (-1);
498     tlist->data = (char *)aobj;
499     tlist->next = aframe->display;
500     aframe->display = tlist;
501     return (0);
502 }
503
504 /* Remove an object from a display list, if it is already there */
505 int
506 gtxframe_RemoveFromList(struct gtx_frame *aframe, struct onode *aobj)
507 {
508     register struct gtxframe_dlist *tlist, **plist;
509
510     plist = &aframe->display;
511     for (tlist = *plist; tlist; plist = &tlist->next, tlist = *plist) {
512         if (tlist->data == (char *)aobj) {
513             *plist = tlist->next;
514             free(tlist);
515             return 0;
516         }
517     }
518     return (-1);                /* Item not found */
519 }
520
521 /* Clear out everything on the display list for the given frame*/
522 int
523 gtxframe_ClearList(struct gtx_frame *aframe)
524 {
525     register struct gtxframe_dlist *tlist, *nlist;
526
527     if (aframe->display != (struct gtxframe_dlist *)0) {
528         /*
529          * Throw away each display list structure (we have at least
530          * one).
531          */
532         for (tlist = aframe->display; tlist; tlist = nlist) {
533             nlist = tlist->next;
534             free(tlist);
535         }
536     }
537
538     aframe->display = (struct gtxframe_dlist *)0;
539     return 0;
540 }