Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / gtx / curseswindows.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 /*
11 * gator_curseswindows.c
12 *
13 * Description:
14 * Implementation of the gator curses window facility.
15 *
16 *------------------------------------------------------------------------*/
17
18 #include <afsconfig.h>
19 #include <afs/param.h>
20
21 #include <roken.h>
22
23 #if !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD80_ENV)
24 #include <sgtty.h>
25 #endif
26
27 #include <lwp.h>
28
29 #include "gtxcurseswin.h" /*Interface definition */
30 #include "gtxobjects.h"
31 #include "gtxframe.h"
32
33 int curses_debug; /*Is debugging turned on? */
34 static char mn[] = "gator_curseswindows"; /*Module name */
35
36 /*
37 * Version of standard operations for a curses window.
38 */
39 struct gwinops curses_gwinops = {
40 gator_cursesgwin_box,
41 gator_cursesgwin_clear,
42 gator_cursesgwin_destroy,
43 gator_cursesgwin_display,
44 gator_cursesgwin_drawline,
45 gator_cursesgwin_drawrectangle,
46 gator_cursesgwin_drawchar,
47 gator_cursesgwin_drawstring,
48 gator_cursesgwin_invert,
49 gator_cursesgwin_getchar,
50 gator_cursesgwin_getdimensions,
51 gator_cursesgwin_wait,
52 };
53
54 struct gwinbaseops gator_curses_gwinbops = {
55 gator_cursesgwin_create,
56 gator_cursesgwin_cleanup,
57 };
58
59
60 /*
61 * Macros to map pixel positions to row & column positions.
62 * (Note: for now, they are the identity function!!)
63 */
64 #define GATOR_MAP_X_TO_COL(w, x) (x)
65 #define GATOR_MAP_Y_TO_LINE(w, y) (y)
66
67 /*------------------------------------------------------------------------
68 * gator_cursesgwin_init
69 *
70 * Description:
71 * Initialize the curses window package.
72 *
73 * Arguments:
74 * int adebug: Is debugging turned on?
75 *
76 * Returns:
77 * 0 on success,
78 * Error value otherwise.
79 *
80 * Environment:
81 * Nothing interesting.
82 *
83 * Side Effects:
84 * As advertised.
85 *------------------------------------------------------------------------*/
86
87 int
88 gator_cursesgwin_init(int adebug)
89 { /*gator_cursesgwin_init */
90
91 static char rn[] = "gator_cursesgwin_init"; /*Routine name */
92 struct gator_cursesgwin *c_data; /*Ptr to curses-specific data */
93
94 /*
95 * Remember if we'll be doing debugging, then init the curses package.
96 */
97 curses_debug = adebug;
98
99 if (curses_debug)
100 fprintf(stderr, "[%s:%s] Calling initscr()\n", mn, rn);
101 initscr();
102
103 /*
104 * Fill out the base window structure for curses.
105 */
106 if (curses_debug)
107 fprintf(stderr,
108 "[%s:%s] Allocating %" AFS_SIZET_FMT " bytes for curses window private space in base window\n",
109 mn, rn, sizeof(struct gator_cursesgwin));
110 c_data = malloc(sizeof(struct gator_cursesgwin));
111 if (c_data == (struct gator_cursesgwin *)0) {
112 fprintf(stderr,
113 "[%s:%s] Can't allocate %" AFS_SIZET_FMT " bytes for curses window private space in base window\n",
114 mn, rn, sizeof(struct gator_cursesgwin));
115 return (-1);
116 }
117
118 /*
119 * Fill in the curses-specific base window info. We assume that chars are 8x13.
120 */
121 c_data->wp = stdscr;
122 c_data->charwidth = 8;
123 c_data->charheight = 13;
124 c_data->box_vertchar = '|';
125 c_data->box_horizchar = '-';
126
127 /*
128 * Fill in the generic base window info.
129 */
130 gator_basegwin.w_type = GATOR_WIN_CURSES;
131 gator_basegwin.w_x = 0;
132 gator_basegwin.w_y = 0;
133 gator_basegwin.w_width = c_data->charwidth * COLS;
134 gator_basegwin.w_height = c_data->charheight * LINES;
135 gator_basegwin.w_changed = 0;
136 gator_basegwin.w_op = &curses_gwinops;
137 gator_basegwin.w_parent = NULL;
138
139 /*
140 * Plug the private data into the generic part of the base window.
141 */
142 gator_basegwin.w_data = (int *)c_data;
143
144 /*
145 * Now, set the terminal into the right mode for handling input
146 */
147 raw(); /* curses raw mode */
148
149 /* init the frame */
150 gator_basegwin.w_frame = gtxframe_Create();
151
152 /*
153 * Clear out the screen and return the good news.
154 */
155 wclear(((struct gator_cursesgwin *)(gator_basegwin.w_data))->wp);
156 return (0);
157
158 } /*gator_cursesgwin_init */
159
160 /*------------------------------------------------------------------------
161 * gator_cursesgwin_create
162 *
163 * Description:
164 * Create a curses window (incorrectly).
165 *
166 * Arguments:
167 * struct gator_cursesgwin_params *params : Ptr to creation parameters.
168 *
169 * Returns:
170 * Ptr to the created curses window if successful,
171 * Null ptr otherwise.
172 *
173 * Environment:
174 * Nothing interesting.
175 *
176 * Side Effects:
177 * As advertised.
178 *------------------------------------------------------------------------*/
179
180 struct gwin *
181 gator_cursesgwin_create(void * rock)
182 {
183 static char rn[] = "gator_cursesgwin_create"; /*Routine name */
184 struct gator_cursesgwin_params *params = (struct gator_cursesgwin_params *)rock;
185 struct gwin *newgwin; /*Ptr to new curses window */
186 struct gator_cursesgwin *c_data; /*Ptr to curses-specific data */
187 WINDOW *newcursgwin; /*Ptr to new curses window */
188
189 if (curses_debug)
190 fprintf(stderr,
191 "[%s:%s] Allocating %" AFS_SIZET_FMT " bytes for new gwin structure\n", mn,
192 rn, sizeof(struct gwin));
193 newgwin = malloc(sizeof(struct gwin));
194 if (newgwin == NULL) {
195 fprintf(stderr,
196 "[%s:%s] Can't malloc() %" AFS_SIZET_FMT " bytes for new gwin structure: Errno is %d\n",
197 mn, rn, sizeof(struct gwin), errno);
198 return (NULL);
199 }
200
201 newgwin->w_type = GATOR_WIN_CURSES;
202 newgwin->w_x = params->gwin_params.cr_x;
203 newgwin->w_y = params->gwin_params.cr_y;
204 newgwin->w_width = params->gwin_params.cr_width;
205 newgwin->w_height = params->gwin_params.cr_height;
206 newgwin->w_changed = 1;
207 newgwin->w_op = &curses_gwinops;
208 newgwin->w_parent = params->gwin_params.cr_parentwin;
209
210 if (curses_debug)
211 fprintf(stderr,
212 "[%s:%s] Allocating %" AFS_SIZET_FMT " bytes for curses window private space\n",
213 mn, rn, sizeof(struct gator_cursesgwin));
214 c_data = malloc(sizeof(struct gator_cursesgwin));
215 if (c_data == (struct gator_cursesgwin *)0) {
216 fprintf(stderr,
217 "[%s:%s] Can't allocate %" AFS_SIZET_FMT " bytes for curses window private space\n",
218 mn, rn, sizeof(struct gator_cursesgwin));
219 free(newgwin);
220 return (NULL);
221 }
222
223 newcursgwin = newwin(newgwin->w_height, /*Number of lines */
224 newgwin->w_width, /*Number of columns */
225 newgwin->w_y, /*Beginning y value */
226 newgwin->w_x); /*Beginning x value */
227 if (newcursgwin == (WINDOW *) 0) {
228 fprintf(stderr,
229 "[%s:%s] Failed to create curses window via newwin()\n", mn,
230 rn);
231 free(newgwin);
232 free(c_data);
233 return (NULL);
234 }
235
236 /*
237 * Now, fill in the curses-specific window info.
238 */
239 c_data->wp = newcursgwin;
240 c_data->charwidth = params->charwidth;
241 c_data->charheight = params->charheight;
242 c_data->box_vertchar = params->box_vertchar;
243 c_data->box_horizchar = params->box_horizchar;
244
245 /*
246 * Plug in a frame at the top-level.
247 */
248 newgwin->w_frame = gtxframe_Create();
249
250 /*
251 * Plug the curses private data into the generic window object, then
252 * return the new window's info.
253 */
254 newgwin->w_data = (int *)c_data;
255 return (newgwin);
256
257 } /*gator_cursesgwin_create */
258
259 /*------------------------------------------------------------------------
260 * gator_cursesgwin_cleanup
261 *
262 * Description:
263 * Clean up, probably right before the caller exits.
264 *
265 * Arguments:
266 * struct gwin *gwp : Ptr to base window.
267 *
268 * Returns:
269 * 0 on success,
270 * Error value otherwise.
271 *
272 * Environment:
273 * Nothing interesting.
274 *
275 * Side Effects:
276 * As advertised.
277 *------------------------------------------------------------------------*/
278
279 int
280 gator_cursesgwin_cleanup(struct gwin *gwp)
281 { /*gator_cursesgwin_cleanup */
282
283 static char rn[] = "gator_cursesgwin_cleanup"; /*Routine name */
284 struct gator_cursesgwin *cwp; /*Curses private area ptr */
285
286 cwp = (struct gator_cursesgwin *)(gwp->w_data);
287
288 /*
289 * Cleaning up in curses is extremely easy - one simple call. We also
290 * want to clear the screen before we go.
291 */
292 if (curses_debug)
293 fprintf(stderr, "[%s:%s] Calling wclear() on window at %p\n", mn,
294 rn, cwp->wp);
295 wclear(cwp->wp);
296 wrefresh(cwp->wp);
297
298 /*
299 * Now, set the terminal back into normal mode.
300 */
301 noraw();
302
303 if (curses_debug)
304 fprintf(stderr, "[%s:%s] Calling endwin()\n", mn, rn);
305 endwin();
306
307 return (0);
308
309 } /*gator_cursesgwin_cleanup */
310
311 /*------------------------------------------------------------------------
312 * gator_cursesgwin_box
313 *
314 * Description:
315 * Draw a box around the given curses window.
316 *
317 * Arguments:
318 * struct gwin *gwp : Ptr to the curses window to draw
319 * a box around.
320 *
321 * Returns:
322 * 0 on success,
323 * Error value otherwise.
324 *
325 * Environment:
326 * Nothing interesting.
327 *
328 * Side Effects:
329 * As advertised.
330 *------------------------------------------------------------------------*/
331
332 int
333 gator_cursesgwin_box(struct gwin *gwp)
334 { /*gator_cursesgwin_box */
335
336 static char rn[] = "gator_cursesgwin_box"; /*Routine name */
337 struct gator_cursesgwin *cwp; /*Ptr to curses private area */
338
339 cwp = (struct gator_cursesgwin *)(gwp->w_data);
340 if (curses_debug)
341 fprintf(stderr, "[%s:%s] Calling box() on window at %p\n", mn, rn,
342 cwp->wp);
343 box(cwp->wp, cwp->box_vertchar, cwp->box_horizchar);
344
345 return (0);
346
347 } /*gator_cursesgwin_box */
348
349 /*------------------------------------------------------------------------
350 * gator_cursesgwin_clear
351 *
352 * Description:
353 * Clear out the given curses window.
354 *
355 * Arguments:
356 * struct gwin *gwp : Ptr to the curses window to clear out.
357 *
358 * Returns:
359 * 0 on success,
360 * Error value otherwise.
361 *
362 * Environment:
363 * Nothing interesting.
364 *
365 * Side Effects:
366 * As advertised.
367 *------------------------------------------------------------------------*/
368
369 int
370 gator_cursesgwin_clear(struct gwin *gwp)
371 { /*gator_cursesgwin_clear */
372
373 static char rn[] = "gator_cursesgwin_clear"; /*Routine name */
374 struct gator_cursesgwin *cwp; /*Ptr to curses private area */
375
376 /*
377 * Clearing windows is very easy in curses; just one call will do it.
378 */
379 cwp = (struct gator_cursesgwin *)(gwp->w_data);
380 if (curses_debug)
381 fprintf(stderr, "[%s:%s] Calling wclear() on window at %p\n", mn,
382 rn, cwp->wp);
383 wclear(cwp->wp);
384
385 return (0);
386
387 } /*gator_cursesgwin_clear */
388
389 /*------------------------------------------------------------------------
390 * gator_cursesgwin_destroy
391 *
392 * Description:
393 * Destroy the given curses window.
394 *
395 * Arguments:
396 * struct gwin *gwp : Ptr to the curses window to destroy.
397 *
398 * Returns:
399 * 0 on success,
400 * Error value otherwise.
401 *
402 * Environment:
403 * Nothing interesting.
404 *
405 * Side Effects:
406 * As advertised.
407 *------------------------------------------------------------------------*/
408
409 int
410 gator_cursesgwin_destroy(struct gwin *gwp)
411 { /*gator_cursesgwin_destroy */
412
413 static char rn[] = "gator_cursesgwin_destroy"; /*Routine name */
414 struct gator_cursesgwin *cwp; /*Ptr to curses private area */
415
416 cwp = (struct gator_cursesgwin *)(gwp->w_data);
417 if (curses_debug)
418 fprintf(stderr, "[%s:%s] Calling delwin() on window at %p\n", mn,
419 rn, cwp->wp);
420 delwin(cwp->wp);
421
422 return (0);
423
424 } /*gator_cursesgwin_destroy */
425
426 /*------------------------------------------------------------------------
427 * gator_cursesgwin_display
428 *
429 * Description:
430 * Display/redraw the given curses window.
431 *
432 * Arguments:
433 * struct gwin *gwp : Ptr to the curses window to draw.
434 *
435 * Returns:
436 * 0 on success,
437 * Error value otherwise.
438 *
439 * Environment:
440 * Nothing interesting.
441 *
442 * Side Effects:
443 * As advertised.
444 *------------------------------------------------------------------------*/
445
446 int
447 gator_cursesgwin_display(struct gwin *gwp)
448 { /*gator_cursesgwin_display */
449
450 struct gator_cursesgwin *cwp; /*Curses private area ptr */
451
452 cwp = (struct gator_cursesgwin *)(gwp->w_data);
453
454 wclear(cwp->wp); /* clear screen */
455 gtxframe_Display(gwp->w_frame, gwp); /* display the frame */
456 wrefresh(cwp->wp); /* redraw the guy */
457 return (0);
458
459 } /*gator_cursesgwin_display */
460
461 /*------------------------------------------------------------------------
462 * gator_cursesgwin_drawline
463 *
464 * Description:
465 * Draw a line between two points in the given curses
466 * window.
467 *
468 * Arguments:
469 * struct gwin *gwp : Ptr to the curses window in which
470 * the line is to be drawn.
471 * struct gwin_lineparams *params : Ptr to other params.
472 *
473 * Returns:
474 * 0 on success,
475 * Error value otherwise.
476 *
477 * Environment:
478 * Nothing interesting.
479 *
480 * Side Effects:
481 * As advertised.
482 *------------------------------------------------------------------------*/
483
484 int
485 gator_cursesgwin_drawline(struct gwin *gwp, struct gwin_lineparams *params)
486 { /*gator_cursesgwin_drawline */
487
488 static char rn[] = "gator_cursesgwin_drawline"; /*Routine name */
489
490 if (curses_debug)
491 fprintf(stderr, "[%s:%s] This routine is currently a no-op\n", mn,
492 rn);
493
494 return (0);
495
496 } /*gator_cursesgwin_drawline */
497
498 /*------------------------------------------------------------------------
499 * gator_cursesgwin_drawrectangle
500 *
501 * Description:
502 * Draw a rectangle in the given curses window.
503 *
504 * Arguments:
505 * struct gwin *gwp : Ptr to the curses window in which
506 * the rectangle is to be drawn.
507 * struct gwin_rectparams *params : Ptr to other params.
508 *
509 * Returns:
510 * 0 on success,
511 * Error value otherwise.
512 *
513 * Environment:
514 * Nothing interesting.
515 *
516 * Side Effects:
517 * As advertised.
518 *------------------------------------------------------------------------*/
519
520 int
521 gator_cursesgwin_drawrectangle(struct gwin *gwp, struct gwin_rectparams *params)
522 { /*gator_cursesgwin_drawrectangle */
523
524 static char rn[] = "gator_cursesgwin_drawrectangle"; /*Routine name */
525
526 if (curses_debug)
527 fprintf(stderr, "[%s:%s] This routine is currently a no-op\n", mn,
528 rn);
529
530 return (0);
531
532 } /*gator_cursesgwin_drawrectangle */
533
534 /*------------------------------------------------------------------------
535 * gator_cursesgwin_drawchar
536 *
537 * Description:
538 * Draw a character in the given curses window.
539 *
540 * Arguments:
541 * struct gwin *gwp : Ptr to the curses window in which
542 * the character is to be drawn.
543 * struct gwin_charparams *params : Ptr to other params.
544 *
545 * Returns:
546 * 0 on success,
547 * Error value otherwise.
548 *
549 * Environment:
550 * Nothing interesting.
551 *
552 * Side Effects:
553 * As advertised.
554 *------------------------------------------------------------------------*/
555
556 int
557 gator_cursesgwin_drawchar(struct gwin *gwp, struct gwin_charparams *params)
558 { /*gator_cursesgwin_drawchar */
559
560 static char rn[] = "gator_cursesgwin_drawchar"; /*Routine name */
561 struct gator_cursesgwin *cwp; /*Ptr to curses private area */
562 int curses_x, curses_y; /*Mapped x,y positions */
563 int code=0;
564
565 cwp = (struct gator_cursesgwin *)(gwp->w_data);
566 curses_x = GATOR_MAP_X_TO_COL(cwp, params->x);
567 curses_y = GATOR_MAP_Y_TO_LINE(cwp, params->y);
568 if (curses_debug)
569 fprintf(stderr,
570 "[%s:%s] Drawing char '%c' on window at %p at (%d, %d) [line %d, column %d]%s\n",
571 mn, rn, params->c, cwp->wp, params->x, params->y, curses_y,
572 curses_x, (params->highlight ? ", using standout mode" : ""));
573 wmove(cwp->wp, curses_y, curses_x);
574 if (params->highlight) {
575 code=wstandout(cwp->wp);
576 if (code)
577 return (code);
578 }
579 waddch(cwp->wp, params->c);
580 if (params->highlight) {
581 code=wstandend(cwp->wp);
582 if (code)
583 return (code);
584 }
585
586 return (0);
587
588 } /*gator_cursesgwin_drawchar */
589
590 /*------------------------------------------------------------------------
591 * gator_cursesgwin_drawstring
592 *
593 * Description:
594 * Draw a string in the given curses window.
595 *
596 * Arguments:
597 * struct gwin *gwp : Ptr to the curses window in which
598 * the string is to be drawn.
599 * struct gwin_strparams *params : Ptr to other params.
600 *
601 * Returns:
602 * 0 on success,
603 * Error value otherwise.
604 *
605 * Environment:
606 * Nothing interesting.
607 *
608 * Side Effects:
609 * As advertised.
610 *------------------------------------------------------------------------*/
611
612 int
613 gator_cursesgwin_drawstring(struct gwin *gwp, struct gwin_strparams *params)
614 { /*gator_cursesgwin_drawstring */
615
616 static char rn[] = "gator_cursesgwin_drawstring"; /*Routine name */
617 struct gator_cursesgwin *cwp; /*Ptr to curses private area */
618 int curses_x, curses_y; /*Mapped x,y positions */
619 int code=0;
620
621 cwp = (struct gator_cursesgwin *)(gwp->w_data);
622 curses_x = GATOR_MAP_X_TO_COL(cwp, params->x);
623 curses_y = GATOR_MAP_Y_TO_LINE(cwp, params->y);
624 if (curses_debug)
625 fprintf(stderr,
626 "[%s:%s] Drawing string '%s' on window at %p at (%d, %d) [line %d, column %d]%s\n",
627 mn, rn, params->s, cwp->wp, params->x, params->y, curses_y,
628 curses_x, (params->highlight ? ", using standout mode" : ""));
629 wmove(cwp->wp, curses_y, curses_x);
630 if (params->highlight) {
631 code=wstandout(cwp->wp);
632 if (code)
633 return (code);
634 }
635 waddstr(cwp->wp, params->s);
636 if (params->highlight) {
637 code=wstandend(cwp->wp);
638 if (code)
639 return (code);
640 }
641
642 return (code);
643
644 } /*gator_cursesgwin_drawstring */
645
646 /*------------------------------------------------------------------------
647 * gator_cursesgwin_invert
648 *
649 * Description:
650 * Invert a region in the given curses window.
651 *
652 * Arguments:
653 * struct gwin *gwp : Ptr to the curses window in which
654 * the inverted region lies.
655 * struct gwin_invparams *params : Ptr to other params.
656 *
657 * Returns:
658 * 0 on success,
659 * Error value otherwise.
660 *
661 * Environment:
662 * Nothing interesting.
663 *
664 * Side Effects:
665 * As advertised.
666 *------------------------------------------------------------------------*/
667
668 int
669 gator_cursesgwin_invert(struct gwin *gwp, struct gwin_invparams *params)
670 { /*gator_cursesgwin_invert */
671
672 static char rn[] = "gator_cursesgwin_invert"; /*Routine name */
673
674 if (curses_debug)
675 fprintf(stderr, "[%s:%s] This routine is currently a no-op\n", mn,
676 rn);
677
678 return (0);
679
680 } /*gator_cursesgwin_invert */
681
682 /*------------------------------------------------------------------------
683 * gator_cursesgwin_getchar
684 *
685 * Description:
686 * Pick up a character from the given window.
687 *
688 * Arguments:
689 * struct gwin *gwp : Ptr to the curses window to listen to.
690 *
691 * Returns:
692 * Value of the character read,
693 * -1 otherwise.
694 *
695 * Environment:
696 * Nothing interesting.
697 *
698 * Side Effects:
699 * As advertised.
700 *------------------------------------------------------------------------*/
701
702 int
703 gator_cursesgwin_getchar(struct gwin *gwp)
704 { /*gator_cursesgwin_getchar */
705
706 return (getc(stdin));
707
708 } /*gator_cursesgwin_getchar */
709
710 /*------------------------------------------------------------------------
711 * gator_cursesgwin_wait
712 *
713 * Description:
714 * Wait until input is available.
715 *
716 * Arguments:
717 * struct gwin *gwp : Ptr to the curses window to wait on.
718 *
719 * Returns:
720 * 0 on success,
721 * Error value otherwise.
722 *
723 * Environment:
724 * Nothing interesting.
725 *
726 * Side Effects:
727 * As advertised.
728 *------------------------------------------------------------------------*/
729
730 int
731 gator_cursesgwin_wait(struct gwin *gwp)
732 { /*gator_cursesgwin_wait */
733
734 while (!LWP_WaitForKeystroke(-1));
735
736 return (0);
737
738 } /*gator_cursesgwin_wait */
739
740 /*------------------------------------------------------------------------
741 * gator_cursesgwin_getdimensions
742 *
743 * Description:
744 * Get the window's X,Y dimensions.
745 *
746 * Arguments:
747 * struct gwin *gwp : Ptr to the curses window to examine.
748 * struct gwin_sizeparams *params : Ptr to the size params to set.
749 *
750 * Returns:
751 * 0 on success,
752 * Error value otherwise.
753 *
754 * Environment:
755 * Nothing interesting.
756 *
757 * Side Effects:
758 * As advertised.
759 *------------------------------------------------------------------------*/
760
761 int
762 gator_cursesgwin_getdimensions(struct gwin *gwp, struct gwin_sizeparams *aparms)
763 { /*gator_cursesgwin_getdimensions */
764
765 struct gator_cursesgwin *cwp; /*Curses-specific data */
766
767 cwp = (struct gator_cursesgwin *)(gwp->w_data);
768 getmaxyx(cwp->wp, aparms->maxy, aparms->maxx);
769
770 return (0);
771
772 } /*gator_cursesgwin_getdimensions */