1 /* Widgets for the Midnight Commander
3 Copyright (C) 1994, 1995, 1996 the Free Software Foundation
5 Authors: 1994, 1995 Radek Doulik
6 1994, 1995 Miguel de Icaza
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include <sys/types.h>
43 #include "key.h" /* XCTRL and ALT macros */
44 #include "profile.h" /* for history loading and saving */
46 #define x_create_button(a,b,c) 1
47 #define x_create_radio(a,b,c) 1
48 #define x_create_check(a,b,c) 1
49 #define x_create_label(a,b,c) 1
50 #define x_create_input(a,b,c) 1
51 #define x_create_listbox(a,b,c) 1
52 #define x_create_buttonbar(a,b,c) 1
53 #define x_create_gauge(a,b,c) 1
54 #define x_listbox_select_nth(a,b)
55 #define x_list_insert(a,b,c)
56 #define x_redefine_label(a,b)
58 #define x_destroy_cmd(w)
59 #define x_radio_focus_item(r)
60 #define x_radio_toggle(r)
62 static int button_event (Gpm_Event
*event
, WButton
*b
);
67 button_callback (Dlg_head
*h
, WButton
*b
, int Msg
, int Par
)
75 return x_create_button (h
, h
->wdata
, b
);
78 if (b
->hotkey
== Par
|| toupper(b
->hotkey
) == Par
){
79 button_callback (h
, b
, WIDGET_KEY
, ' '); /* to make action */
85 if (Par
!= ' ' && Par
!= '\n')
89 stop
= (*b
->callback
)(b
->action
, b
->callback_data
);
90 if (!b
->callback
|| stop
){
91 h
->ret_value
= b
->action
;
112 widget_move (&b
->widget
, 0, b
->hotpos
+ off
);
118 if (Msg
==WIDGET_UNFOCUS
)
120 else if (Msg
==WIDGET_FOCUS
)
125 g_snprintf (buf
, sizeof(buf
), "[< %s >]", b
->text
);
129 g_snprintf (buf
, sizeof(buf
), "[ %s ]", b
->text
);
133 g_snprintf (buf
, sizeof(buf
), "[%s]", b
->text
);
143 attrset ((b
->selected
) ? FOCUSC
: NORMALC
);
144 widget_move (&b
->widget
, 0, 0);
149 attrset ((b
->selected
) ? HOT_FOCUSC
: HOT_NORMALC
);
150 widget_move (&b
->widget
, 0, b
->hotpos
+off
);
151 addch ((unsigned char)b
->text
[b
->hotpos
]);
153 if (Msg
== WIDGET_FOCUS
)
159 return default_proc (h
, Msg
, Par
);
163 button_event (Gpm_Event
*event
, WButton
*b
)
165 if (event
->type
& (GPM_DOWN
|GPM_UP
)){
166 Dlg_head
*h
=b
->widget
.parent
;
167 dlg_select_widget (h
, b
);
168 if (event
->type
& GPM_UP
){
169 button_callback (h
, b
, WIDGET_KEY
, ' ');
170 (*h
->callback
) (h
, ' ', DLG_POST_KEY
);
178 button_destroy (WButton
*b
)
185 button_len (const char *text
, unsigned int flags
)
187 int ret
= strlen (text
);
206 * Assuming that button text is malloc'ed, we may safely change it
207 * (as opposed to statically allocated); from other hand, excluding &
208 * and shifting data past it to the left results to one unused byte.
209 * This does not harm though :)
212 button_scan_hotkey(WButton
* b
)
214 char* cp
= strchr (b
->text
, '&');
216 if (cp
!= NULL
&& cp
[1] != '\0'){
218 b
->hotkey
= tolower (*cp
);
219 b
->hotpos
= cp
- b
->text
;
224 button_new (int y
, int x
, int action
, int flags
, char *text
,
225 int (*callback
)(int, void *), void *callback_data
, char *tkname
)
227 WButton
*b
= g_new (WButton
, 1);
229 init_widget (&b
->widget
, y
, x
, 1, button_len (text
, flags
),
230 (callback_fn
) button_callback
,
231 (destroy_fn
) button_destroy
, (mouse_h
)button_event
, tkname
);
236 b
->text
= g_strdup (text
);
237 b
->callback
= callback
;
238 b
->callback_data
= callback_data
;
239 widget_want_hotkey (b
->widget
, 1);
243 button_scan_hotkey(b
);
248 button_set_text (WButton
*b
, char *text
)
251 b
->text
= g_strdup (text
);
252 b
->widget
.cols
= button_len (text
, b
->flags
);
253 button_scan_hotkey(b
);
254 dlg_redraw (b
->widget
.parent
);
258 /* Radio button widget */
259 static int radio_event (Gpm_Event
*event
, WRadio
*r
);
262 radio_callback (Dlg_head
*h
, WRadio
*r
, int Msg
, int Par
)
268 return x_create_radio (h
, h
->wdata
, r
);
272 int i
, lp
= tolower(Par
);
275 for (i
= 0; i
< r
->count
; i
++){
276 cp
= strchr (r
->texts
[i
], '&');
277 if (cp
!= NULL
&& cp
[1] != '\0'){
278 int c
= tolower (cp
[1]);
283 radio_callback (h
, r
, WIDGET_KEY
, ' '); /* Take action */
294 (*h
->callback
) (h
, h
->current
->dlg_id
, DLG_ACTION
);
295 radio_callback (h
, r
, WIDGET_FOCUS
, ' ');
303 x_radio_focus_item (r
);
310 if (r
->count
- 1 > r
->pos
) {
312 x_radio_focus_item (r
);
319 (*h
->callback
) (h
, h
->current
->dlg_id
, DLG_ACTION
);
320 radio_callback (h
, r
, WIDGET_FOCUS
, ' ');
321 widget_move (&r
->widget
, r
->pos
, 1);
327 for (i
= 0; i
< r
->count
; i
++){
328 register unsigned char* cp
;
329 attrset ((i
==r
->pos
&& Msg
==WIDGET_FOCUS
) ? FOCUSC
:NORMALC
);
330 widget_move (&r
->widget
, i
, 0);
332 printw("(%c) ", (r
->sel
== i
) ? '*' : ' ');
333 for (cp
= r
->texts
[i
]; *cp
; cp
++)
337 attrset ((i
==r
->pos
&& Msg
==WIDGET_FOCUS
)
338 ? HOT_FOCUSC
: HOT_NORMALC
);
340 attrset ((i
==r
->pos
&& Msg
==WIDGET_FOCUS
) ? FOCUSC
: NORMALC
);
349 return default_proc (h
, Msg
, Par
);
353 radio_event (Gpm_Event
*event
, WRadio
*r
)
355 if (event
->type
& (GPM_DOWN
|GPM_UP
)){
356 Dlg_head
*h
= r
->widget
.parent
;
358 r
->pos
= event
->y
- 1;
359 dlg_select_widget (h
, r
);
360 if (event
->type
& GPM_UP
){
361 radio_callback (h
, r
, WIDGET_KEY
, ' ');
362 radio_callback (h
, r
, WIDGET_FOCUS
, 0);
363 (*h
->callback
) (h
, ' ', DLG_POST_KEY
);
371 radio_new (int y
, int x
, int count
, char **texts
, int use_hotkey
, char *tkname
)
373 WRadio
*r
= g_new (WRadio
, 1);
376 /* Compute the longest string */
378 for (i
= 0; i
< count
; i
++){
379 m
= strlen (texts
[i
]);
384 init_widget (&r
->widget
, y
, x
, count
, max
, (callback_fn
) radio_callback
,
385 0, (mouse_h
) radio_event
, tkname
);
391 r
->upper_letter_is_hotkey
= use_hotkey
;
392 widget_want_hotkey (r
->widget
, 1);
398 /* Checkbutton widget */
400 static int check_event (Gpm_Event
*event
, WCheck
*b
);
403 check_callback (Dlg_head
*h
, WCheck
*c
, int Msg
, int Par
)
407 return x_create_check (h
, h
->wdata
, c
);
410 if (c
->hotkey
==Par
||
411 (c
->hotkey
>='a' && c
->hotkey
<='z' && c
->hotkey
-32==Par
)){
412 check_callback (h
, c
, WIDGET_KEY
, ' '); /* make action */
421 c
->state
^= C_CHANGE
;
422 (*h
->callback
) (h
, h
->current
->dlg_id
, DLG_ACTION
);
423 check_callback (h
, c
, WIDGET_FOCUS
, ' ');
427 widget_move (&c
->widget
, 0, 1);
433 attrset ((Msg
== WIDGET_FOCUS
) ? FOCUSC
: NORMALC
);
434 widget_move (&c
->widget
, 0, 0);
435 printw ("[%c] %s", (c
->state
& C_BOOL
) ? 'x' : ' ', c
->text
);
438 attrset ((Msg
== WIDGET_FOCUS
) ? HOT_FOCUSC
: HOT_NORMALC
);
439 widget_move (&c
->widget
, 0, + c
->hotpos
+4);
440 addch ((unsigned char)c
->text
[c
->hotpos
]);
444 return default_proc (h
, Msg
, Par
);
448 check_event (Gpm_Event
*event
, WCheck
*c
)
450 if (event
->type
& (GPM_DOWN
|GPM_UP
)){
451 Dlg_head
*h
= c
->widget
.parent
;
453 dlg_select_widget (h
, c
);
454 if (event
->type
& GPM_UP
){
455 check_callback (h
, c
, WIDGET_KEY
, ' ');
456 check_callback (h
, c
, WIDGET_FOCUS
, 0);
457 (*h
->callback
) (h
, ' ', DLG_POST_KEY
);
465 check_destroy (WCheck
*c
)
472 check_new (int y
, int x
, int state
, char *text
, char *tkname
)
474 WCheck
*c
= g_new (WCheck
, 1);
477 init_widget (&c
->widget
, y
, x
, 1, strlen (text
),
478 (callback_fn
)check_callback
,
479 (destroy_fn
)check_destroy
, (mouse_h
) check_event
, tkname
);
480 c
->state
= state
? C_BOOL
: 0;
481 c
->text
= g_strdup (text
);
484 widget_want_hotkey (c
->widget
, 1);
486 /* Scan for the hotkey */
487 for (s
= text
, t
= c
->text
; *s
; s
++, t
++){
494 c
->hotkey
= tolower (*s
);
495 c
->hotpos
= t
- c
->text
;
507 label_callback (Dlg_head
*h
, WLabel
*l
, int Msg
, int Par
)
509 if (Msg
== WIDGET_INIT
)
510 return x_create_label (h
, h
->wdata
, l
);
512 /* We don't want to get the focus */
513 if (Msg
== WIDGET_FOCUS
)
515 if (Msg
== WIDGET_DRAW
&& l
->text
){
516 char *p
= l
->text
, *q
, c
= 0;
519 attrset (DEFAULT_COLOR
);
525 q
= strchr (p
, '\n');
530 widget_move (&l
->widget
, y
, 0);
532 xlen
= l
->widget
.cols
- strlen (p
);
534 printw ("%*s", xlen
, " ");
543 return default_proc (h
, Msg
, Par
);
547 label_set_text (WLabel
*label
, char *text
)
549 int newcols
= label
->widget
.cols
;
551 if (label
->text
&& text
&& !strcmp (label
->text
, text
))
552 return; /* Flickering is not nice */
555 g_free (label
->text
);
558 label
->text
= g_strdup (text
);
559 if (label
->auto_adjust_cols
) {
560 newcols
= strlen (text
);
561 if (newcols
> label
->widget
.cols
)
562 label
->widget
.cols
= newcols
;
567 if (label
->widget
.parent
)
568 label_callback (label
->widget
.parent
, label
, WIDGET_DRAW
, 0);
570 if (newcols
< label
->widget
.cols
)
571 label
->widget
.cols
= newcols
;
575 label_destroy (WLabel
*l
)
583 label_new (int y
, int x
, const char *text
, char *tkname
)
588 /* Multiline labels are immutable - no need to compute their sizes */
589 if (!text
|| strchr(text
, '\n'))
592 width
= strlen (text
);
594 l
= g_new (WLabel
, 1);
595 init_widget (&l
->widget
, y
, x
, 1, width
,
596 (callback_fn
) label_callback
,
597 (destroy_fn
) label_destroy
, NULL
, tkname
);
598 l
->text
= text
? g_strdup (text
) : 0;
599 l
->auto_adjust_cols
= 1;
601 widget_want_cursor (l
->widget
, 0);
606 /* Gauge widget (progress indicator) */
607 /* Currently width is hardcoded here for text mode */
611 gauge_callback (Dlg_head
*h
, WGauge
*g
, int Msg
, int Par
)
614 if (Msg
== WIDGET_INIT
)
615 return x_create_gauge (h
, h
->wdata
, g
);
617 /* We don't want to get the focus */
618 if (Msg
== WIDGET_FOCUS
)
621 if (Msg
== WIDGET_DRAW
){
622 widget_move (&g
->widget
, 0, 0);
625 printw ("%*s", gauge_len
, "");
627 long percentage
, columns
;
628 long total
= g
->max
, done
= g
->current
;
630 if (total
<= 0 || done
< 0) {
636 while (total
> 65535) {
640 percentage
= (200 * done
/ total
+ 1) / 2;
641 columns
= (2 * (gauge_len
- 7) * done
/ total
+ 1) / 2;
643 attrset (GAUGE_COLOR
);
644 printw ("%*s", columns
, "");
646 printw ("%*s] %3d%%", gauge_len
- 7 - columns
, "", percentage
);
650 return default_proc (h
, Msg
, Par
);
654 gauge_set_value (WGauge
*g
, int max
, int current
)
656 if (g
->current
== current
&& g
->max
== max
)
657 return; /* Do not flicker */
659 max
= 1; /* I do not like division by zero :) */
661 g
->current
= current
;
663 gauge_callback (g
->widget
.parent
, g
, WIDGET_DRAW
, 0);
667 gauge_show (WGauge
*g
, int shown
)
669 if (g
->shown
== shown
)
672 gauge_callback (g
->widget
.parent
, g
, WIDGET_DRAW
, 0);
676 gauge_destroy (WGauge
*g
)
682 gauge_new (int y
, int x
, int shown
, int max
, int current
, char *tkname
)
684 WGauge
*g
= g_new (WGauge
, 1);
686 init_widget (&g
->widget
, y
, x
, 1, gauge_len
,
687 (callback_fn
) gauge_callback
,
688 (destroy_fn
) gauge_destroy
, NULL
, tkname
);
691 max
= 1; /* I do not like division by zero :) */
693 g
->current
= current
;
695 widget_want_cursor (g
->widget
, 0);
702 /* {{{ history button */
704 #define LARGE_HISTORY_BUTTON 1
706 #ifdef LARGE_HISTORY_BUTTON
707 # define HISTORY_BUTTON_WIDTH 3
709 # define HISTORY_BUTTON_WIDTH 1
712 #define should_show_history_button(in) \
713 (in->history && in->field_len > HISTORY_BUTTON_WIDTH * 2 + 1 && in->widget.parent)
715 static void draw_history_button (WInput
* in
)
718 c
= in
->history
->next
? (in
->history
->prev
? '|' : 'v') : '^';
719 widget_move (&in
->widget
, 0, in
->field_len
- HISTORY_BUTTON_WIDTH
);
720 #ifdef LARGE_HISTORY_BUTTON
723 h
= in
->widget
.parent
;
725 attrset (NORMALC
); /* button has the same colour as other buttons */
727 attrset (HOT_NORMALC
);
729 attrset (NORMAL_COLOR
);
731 /* Too distracting: attrset (MARKED_COLOR); */
733 widget_move (&in
->widget
, 0, in
->field_len
- HISTORY_BUTTON_WIDTH
+ 1);
737 attrset (MARKED_COLOR
);
742 /* }}} history button */
745 /* Input widgets now have a global kill ring */
746 /* Pointer to killed data */
747 static char *kill_buffer
= 0;
750 update_input (WInput
*in
, int clear_first
)
755 int buf_len
= strlen (in
->buffer
);
757 if (should_show_history_button (in
))
758 has_history
= HISTORY_BUTTON_WIDTH
;
760 if (in
->disable_update
)
763 /* Make the point visible */
764 if ((in
->point
< in
->first_shown
) ||
765 (in
->point
>= in
->first_shown
+in
->field_len
- has_history
)){
766 in
->first_shown
= in
->point
- (in
->field_len
/ 3);
767 if (in
->first_shown
< 0)
771 /* Adjust the mark */
772 if (in
->mark
> buf_len
)
776 draw_history_button (in
);
780 widget_move (&in
->widget
, 0, 0);
781 for (i
= 0; i
< in
->field_len
- has_history
; i
++)
783 widget_move (&in
->widget
, 0, 0);
785 for (i
= 0, j
= in
->first_shown
; i
< in
->field_len
- has_history
&& in
->buffer
[j
]; i
++){
786 c
= in
->buffer
[j
++];
787 c
= is_printable (c
) ? c
: '.';
792 widget_move (&in
->widget
, 0, in
->point
- in
->first_shown
);
799 winput_set_origin (WInput
*in
, int x
, int field_len
)
802 in
->field_len
= in
->widget
.cols
= field_len
;
803 update_input (in
, 0);
806 /* {{{ history saving and loading */
809 This loads and saves the history of an input line to and from the
810 widget. It is called with the widgets tk name on creation of the
811 widget, and returns the Hist list. It stores histories in the file
812 ~/.mc/history in using the profile code.
814 If def_text is passed as INPUT_LAST_TEXT (to the input_new()
815 function) then input_new assigns the default text to be the last text
816 entered, or "" if not found.
819 int num_history_items_recorded
= 60;
821 Hist
*history_get (char *input_name
)
829 if (!num_history_items_recorded
) /* this is how to disable */
835 profile
= concat_dir_and_file (home_dir
, HISTORY_FILE_NAME
);
837 char key_name
[BUF_TINY
];
838 char this_entry
[BUF_LARGE
];
839 g_snprintf (key_name
, sizeof (key_name
), "%d", i
);
840 GetPrivateProfileString (input_name
, key_name
, "", this_entry
, sizeof (this_entry
), profile
);
843 new = g_new0 (Hist
, 1);
844 new->text
= g_strdup (this_entry
);
845 new->prev
= old
; /* set up list pointers */
851 return new; /* return pointer to last entry in list */
854 void history_put (char *input_name
, Hist
*h
)
868 if (!num_history_items_recorded
) /* this is how to disable */
871 profile
= concat_dir_and_file (home_dir
, HISTORY_FILE_NAME
);
873 if ((i
= open (profile
, O_CREAT
| O_EXCL
, S_IRUSR
| S_IWUSR
)) != -1)
875 /* Just in case I forgot to strip passwords somewhere -- Norbert */
876 if (chmod (profile
, S_IRUSR
| S_IWUSR
) == -1 && errno
!= ENOENT
){
881 while (h
->next
) /* go to end of list */
884 /* go back 60 places */
885 for (i
= 0; i
< num_history_items_recorded
- 1 && h
->prev
; i
++)
889 profile_clean_section (input_name
, profile
);
891 /* dump histories into profile */
892 for (i
= 0; h
; h
= h
->next
){
895 /* probably aren't any null entries, but lets be sure */
897 char key_name
[BUF_TINY
];
898 g_snprintf (key_name
, sizeof(key_name
), "%d", i
++);
899 WritePrivateProfileString (input_name
, key_name
, h
->text
, profile
);
906 /* }}} history saving and loading */
909 /* {{{ history display */
914 static char *history_title
= NULL
;
916 if (history_title
== NULL
)
917 history_title
= _(" History ");
918 return history_title
;
922 history_callback (Dlg_head
* h
, int Par
, int Msg
)
926 attrset (COLOR_NORMAL
);
928 draw_box (h
, 0, 0, h
->lines
, h
->cols
);
929 attrset (COLOR_HOT_NORMAL
);
930 dlg_move (h
, 0, (h
->cols
- strlen (i18n_htitle())) / 2);
931 printw (i18n_htitle());
937 static inline int listbox_fwd (WListbox
*l
);
939 char *show_hist (Hist
*history
, int widget_x
, int widget_y
)
942 size_t maxlen
= strlen (i18n_htitle()), i
, count
= 0;
946 WListbox
*query_list
;
952 while (z
->prev
) /* goto first */
956 if ((i
= strlen (hi
->text
)) > maxlen
)
964 if (h
<= y
|| y
> LINES
- 6)
972 h
= min(h
, LINES
- y
);
979 if ((w
= maxlen
+ 4) + x
> COLS
)
985 query_dlg
= create_dlg (y
, x
, h
, w
, dialog_colors
, history_callback
,
986 "[History-query]", "history", DLG_NONE
);
987 query_list
= listbox_new (1, 1, w
- 2, h
- 2, listbox_finish
, 0, NULL
);
988 add_widget (query_dlg
, query_list
);
991 while (hi
) { /* traverse */
992 listbox_add_item (query_list
, 0, 0, hi
->text
, NULL
);
995 while (listbox_fwd (query_list
));
999 while (hi
) { /* traverse backwards */
1000 listbox_add_item (query_list
, 0, 0, hi
->text
, NULL
);
1004 run_dlg (query_dlg
);
1006 if (query_dlg
->ret_value
!= B_CANCEL
) {
1007 listbox_get_current (query_list
, &q
, NULL
);
1011 destroy_dlg (query_dlg
);
1015 static void do_show_hist (WInput
* in
)
1018 r
= show_hist (in
->history
, in
->widget
.x
, in
->widget
.y
);
1020 assign_text (in
, r
);
1025 /* }}} history display */
1028 input_destroy (WInput
*in
)
1031 fprintf (stderr
, "Internal error: null Input *\n");
1037 Hist
*current
, *old
;
1039 if (!in
->is_password
) /* don't save passwords ;-) */
1040 history_put (in
->history_name
, in
->history
);
1042 current
= in
->history
;
1043 while (current
->next
)
1044 current
= current
->next
;
1047 current
= current
->prev
;
1053 g_free (in
->buffer
);
1054 free_completions (in
);
1055 if (in
->history_name
)
1056 g_free (in
->history_name
);
1059 static char disable_update
= 0;
1062 input_disable_update (WInput
*in
)
1064 in
->disable_update
++;
1068 input_enable_update (WInput
*in
)
1070 in
->disable_update
--;
1071 update_input (in
, 0);
1074 #define ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
1077 push_history (WInput
*in
, char *text
)
1080 /* input widget where urls with passwords are entered without any
1082 static const char *password_input_fields
[] = {
1083 N_(" Link to a remote machine "),
1084 N_(" FTP to machine "),
1085 N_(" SMB link to machine ")
1093 for (i
= 0; i
< ELEMENTS(password_input_fields
); i
++)
1094 password_input_fields
[i
] = _(password_input_fields
[i
]);
1097 for (p
= text
; *p
== ' ' || *p
== '\t'; p
++);
1101 while (in
->history
->next
)
1102 in
->history
= in
->history
->next
;
1103 if (!strcmp (in
->history
->text
, text
))
1105 new = g_new (Hist
, 1);
1106 in
->history
->next
= new;
1108 new = g_new (Hist
, 1);
1111 new->prev
= in
->history
;
1112 new->text
= g_strdup (text
);
1113 if (in
->history_name
) {
1114 p
= in
->history_name
+ 3;
1115 for (i
= 0; i
< ELEMENTS(password_input_fields
); i
++)
1116 if (strcmp (p
, password_input_fields
[i
]) == 0)
1118 if (i
< ELEMENTS(password_input_fields
))
1119 strip_password (new->text
, 0);
1121 strip_password (new->text
, 1);
1130 /* Cleans the input line and adds the current text to the history */
1132 new_input (WInput
*in
)
1135 push_history (in
, in
->buffer
);
1140 free_completions (in
);
1141 update_input (in
, 0);
1145 insert_char (WInput
*in
, int c_code
)
1153 if (strlen (in
->buffer
)+1 == in
->current_max_len
){
1154 /* Expand the buffer */
1155 char *narea
= g_malloc (in
->current_max_len
+ in
->field_len
);
1157 char *p
= in
->buffer
;
1159 strcpy (narea
, in
->buffer
);
1161 in
->current_max_len
+= in
->field_len
;
1165 if (strlen (in
->buffer
)+1 < in
->current_max_len
){
1166 int l
= strlen (&in
->buffer
[in
->point
]);
1167 for (i
= l
+1; i
> 0; i
--)
1168 in
->buffer
[in
->point
+i
] = in
->buffer
[in
->point
+i
-1];
1169 in
->buffer
[in
->point
] = c_code
;
1176 beginning_of_line (WInput
*in
)
1182 end_of_line (WInput
*in
)
1184 in
->point
= strlen (in
->buffer
);
1188 backward_char (WInput
*in
)
1195 forward_char (WInput
*in
)
1197 if (in
->buffer
[in
->point
])
1202 forward_word (WInput
*in
)
1204 unsigned char *p
= in
->buffer
+in
->point
;
1206 while (*p
&& (isspace (*p
) || ispunct (*p
)))
1208 while (*p
&& isalnum (*p
))
1210 in
->point
= p
- in
->buffer
;
1214 backward_word (WInput
*in
)
1216 unsigned char *p
= in
->buffer
+in
->point
;
1218 while (p
-1 > in
->buffer
-1 && (isspace (*(p
-1)) || ispunct (*(p
-1))))
1220 while (p
-1 > in
->buffer
-1 && isalnum (*(p
-1)))
1222 in
->point
= p
- in
->buffer
;
1226 key_left (WInput
*in
)
1228 if (ctrl_pressed ())
1235 key_right (WInput
*in
)
1237 if (ctrl_pressed ())
1244 backward_delete (WInput
*in
)
1250 for (i
= in
->point
; in
->buffer
[i
-1]; i
++)
1251 in
->buffer
[i
-1] = in
->buffer
[i
];
1257 delete_char (WInput
*in
)
1261 for (i
= in
->point
; in
->buffer
[i
]; i
++)
1262 in
->buffer
[i
] = in
->buffer
[i
+1];
1267 copy_region (WInput
*in
, int x_first
, int x_last
)
1269 int first
= min (x_first
, x_last
);
1270 int last
= max (x_first
, x_last
);
1276 g_free (kill_buffer
);
1278 kill_buffer
= g_malloc (last
-first
+ 1);
1279 strncpy (kill_buffer
, in
->buffer
+first
, last
-first
);
1280 kill_buffer
[last
-first
] = 0;
1284 delete_region (WInput
*in
, int x_first
, int x_last
)
1286 int first
= min (x_first
, x_last
);
1287 int last
= max (x_first
, x_last
);
1291 strcpy (&in
->buffer
[first
], &in
->buffer
[last
]);
1296 kill_word (WInput
*in
)
1298 int old_point
= in
->point
;
1302 new_point
= in
->point
;
1303 in
->point
= old_point
;
1305 copy_region (in
, old_point
, new_point
);
1306 delete_region (in
, old_point
, new_point
);
1311 back_kill_word (WInput
*in
)
1313 int old_point
= in
->point
;
1317 new_point
= in
->point
;
1318 in
->point
= old_point
;
1320 copy_region (in
, old_point
, new_point
);
1321 delete_region (in
, old_point
, new_point
);
1326 set_mark (WInput
*in
)
1328 in
->mark
= in
->point
;
1332 kill_save (WInput
*in
)
1334 copy_region (in
, in
->mark
, in
->point
);
1338 kill_region (WInput
*in
)
1341 delete_region (in
, in
->point
, in
->mark
);
1351 for (p
= kill_buffer
; *p
; p
++)
1352 insert_char (in
, *p
);
1356 kill_line (WInput
*in
)
1359 g_free (kill_buffer
);
1360 kill_buffer
= g_strdup (&in
->buffer
[in
->point
]);
1361 in
->buffer
[in
->point
] = 0;
1365 assign_text (WInput
*in
, char *text
)
1367 free_completions (in
);
1368 g_free (in
->buffer
);
1369 in
->buffer
= g_strdup (text
); /* was in->buffer->text */
1370 in
->current_max_len
= strlen (in
->buffer
) + 1;
1371 in
->point
= strlen (in
->buffer
);
1377 hist_prev (WInput
*in
)
1382 if (in
->need_push
) {
1383 switch (push_history (in
, in
->buffer
)) {
1384 case 2: in
->history
= in
->history
->prev
; break;
1385 case 1: if (in
->history
->prev
) in
->history
= in
->history
->prev
; break;
1388 } else if (in
->history
->prev
)
1389 in
->history
= in
->history
->prev
;
1392 assign_text (in
, in
->history
->text
);
1397 hist_next (WInput
*in
)
1399 if (in
->need_push
) {
1400 switch (push_history (in
, in
->buffer
)) {
1402 assign_text (in
, "");
1412 if (!in
->history
->next
) {
1413 assign_text (in
, "");
1417 in
->history
= in
->history
->next
;
1418 assign_text (in
, in
->history
->text
);
1422 static const struct {
1424 void (*fn
)(WInput
*in
);
1427 { XCTRL('a'), beginning_of_line
},
1428 { KEY_HOME
, beginning_of_line
},
1429 { KEY_A1
, beginning_of_line
},
1430 { XCTRL('e'), end_of_line
},
1431 { KEY_END
, end_of_line
},
1432 { KEY_C1
, end_of_line
},
1433 { KEY_LEFT
, key_left
},
1434 { XCTRL('b'), backward_char
},
1435 { ALT('b'), backward_word
},
1436 { KEY_RIGHT
, key_right
},
1437 { XCTRL('f'), forward_char
},
1438 { ALT('f'), forward_word
},
1441 { 0177, backward_delete
},
1442 { KEY_BACKSPACE
, backward_delete
},
1443 { XCTRL('h'), backward_delete
},
1444 { KEY_DC
, delete_char
},
1445 { XCTRL('d'), delete_char
},
1446 { ALT('d'), kill_word
},
1447 { ALT(KEY_BACKSPACE
), back_kill_word
},
1448 { ALT(XCTRL('h')), back_kill_word
},
1449 { ALT(127), back_kill_word
},
1451 /* Region manipulation */
1453 { XCTRL('w'), kill_region
},
1454 { ALT('w'), kill_save
},
1455 { XCTRL('y'), yank
},
1456 { XCTRL('k'), kill_line
},
1459 { ALT('p'), hist_prev
},
1460 { ALT('n'), hist_next
},
1461 { ALT('h'), do_show_hist
},
1464 { ALT('\t'), complete
},
1469 /* This function is a test for a special input key used in complete.c */
1470 /* Returns 0 if it is not a special key, 1 if it is a non-complete key
1471 and 2 if it is a complete key */
1473 is_in_input_map (WInput
*in
, int c_code
)
1477 for (i
= 0; input_map
[i
].fn
; i
++)
1478 if (c_code
== input_map
[i
].key_code
) {
1479 if (input_map
[i
].fn
== complete
)
1488 port_region_marked_for_delete (WInput
*in
)
1496 handle_char (WInput
*in
, int c_code
)
1504 free_completions (in
);
1505 v
= insert_char (in
, c_code
);
1506 update_input (in
, 1);
1511 for (i
= 0; input_map
[i
].fn
; i
++){
1512 if (c_code
== input_map
[i
].key_code
){
1513 if (input_map
[i
].fn
!= complete
)
1514 free_completions (in
);
1515 (*input_map
[i
].fn
)(in
);
1520 if (!input_map
[i
].fn
){
1521 if (c_code
> 255 || !is_printable (c_code
))
1524 port_region_marked_for_delete (in
);
1526 free_completions (in
);
1527 v
= insert_char (in
, c_code
);
1528 in
->inserted_one
= c_code
;
1530 if (!disable_update
)
1531 update_input (in
, 1);
1535 /* Inserts text in input line */
1537 stuff (WInput
*in
, char *text
, int insert_extra_space
)
1539 input_disable_update (in
);
1541 handle_char (in
, *text
++);
1542 if (insert_extra_space
)
1543 handle_char (in
, ' ');
1544 input_enable_update (in
);
1545 update_input (in
, 1);
1549 input_set_point (WInput
*in
, int pos
)
1551 if (pos
> in
->current_max_len
)
1552 pos
= in
->current_max_len
;
1553 if (pos
!= in
->point
)
1554 free_completions (in
);
1556 update_input (in
, 1);
1559 int input_event (Gpm_Event
*event
, WInput
*b
);
1562 input_callback (Dlg_head
*h
, WInput
*in
, int Msg
, int Par
)
1566 return x_create_input (h
, h
->wdata
, in
);
1569 if (Par
== XCTRL('q')){
1573 v
= handle_char (in
, mi_getch ());
1577 if (Par
== KEY_UP
|| Par
== KEY_DOWN
||
1578 Par
== ESC_CHAR
|| Par
== KEY_F(10) ||
1580 return 0; /* We don't handle up/down */
1586 return handle_char (in
, Par
);
1589 case WIDGET_UNFOCUS
:
1591 update_input (in
, 0);
1594 widget_move (&in
->widget
, 0, in
->point
- in
->first_shown
);
1598 return default_proc (h
, Msg
, Par
);
1601 /* Not declared static, since we check against this value in dlg.c */
1602 /* FIXME: Declare static again and provide an identification mechanism */
1604 input_event (Gpm_Event
*event
, WInput
*in
)
1606 if (event
->type
& (GPM_DOWN
|GPM_DRAG
)){
1607 dlg_select_widget (in
->widget
.parent
, in
);
1609 if (event
->x
>= in
->field_len
- HISTORY_BUTTON_WIDTH
+ 1 && should_show_history_button (in
)) {
1612 in
->point
= strlen (in
->buffer
);
1613 if (event
->x
- in
->first_shown
- 1 < in
->point
)
1614 in
->point
= event
->x
- in
->first_shown
- 1;
1618 update_input (in
, 1);
1624 input_new (int y
, int x
, int color
, int len
, const char *def_text
, char *tkname
)
1626 WInput
*in
= g_new (WInput
, 1);
1627 int initial_buffer_len
;
1629 init_widget (&in
->widget
, y
, x
, 1, len
,
1630 (callback_fn
) input_callback
,
1631 (destroy_fn
) input_destroy
, (mouse_h
) input_event
, tkname
);
1635 in
->history_name
= 0;
1638 in
->history_name
= g_strdup (tkname
);
1639 in
->history
= history_get (tkname
);
1646 if (def_text
== INPUT_LAST_TEXT
) {
1649 if (in
->history
->text
)
1650 def_text
= in
->history
->text
;
1652 initial_buffer_len
= 1 + max (len
, strlen (def_text
));
1653 in
->widget
.options
|= W_IS_INPUT
;
1654 in
->completions
= NULL
;
1655 in
->completion_flags
=
1656 INPUT_COMPLETE_FILENAMES
| INPUT_COMPLETE_HOSTNAMES
|
1657 INPUT_COMPLETE_VARIABLES
| INPUT_COMPLETE_USERNAMES
;
1658 in
->current_max_len
= initial_buffer_len
;
1659 in
->buffer
= g_malloc (initial_buffer_len
);
1661 in
->field_len
= len
;
1663 in
->first_shown
= 0;
1664 in
->disable_update
= 0;
1667 in
->is_password
= 0;
1669 strcpy (in
->buffer
, def_text
);
1670 in
->point
= strlen (in
->buffer
);
1675 /* Listbox widget */
1677 /* Should draw the scrollbar, but currently draws only
1678 * indications that there is more information
1680 static int listbox_cdiff (WLEntry
*s
, WLEntry
*e
);
1683 listbox_drawscroll (WListbox
*l
)
1685 extern int slow_terminal
;
1688 int max_line
= l
->height
-1;
1690 /* Are we at the top? */
1691 widget_move (&l
->widget
, 0, l
->width
);
1692 if (l
->list
== l
->top
)
1697 /* Are we at the bottom? */
1698 widget_move (&l
->widget
, max_line
, l
->width
);
1699 top
= listbox_cdiff (l
->list
, l
->top
);
1700 if ((top
+ l
->height
== l
->count
) || l
->height
>= l
->count
)
1705 /* Now draw the nice relative pointer */
1707 line
= 1+ ((l
->pos
* (l
->height
-2)) / l
->count
);
1711 for (i
= 1; i
< max_line
; i
++){
1712 widget_move (&l
->widget
, i
, l
->width
);
1721 listbox_draw (WListbox
*l
, Dlg_head
*h
, int focused
)
1726 int normalc
= NORMALC
;
1737 for (e
= l
->top
, i
= 0; (i
< l
->height
); i
++){
1739 /* Display the entry */
1740 if (e
== l
->current
&& sel_line
== -1){
1746 widget_move (&l
->widget
, i
, 0);
1748 if ((i
> 0 && e
== l
->list
) || !l
->list
)
1754 printw (" %-*s ", l
->width
-2, name_trunc (text
, l
->width
-2));
1756 l
->cursor_y
= sel_line
;
1760 listbox_drawscroll (l
);
1763 /* Returns the number of items between s and e,
1764 must be on the same linked list */
1766 listbox_cdiff (WLEntry
*s
, WLEntry
*e
)
1770 for (count
= 0; s
!= e
; count
++)
1776 listbox_check_hotkey (WListbox
*l
, int key
)
1788 /* If we didn't find anything, return */
1789 if (i
&& e
== l
->list
)
1792 if (e
->hotkey
== key
)
1800 /* Used only for display updating, for avoiding line at a time scroll */
1802 listbox_select_last (WListbox
*l
, int set_top
)
1805 l
->current
= l
->list
->prev
;
1806 l
->pos
= l
->count
- 1;
1808 l
->top
= l
->list
->prev
;
1809 x_listbox_select_nth (l
, l
->pos
);
1814 listbox_remove_list (WListbox
*l
)
1823 while (l
->count
--) {
1829 l
->pos
= l
->count
= 0;
1830 l
->list
= l
->top
= l
->current
= 0;
1834 * bor 30.10.96: added force flag to remove *last* entry as well
1835 * bor 30.10.96: corrected selection bug if last entry was removed
1839 listbox_remove_current (WListbox
*l
, int force
)
1843 /* Ok, note: this won't allow for emtpy lists */
1844 if (!force
&& (!l
->count
|| l
->count
== 1))
1851 l
->current
->next
->prev
= l
->current
->prev
;
1852 l
->current
->prev
->next
= l
->current
->next
;
1853 if (p
->next
== l
->list
) {
1854 l
->current
= p
->prev
;
1858 l
->current
= p
->next
;
1861 l
->list
= l
->top
= p
->next
;
1864 l
->list
= l
->top
= l
->current
= 0;
1871 /* Makes *e the selected entry (sets current and pos) */
1873 listbox_select_entry (WListbox
*l
, WLEntry
*dest
)
1882 for (pos
= 0, e
= l
->list
; pos
< l
->count
; e
= e
->next
, pos
++){
1890 while (listbox_cdiff (l
->top
, l
->current
) >= l
->height
)
1891 l
->top
= l
->top
->next
;
1893 l
->top
= l
->current
;
1896 x_listbox_select_nth (l
, l
->pos
);
1900 /* If we are unable to find it, set decent values */
1901 l
->current
= l
->top
= l
->list
;
1903 x_listbox_select_nth (l
, l
->pos
);
1906 /* Selects from base the pos element */
1908 listbox_select_pos (WListbox
*l
, WLEntry
*base
, int pos
)
1910 WLEntry
*last
= l
->list
->prev
;
1923 listbox_back (WListbox
*l
)
1926 listbox_select_entry (l
, listbox_select_pos (l
, l
->list
, l
->pos
-1));
1933 listbox_fwd (WListbox
*l
)
1935 if (l
->current
!= l
->list
->prev
){
1936 listbox_select_entry (l
, listbox_select_pos (l
, l
->list
, l
->pos
+1));
1942 /* Returns 1 if we want a redraw */
1944 listbox_key (WListbox
*l
, int key
)
1955 l
->current
= l
->top
= l
->list
;
1961 l
->current
= l
->top
= l
->list
->prev
;
1962 for (i
= min (l
->height
- 1, l
->count
- 1); i
; i
--)
1963 l
->top
= l
->top
->prev
;
1964 l
->pos
= l
->count
- 1;
1979 for (i
= 0; i
< l
->height
-1; i
++)
1980 j
|= listbox_fwd (l
);
1985 for (i
= 0; i
< l
->height
-1; i
++)
1986 j
|= listbox_back (l
);
1992 static int listbox_event (Gpm_Event
*event
, WListbox
*l
);
1994 listbox_callback (Dlg_head
*h
, WListbox
*l
, int msg
, int par
)
1997 /* int selected_color; Never used */
2002 return x_create_listbox (h
, h
->wdata
, l
);
2005 if ((e
= listbox_check_hotkey (l
, par
)) != NULL
){
2006 listbox_select_entry (l
, e
);
2008 /* Take the appropriate action */
2009 if (l
->action
== listbox_finish
){
2010 l
->widget
.parent
->running
= 0;
2011 l
->widget
.parent
->ret_value
= B_ENTER
;
2012 } else if (l
->action
== listbox_cback
){
2013 if ((*l
->cback
)(l
) == listbox_finish
){
2014 l
->widget
.parent
->running
= 0;
2015 l
->widget
.parent
->ret_value
= B_ENTER
;
2023 if ((ret_code
= listbox_key (l
, par
)))
2024 listbox_draw (l
, h
, 1);
2028 widget_move (&l
->widget
, l
->cursor_y
, 0);
2032 case WIDGET_UNFOCUS
:
2034 listbox_draw (l
, h
, msg
!= WIDGET_UNFOCUS
);
2037 return default_proc (h
, msg
, par
);
2041 listbox_event (Gpm_Event
*event
, WListbox
*l
)
2045 Dlg_head
*h
= l
->widget
.parent
;
2048 if (event
->type
& GPM_DOWN
)
2049 dlg_select_widget (l
->widget
.parent
, l
);
2052 if (event
->type
& (GPM_DOWN
|GPM_DRAG
)){
2053 if (event
->x
< 0 || event
->x
>= l
->width
)
2056 for (i
= -event
->y
; i
>= 0; i
--)
2058 else if (event
->y
> l
->height
)
2059 for (i
= event
->y
- l
->height
; i
> 0; i
--)
2062 listbox_select_entry (l
, listbox_select_pos (l
, l
->top
,
2065 /* We need to refresh ourselves since the dialog manager doesn't */
2066 /* know about this event */
2067 listbox_callback (h
, l
, WIDGET_DRAW
, 0);
2073 if ((event
->type
& (GPM_DOUBLE
|GPM_UP
)) == (GPM_UP
|GPM_DOUBLE
)){
2074 if (event
->x
< 0 || event
->x
>= l
->width
)
2076 if (event
->y
< 1 || event
->y
> l
->height
)
2079 dlg_select_widget (l
->widget
.parent
, l
);
2080 listbox_select_entry (l
, listbox_select_pos (l
, l
->top
, event
->y
- 1));
2083 case listbox_nothing
:
2086 case listbox_finish
:
2087 h
->ret_value
= B_ENTER
;
2092 if ((*l
->cback
)(l
) == listbox_finish
)
2100 listbox_destroy (WListbox
*l
)
2102 WLEntry
*n
, *p
= l
->list
;
2106 for (i
= 0; i
< l
->count
; i
++){
2115 listbox_new (int y
, int x
, int width
, int height
,
2116 int action
, lcback callback
, char *tkname
)
2118 WListbox
*l
= g_new (WListbox
, 1);
2119 extern int slow_terminal
;
2121 init_widget (&l
->widget
, y
, x
, height
, width
,
2122 (callback_fn
)listbox_callback
,
2123 (destroy_fn
) listbox_destroy
, (mouse_h
)listbox_event
, tkname
);
2125 l
->list
= l
->top
= l
->current
= 0;
2135 l
->cback
= callback
;
2137 l
->allow_duplicates
= 1;
2138 l
->scrollbar
= slow_terminal
? 0 : 1;
2139 widget_want_hotkey (l
->widget
, 1);
2144 /* Listbox item adding function. They still lack a lot of functionality */
2146 /* 1.11.96 bor: added pos argument to control placement of new entry */
2148 listbox_append_item (WListbox
*l
, WLEntry
*e
, enum append_pos pos
)
2156 } else if (pos
== LISTBOX_APPEND_AT_END
) {
2158 e
->prev
= l
->list
->prev
;
2159 l
->list
->prev
->next
= e
;
2161 } else if (pos
== LISTBOX_APPEND_BEFORE
){
2162 e
->next
= l
->current
;
2163 e
->prev
= l
->current
->prev
;
2164 l
->current
->prev
->next
= e
;
2165 l
->current
->prev
= e
;
2166 if (l
->list
== l
->current
) { /* move list one position down */
2170 } else if (pos
== LISTBOX_APPEND_AFTER
) {
2171 e
->prev
= l
->current
;
2172 e
->next
= l
->current
->next
;
2173 l
->current
->next
->prev
= e
;
2174 l
->current
->next
= e
;
2176 x_list_insert (l
, l
->list
, e
);
2181 listbox_add_item (WListbox
*l
, enum append_pos pos
, int hotkey
, char *text
,
2189 if (!l
->allow_duplicates
)
2190 if (listbox_search_text (l
, text
))
2193 entry
= g_new (WLEntry
, 1);
2194 entry
->text
= g_strdup (text
);
2196 entry
->hotkey
= hotkey
;
2198 listbox_append_item (l
, entry
, pos
);
2203 /* Selects the nth entry in the listbox */
2205 listbox_select_by_number (WListbox
*l
, int n
)
2207 listbox_select_entry (l
, listbox_select_pos (l
, l
->list
, n
));
2211 listbox_search_text (WListbox
*l
, char *text
)
2220 if(!strcmp (e
->text
, text
))
2223 } while (e
!=l
->list
);
2228 /* Returns the current string text as well as the associated extra data */
2230 listbox_get_current (WListbox
*l
, char **string
, char **extra
)
2236 if (string
&& l
->current
)
2237 *string
= l
->current
->text
;
2238 if (extra
&& l
->current
)
2239 *extra
= l
->current
->data
;
2243 buttonbar_callback (Dlg_head
*h
, WButtonBar
*bb
, int msg
, int par
)
2249 return x_create_buttonbar (h
, h
->wdata
, bb
);
2255 for (i
= 0; i
< 10; i
++){
2256 if (par
== KEY_F(i
+1) && bb
->labels
[i
].function
){
2257 (*bb
->labels
[i
].function
)(bb
->labels
[i
].data
);
2266 widget_move (&bb
->widget
, 0, 0);
2267 attrset (DEFAULT_COLOR
);
2268 printw ("%-*s", bb
->widget
.cols
- 1, "");
2269 for (i
= 0; i
< COLS
/8 && i
< 10; i
++){
2270 widget_move (&bb
->widget
, 0, i
*8);
2271 attrset (DEFAULT_COLOR
);
2273 attrset (SELECTED_COLOR
);
2274 printw ("%-*s", ((i
+1) * 8 == COLS
? 5 : 6),
2275 bb
->labels
[i
].text
? bb
->labels
[i
].text
: "");
2276 attrset (DEFAULT_COLOR
);
2278 attrset (SELECTED_COLOR
);
2281 return default_proc (h
, msg
, par
);
2285 buttonbar_destroy (WButtonBar
*bb
)
2289 for (i
= 0; i
< 10; i
++){
2290 if (bb
->labels
[i
].text
)
2291 g_free (bb
->labels
[i
].text
);
2296 buttonbar_event (Gpm_Event
*event
, WButtonBar
*bb
)
2300 if (!(event
->type
& GPM_UP
))
2304 button
= event
->x
/ 8;
2305 if (button
< 10 && bb
->labels
[button
].function
)
2306 (*bb
->labels
[button
].function
)(bb
->labels
[button
].data
);
2311 buttonbar_new (int visible
)
2314 WButtonBar
*bb
= g_new (WButtonBar
, 1);
2316 init_widget (&bb
->widget
, LINES
-1, 0, 1, COLS
,
2317 (callback_fn
) buttonbar_callback
,
2318 (destroy_fn
) buttonbar_destroy
, (mouse_h
) buttonbar_event
, NULL
);
2320 bb
->visible
= visible
;
2321 for (i
= 0; i
< 10; i
++){
2322 bb
->labels
[i
].text
= 0;
2323 bb
->labels
[i
].function
= 0;
2325 widget_want_hotkey (bb
->widget
, 1);
2326 widget_want_cursor (bb
->widget
, 0);
2332 set_label_text (WButtonBar
*bb
, int index
, char *text
)
2334 if (bb
->labels
[index
-1].text
)
2335 g_free (bb
->labels
[index
-1].text
);
2337 bb
->labels
[index
-1].text
= g_strdup (text
);
2340 /* paneletc is either the panel widget, or info or view or tree widget */
2342 find_buttonbar (Dlg_head
*h
, Widget
*paneletc
)
2349 for (i
= 0, item
= h
->current
; i
< h
->count
; i
++, item
= item
->next
){
2350 if (item
->widget
->callback
== (callback_fn
) buttonbar_callback
){
2351 bb
= (WButtonBar
*) item
->widget
;
2359 define_label_data (Dlg_head
*h
, Widget
*paneletc
, int idx
, char *text
,
2360 buttonbarfn cback
, void *data
)
2362 WButtonBar
*bb
= find_buttonbar (h
, paneletc
);
2366 set_label_text (bb
, idx
, text
);
2367 bb
->labels
[idx
-1].function
= cback
;
2368 bb
->labels
[idx
-1].data
= data
;
2369 x_redefine_label (bb
, idx
);
2373 define_label (Dlg_head
*h
, Widget
*paneletc
, int idx
, char *text
, void (*cback
)(void))
2375 define_label_data (h
, paneletc
, idx
, text
, (buttonbarfn
) cback
, 0);
2379 redraw_labels (Dlg_head
*h
, Widget
*paneletc
)
2384 for (i
= 0, item
= h
->current
; i
< h
->count
; i
++, item
= item
->next
){
2385 if (item
->widget
->callback
== (callback_fn
) buttonbar_callback
){
2386 widget_redraw (h
, item
);