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