3 * Author: Marc van Kempen
4 * Desc: Implementation of UI-objects:
5 * - String input fields
9 * Copyright (c) 1995, Marc van Kempen
11 * All rights reserved.
13 * This software may be used, modified, copied, distributed, and
14 * sold, in both source and binary form provided that the above
15 * copyright and these terms are retained, verbatim, as the first
16 * lines of this file. Under no circumstances is the author
17 * responsible for the proper functioning of this software, nor does
18 * the author assume any responsibility for damages incurred with
24 #include <sys/param.h>
27 #include "dialog.priv.h"
28 #include "ui_objects.h"
32 /***********************************************************************
36 ***********************************************************************/
39 AddObj(ComposeObj
**Obj
, int objtype
, void *obj
)
41 * Desc: Add the object <obj> to the list of objects <Obj>
45 /* Create the root object */
46 *Obj
= (ComposeObj
*) malloc( sizeof(ComposeObj
) );
48 printf("AddObj: Error malloc'ing ComposeObj\n");
51 (*Obj
)->objtype
= objtype
;
58 /* create the next object */
59 while (o
->next
) o
= (ComposeObj
*) o
->next
;
60 o
->next
= (struct ComposeObj
*) malloc( sizeof(ComposeObj
) );
62 printf("AddObj: Error malloc'ing o->next\n");
65 o
->next
->objtype
= objtype
;
75 FreeObj(ComposeObj
*Obj
)
77 * Desc: free the memory occupied by *Obj
94 ReadObj(ComposeObj
*Obj
)
96 * Desc: navigate through the different objects calling their
97 * respective navigation routines as necessary
102 ComposeObj
*last
; /* the last object in the list */
103 int ret
; /* the return value from the selection routine */
105 /* find the last object in the list */
107 while (last
->next
) last
= last
->next
;
111 while ((ret
!= SEL_BUTTON
) && (ret
!= SEL_ESC
)) {
114 ret
= SelectStringObj((StringObj
*) o
->obj
);
117 ret
= SelectListObj((ListObj
*) o
->obj
);
120 ret
= SelectButtonObj((ButtonObj
*) o
->obj
);
126 case SEL_TAB
: /* move to the next object in the list */
127 if (o
->next
!= NULL
) {
128 o
= o
->next
; /* next object */
130 o
= Obj
; /* beginning of the list */
135 case SEL_BACKTAB
: /* move to the previous object in the list */
136 if (o
->prev
!= NULL
) {
137 o
= o
->prev
; /* previous object */
139 o
= last
; /* end of the list */
143 case KEY_F(1): /* display help_file */
156 PollObj(ComposeObj
**Obj
)
158 ComposeObj
*last
; /* the last object in the list */
159 ComposeObj
*first
; /* the first object in the list */
160 int ret
; /* the return value from the selection routine */
162 /* find the last object in the list */
164 while (last
->next
) last
= last
->next
;
166 /* find the first object in the list */
168 while (first
->prev
) first
= first
->prev
;
171 switch((*Obj
)->objtype
) {
173 ret
= SelectStringObj((StringObj
*) (*Obj
)->obj
);
176 ret
= SelectListObj((ListObj
*) (*Obj
)->obj
);
179 ret
= SelectButtonObj((ButtonObj
*) (*Obj
)->obj
);
185 case SEL_TAB
: /* move to the next object in the list */
186 if ((*Obj
)->next
!= NULL
) {
187 *Obj
= (*Obj
)->next
; /* next object */
189 *Obj
= first
; /* beginning of the list */
194 case SEL_BACKTAB
: /* move to the previous object in the list */
195 if ((*Obj
)->prev
!= NULL
) {
196 *Obj
= (*Obj
)->prev
; /* previous object */
198 *Obj
= last
; /* end of the list */
209 DelObj(ComposeObj
*Obj
)
211 * Desc: Free all objects
217 while (Obj
!= NULL
) {
218 switch(Obj
->objtype
) {
220 DelStringObj((StringObj
*) Obj
->obj
);
223 DelListObj((ListObj
*) Obj
->obj
);
226 DelButtonObj((ButtonObj
*) Obj
->obj
);
235 /***********************************************************************
239 ***********************************************************************/
242 outstr(WINDOW
*win
, char *str
, int attrs
)
244 if (attrs
& DITEM_NO_ECHO
) {
258 RefreshStringObj(StringObj
*so
)
260 * Desc: redraw the object
265 wmove(so
->win
, so
->y
, so
->x
+1);
266 wattrset(so
->win
, dialog_attr
);
267 waddstr(so
->win
, so
->title
);
269 draw_box(so
->win
, so
->y
+1, so
->x
, 3, so
->w
, dialog_attr
, border_attr
);
270 wattrset(so
->win
, item_attr
);
271 wmove(so
->win
, so
->y
+2, so
->x
+1);
272 if (strlen(so
->s
) > so
->w
-2) {
273 strncpy(tmp
, (char *) so
->s
+ strlen(so
->s
) - so
->w
+ 2, so
->w
- 1);
274 outstr(so
->win
, tmp
, so
->attr_mask
);
276 outstr(so
->win
, so
->s
, so
->attr_mask
);
280 } /* RefreshStringObj() */
283 NewStringObj(WINDOW
*win
, char *title
, char *s
, int y
, int x
, int w
, int len
)
285 * Desc: Initialize a new stringobj and return a pointer to it.
286 * Draw the object on the screen at the specified coordinates
291 /* Initialize a new object */
292 so
= (StringObj
*) malloc( sizeof(StringObj
) );
294 printf("NewStringObj: Error malloc'ing StringObj\n");
297 so
->title
= (char *) malloc( strlen(title
) + 1);
299 printf("NewStringObj: Error malloc'ing so->title\n");
302 strcpy(so
->title
, title
);
310 so
->attr_mask
= DialogInputAttrs
; /* Grossly use a global to avoid changing API */
312 /* Draw it on the screen */
313 RefreshStringObj(so
);
316 } /* NewStringObj() */
319 SelectStringObj(StringObj
*so
)
321 * Desc: get input using the info in <so>
328 key
= line_edit(so
->win
, so
->y
+2, so
->x
+1,
329 so
->len
, so
->w
-2, inputbox_attr
, TRUE
, tmp
, so
->attr_mask
);
330 if ((key
== '\n') || (key
== '\r') || (key
== '\t') || key
== (KEY_BTAB
) ) {
333 RefreshStringObj(so
);
340 if ( (key
== KEY_BTAB
) || (key
== KEY_F(2)) ) {
343 if ((key
== '\n') || (key
== '\r')) {
347 } /* SelectStringObj() */
351 DelStringObj(StringObj
*so
)
353 * Desc: Free the space occupied by <so>
362 /***********************************************************************
366 ***********************************************************************/
369 DrawNames(ListObj
*lo
)
371 * Desc: Just refresh the names, not the surrounding box and title
375 char tmp
[MAXPATHLEN
];
380 for (i
=lo
->scroll
; i
<lo
->n
&& i
<lo
->scroll
+h
; i
++) {
381 wmove(lo
->win
, y
+i
-lo
->scroll
, x
);
383 wattrset(lo
->win
, A_BOLD
);
385 wattrset(lo
->win
, item_attr
);
387 if (strlen(lo
->name
[i
]) > lo
->w
-2) {
388 strncpy(tmp
, lo
->name
[i
], lo
->w
-2);
390 waddstr(lo
->win
, tmp
);
392 waddstr(lo
->win
, lo
->name
[i
]);
393 for (j
=strlen(lo
->name
[i
]); j
<lo
->w
-2; j
++) waddstr(lo
->win
, " ");
396 wattrset(lo
->win
, item_attr
);
397 while (i
<lo
->scroll
+h
) {
398 wmove(lo
->win
, y
+i
-lo
->scroll
, x
);
399 for (j
=0; j
<lo
->w
-2; j
++) waddstr(lo
->win
, " ");
407 RefreshListObj(ListObj
*lo
)
409 * Desc: redraw the list object
415 wmove(lo
->win
, lo
->y
, lo
->x
+1);
416 wattrset(lo
->win
, dialog_attr
);
417 waddstr(lo
->win
, lo
->title
);
418 draw_box(lo
->win
, lo
->y
+1, lo
->x
, lo
->h
, lo
->w
, dialog_attr
, border_attr
);
423 /* Draw % indication */
424 sprintf(perc
, "(%3d%%)", MIN(100, (int) (100 * (lo
->sel
+lo
->h
-2) / MAX(1, lo
->n
))));
425 wmove(lo
->win
, lo
->y
+ lo
->h
, lo
->x
+ lo
->w
- 8);
426 wattrset(lo
->win
, dialog_attr
);
427 waddstr(lo
->win
, perc
);
431 } /* RefreshListObj() */
434 NewListObj(WINDOW
*win
, char *title
, char **list
, char *listelt
, int y
, int x
,
437 * Desc: create a listobj, draw it on the screen and return a pointer to it.
443 /* Initialize a new object */
444 lo
= (ListObj
*) malloc( sizeof(ListObj
) );
446 fprintf(stderr
, "NewListObj: Error malloc'ing ListObj\n");
449 lo
->title
= (char *) malloc( strlen(title
) + 1);
451 fprintf(stderr
, "NewListObj: Error malloc'ing lo->title\n");
454 strcpy(lo
->title
, title
);
457 lo
->seld
= (int *) malloc( n
* sizeof(int) );
459 fprintf(stderr
, "NewListObj: Error malloc'ing lo->seld\n");
462 for (i
=0; i
<n
; i
++) {
478 /* Draw the object on the screen */
485 UpdateListObj(ListObj
*lo
, char **list
, int n
)
487 * Desc: Update the list in the listobject with the provided list
488 * Pre: lo->name "has been freed"
489 * "(A i: 0<=i<lo->n: "lo->name[i] has been freed")"
498 /* Rewrite the list in the object */
501 lo
->seld
= (int *) malloc( n
* sizeof(int) );
503 fprintf(stderr
, "UpdateListObj: Error malloc'ing lo->seld\n");
506 for (i
=0; i
<n
; i
++) {
516 /* Draw the object on the screen */
520 } /* UpdateListObj() */
523 SelectListObj(ListObj
*lo
)
525 * Desc: get a listname (or listnames), TAB to move on, or ESC ESC to exit
529 int key
, sel_x
, sel_y
, quit
;
530 char tmp
[MAXPATHLEN
];
534 sel_y
= lo
->y
+ 2 + lo
->sel
- lo
->scroll
;
536 if (lo
->n
== 0) return(SEL_TAB
);
538 keypad(lo
->win
, TRUE
);
540 /* Draw current selection in inverse video */
541 wmove(lo
->win
, sel_y
, sel_x
);
542 wattrset(lo
->win
, item_selected_attr
);
543 waddstr(lo
->win
, lo
->name
[lo
->sel
]);
545 key
= wgetch(lo
->win
);
547 while ((key
!= '\t') && (key
!= '\n') && (key
!= '\r')
548 && (key
!= ESC
) && (key
!= KEY_F(1)) && (key
!= '?') && !quit
) {
549 /* first draw current item in normal video */
550 wmove(lo
->win
, sel_y
, sel_x
);
551 if (lo
->seld
[lo
->sel
]) {
552 wattrset(lo
->win
, A_BOLD
);
554 wattrset(lo
->win
, item_attr
);
556 if (strlen(lo
->name
[lo
->sel
]) > lo
->w
- 2) {
557 strncpy(tmp
, lo
->name
[lo
->sel
], lo
->w
- 2);
559 waddstr(lo
->win
, tmp
);
561 waddstr(lo
->win
, lo
->name
[lo
->sel
]);
567 if (sel_y
< lo
->y
+ lo
->h
-1) {
568 if (lo
->sel
< lo
->n
-1) {
573 if (lo
->sel
< lo
->n
-1) {
583 if (sel_y
> lo
->y
+2) {
607 if (lo
->n
< lo
->h
- 3) {
610 sel_y
= lo
->y
+ 2 + lo
->sel
- lo
->scroll
;
612 /* more than one page of list */
614 lo
->scroll
= lo
->n
-1 - (lo
->h
-3);
615 sel_y
= lo
->y
+ 2 + lo
->sel
- lo
->scroll
;
622 lo
->sel
+= lo
->h
- 2;
623 if (lo
->sel
>= lo
->n
) lo
->sel
= lo
->n
- 1;
624 lo
->scroll
+= lo
->h
- 2;
625 if (lo
->scroll
>= lo
->n
- 1) lo
->scroll
= lo
->n
- 1;
626 if (lo
->scroll
< 0) lo
->scroll
= 0;
627 sel_y
= lo
->y
+ 2 + lo
->sel
- lo
->scroll
;
633 lo
->sel
-= lo
->h
- 2;
634 if (lo
->sel
< 0) lo
->sel
= 0;
635 lo
->scroll
-= lo
->h
- 2;
636 if (lo
->scroll
< 0) lo
->scroll
= 0;
637 sel_y
= lo
->y
+ 2 + lo
->sel
- lo
->scroll
;
645 /* Draw % indication */
646 sprintf(perc
, "(%3d%%)", MIN(100, (int)
647 (100 * (lo
->sel
+lo
->h
- 2) / MAX(1, lo
->n
))));
648 wmove(lo
->win
, lo
->y
+ lo
->h
, lo
->x
+ lo
->w
- 8);
649 wattrset(lo
->win
, dialog_attr
);
650 waddstr(lo
->win
, perc
);
652 /* draw current item in inverse */
653 wmove(lo
->win
, sel_y
, sel_x
);
654 wattrset(lo
->win
, item_selected_attr
);
655 if (strlen(lo
->name
[lo
->sel
]) > lo
->w
- 2) {
656 /* when printing in inverse video show the last characters in the */
657 /* name that will fit in the window */
659 lo
->name
[lo
->sel
] + strlen(lo
->name
[lo
->sel
]) - (lo
->w
- 2),
662 waddstr(lo
->win
, tmp
);
664 waddstr(lo
->win
, lo
->name
[lo
->sel
]);
666 if (!quit
) key
= wgetch(lo
->win
);
675 if ((key
== KEY_BTAB
) || (key
== ctrl('b'))) {
678 if ((key
== '\n') || (key
== '\r')) {
679 strcpy(lo
->elt
, lo
->name
[lo
->sel
]);
683 } /* SelectListObj() */
686 DelListObj(ListObj
*lo
)
688 * Desc: Free the space occupied by the listobject
692 if (lo
->seld
!= NULL
) free(lo
->seld
);
699 MarkCurrentListObj(ListObj
*lo
)
701 * Desc: mark the current item for the selection list
704 lo
->seld
[lo
->sel
] = !(lo
->seld
[lo
->sel
]);
708 } /* MarkCurrentListObj() */
711 MarkAllListObj(ListObj
*lo
)
713 * Desc: mark all items
718 for (i
=0; i
<lo
->n
; i
++) {
724 } /* MarkAllListObj() */
727 UnMarkAllListObj(ListObj
*lo
)
729 * Desc: unmark all items
734 for (i
=0; i
<lo
->n
; i
++) {
740 } /* UnMarkAllListObj() */
743 /***********************************************************************
747 ***********************************************************************/
751 RefreshButtonObj(ButtonObj
*bo
)
753 * Desc: redraw the button
756 draw_box(bo
->win
, bo
->y
, bo
->x
, 3, bo
->w
, dialog_attr
, border_attr
);
757 print_button(bo
->win
, bo
->title
, bo
->y
+1, bo
->x
+2, FALSE
);
760 } /* RefreshButtonObj() */
763 NewButtonObj(WINDOW
*win
, char *title
, int *pushed
, int y
, int x
)
765 * Desc: Create a new button object
770 bo
= (ButtonObj
*) malloc( sizeof(ButtonObj
) );
773 bo
->title
= (char *) malloc( strlen(title
) + 1);
774 strcpy(bo
->title
, title
);
777 bo
->w
= strlen(title
) + 6;
781 RefreshButtonObj(bo
);
784 } /* NewButtonObj() */
787 SelectButtonObj(ButtonObj
*bo
)
789 * Desc: Wait for buttonpresses or TAB's to move on, or ESC ESC
794 print_button(bo
->win
, bo
->title
, bo
->y
+1, bo
->x
+2, TRUE
);
795 wmove(bo
->win
, bo
->y
+1, bo
->x
+(bo
->w
/2)-1);
796 key
= wgetch(bo
->win
);
797 print_button(bo
->win
, bo
->title
, bo
->y
+1, bo
->x
+2, FALSE
);
807 *(bo
->pushed
) = TRUE
;
817 } /* SelectButtonObj() */
820 DelButtonObj(ButtonObj
*bo
)
822 * Desc: Free the space occupied by <bo>
829 } /* DelButtonObj() */