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 */
45 #include "profile.h" /* for history loading and saving */
48 # define x_create_button(a,b,c) 1
49 # define x_create_radio(a,b,c) 1
50 # define x_create_check(a,b,c) 1
51 # define x_create_label(a,b,c) 1
52 # define x_create_input(a,b,c) 1
53 # define x_create_listbox(a,b,c) 1
54 # define x_create_buttonbar(a,b,c) 1
55 # define x_create_gauge(a,b,c) 1
56 # define x_listbox_select_nth(a,b)
57 # define x_list_insert(a,b,c)
58 # define x_redefine_label(a,b)
61 #ifndef PORT_HAS_DESTROY_CMD
62 # define x_destroy_cmd(w)
65 #ifndef PORT_HAS_RADIO_FOCUS_ITEM
66 # define x_radio_focus_item(r)
69 #ifndef PORT_HAS_RADIO_TOGGLE
70 # define x_radio_toggle(r)
73 static int button_event (Gpm_Event
*event
, WButton
*b
);
78 button_callback (Dlg_head
*h
, WButton
*b
, int Msg
, int Par
)
88 return x_create_button (h
, h
->wdata
, b
);
91 if (b
->hotkey
== Par
|| toupper(b
->hotkey
) == Par
){
92 button_callback (h
, b
, WIDGET_KEY
, ' '); /* to make action */
98 if (Par
!= ' ' && Par
!= '\n')
102 stop
= (*b
->callback
)(b
->action
, b
->callback_data
);
103 if (!b
->callback
|| stop
){
104 h
->ret_value
= b
->action
;
125 widget_move (&b
->widget
, 0, b
->hotpos
+ off
);
132 if (Msg
==WIDGET_UNFOCUS
)
134 else if (Msg
==WIDGET_FOCUS
)
139 g_snprintf (buf
, sizeof(buf
), "[< %s >]", b
->text
);
143 g_snprintf (buf
, sizeof(buf
), "[ %s ]", b
->text
);
147 g_snprintf (buf
, sizeof(buf
), "[%s]", b
->text
);
157 attrset ((b
->selected
) ? FOCUSC
: NORMALC
);
158 widget_move (&b
->widget
, 0, 0);
163 attrset ((b
->selected
) ? HOT_FOCUSC
: HOT_NORMALC
);
164 widget_move (&b
->widget
, 0, b
->hotpos
+off
);
165 addch ((unsigned char)b
->text
[b
->hotpos
]);
168 if (Msg
== WIDGET_FOCUS
)
174 return default_proc (h
, Msg
, Par
);
178 button_event (Gpm_Event
*event
, WButton
*b
)
181 if (event
->type
& (GPM_DOWN
|GPM_UP
)){
182 Dlg_head
*h
=b
->widget
.parent
;
183 dlg_select_widget (h
, b
);
184 if (event
->type
& GPM_UP
){
185 button_callback (h
, b
, WIDGET_KEY
, ' ');
186 (*h
->callback
) (h
, ' ', DLG_POST_KEY
);
195 button_destroy (WButton
*b
)
202 button_len (const char *text
, unsigned int flags
)
205 int ret
= strlen (text
);
222 return strlen (text
);
227 * Assuming that button text is malloc'ed, we may safely change it
228 * (as opposed to statically allocated); from other hand, excluding &
229 * and shifting data past it to the left results to one unused byte.
230 * This does not harm though :)
233 button_scan_hotkey(WButton
* b
)
235 char* cp
= strchr (b
->text
, '&');
237 if (cp
!= NULL
&& cp
[1] != '\0'){
239 b
->hotkey
= tolower (*cp
);
240 b
->hotpos
= cp
- b
->text
;
245 button_new (int y
, int x
, int action
, int flags
, char *text
,
246 int (*callback
)(int, void *), void *callback_data
, char *tkname
)
248 WButton
*b
= g_new (WButton
, 1);
250 init_widget (&b
->widget
, y
, x
, 1, button_len (text
, flags
),
251 (callback_fn
) button_callback
,
252 (destroy_fn
) button_destroy
, (mouse_h
)button_event
, tkname
);
257 b
->text
= g_strdup (text
);
258 b
->callback
= callback
;
259 b
->callback_data
= callback_data
;
260 widget_want_hotkey (b
->widget
, 1);
264 button_scan_hotkey(b
);
269 button_set_text (WButton
*b
, char *text
)
272 b
->text
= g_strdup (text
);
273 b
->widget
.cols
= button_len (text
, b
->flags
);
274 button_scan_hotkey(b
);
276 x_button_set (b
, b
->text
);
278 dlg_redraw (b
->widget
.parent
);
283 /* Radio button widget */
284 static int radio_event (Gpm_Event
*event
, WRadio
*r
);
287 radio_callback (Dlg_head
*h
, WRadio
*r
, int Msg
, int Par
)
295 return x_create_radio (h
, h
->wdata
, r
);
299 int i
, lp
= tolower(Par
);
302 for (i
= 0; i
< r
->count
; i
++){
303 cp
= strchr (r
->texts
[i
], '&');
304 if (cp
!= NULL
&& cp
[1] != '\0'){
305 int c
= tolower (cp
[1]);
310 radio_callback (h
, r
, WIDGET_KEY
, ' '); /* Take action */
321 (*h
->callback
) (h
, h
->current
->dlg_id
, DLG_ACTION
);
322 radio_callback (h
, r
, WIDGET_FOCUS
, ' ');
330 x_radio_focus_item (r
);
337 if (r
->count
- 1 > r
->pos
) {
339 x_radio_focus_item (r
);
348 x_radio_focus_item (r
);
354 (*h
->callback
) (h
, h
->current
->dlg_id
, DLG_ACTION
);
355 radio_callback (h
, r
, WIDGET_FOCUS
, ' ');
356 widget_move (&r
->widget
, r
->pos
, 1);
362 for (i
= 0; i
< r
->count
; i
++){
363 register unsigned char* cp
;
364 attrset ((i
==r
->pos
&& Msg
==WIDGET_FOCUS
) ? FOCUSC
:NORMALC
);
365 widget_move (&r
->widget
, i
, 0);
367 printw("(%c) ", (r
->sel
== i
) ? '*' : ' ');
368 for (cp
= r
->texts
[i
]; *cp
; cp
++)
372 attrset ((i
==r
->pos
&& Msg
==WIDGET_FOCUS
)
373 ? HOT_FOCUSC
: HOT_NORMALC
);
375 attrset ((i
==r
->pos
&& Msg
==WIDGET_FOCUS
) ? FOCUSC
: NORMALC
);
385 return default_proc (h
, Msg
, Par
);
389 radio_event (Gpm_Event
*event
, WRadio
*r
)
392 if (event
->type
& (GPM_DOWN
|GPM_UP
)){
393 Dlg_head
*h
= r
->widget
.parent
;
395 r
->pos
= event
->y
- 1;
396 dlg_select_widget (h
, r
);
397 if (event
->type
& GPM_UP
){
398 radio_callback (h
, r
, WIDGET_KEY
, ' ');
399 radio_callback (h
, r
, WIDGET_FOCUS
, 0);
400 (*h
->callback
) (h
, ' ', DLG_POST_KEY
);
409 radio_new (int y
, int x
, int count
, char **texts
, int use_hotkey
, char *tkname
)
411 WRadio
*r
= g_new (WRadio
, 1);
414 /* Compute the longest string */
416 for (i
= 0; i
< count
; i
++){
417 m
= strlen (texts
[i
]);
422 init_widget (&r
->widget
, y
, x
, count
, max
, (callback_fn
) radio_callback
,
423 0, (mouse_h
) radio_event
, tkname
);
429 r
->upper_letter_is_hotkey
= use_hotkey
;
430 widget_want_hotkey (r
->widget
, 1);
436 /* Checkbutton widget */
438 static int check_event (Gpm_Event
*event
, WCheck
*b
);
441 check_callback (Dlg_head
*h
, WCheck
*c
, int Msg
, int Par
)
445 return x_create_check (h
, h
->wdata
, c
);
448 if (c
->hotkey
==Par
||
449 (c
->hotkey
>='a' && c
->hotkey
<='z' && c
->hotkey
-32==Par
)){
450 check_callback (h
, c
, WIDGET_KEY
, ' '); /* make action */
459 c
->state
^= C_CHANGE
;
460 (*h
->callback
) (h
, h
->current
->dlg_id
, DLG_ACTION
);
461 check_callback (h
, c
, WIDGET_FOCUS
, ' ');
466 widget_move (&c
->widget
, 0, 1);
472 attrset ((Msg
== WIDGET_FOCUS
) ? FOCUSC
: NORMALC
);
473 widget_move (&c
->widget
, 0, 0);
474 printw ("[%c] %s", (c
->state
& C_BOOL
) ? 'x' : ' ', c
->text
);
477 attrset ((Msg
== WIDGET_FOCUS
) ? HOT_FOCUSC
: HOT_NORMALC
);
478 widget_move (&c
->widget
, 0, + c
->hotpos
+4);
479 addch ((unsigned char)c
->text
[c
->hotpos
]);
484 return default_proc (h
, Msg
, Par
);
488 check_event (Gpm_Event
*event
, WCheck
*c
)
491 if (event
->type
& (GPM_DOWN
|GPM_UP
)){
492 Dlg_head
*h
= c
->widget
.parent
;
494 dlg_select_widget (h
, c
);
495 if (event
->type
& GPM_UP
){
496 check_callback (h
, c
, WIDGET_KEY
, ' ');
497 check_callback (h
, c
, WIDGET_FOCUS
, 0);
498 (*h
->callback
) (h
, ' ', DLG_POST_KEY
);
507 check_destroy (WCheck
*c
)
514 check_new (int y
, int x
, int state
, char *text
, char *tkname
)
516 WCheck
*c
= g_new (WCheck
, 1);
519 init_widget (&c
->widget
, y
, x
, 1, strlen (text
),
520 (callback_fn
)check_callback
,
521 (destroy_fn
)check_destroy
, (mouse_h
) check_event
, tkname
);
522 c
->state
= state
? C_BOOL
: 0;
523 c
->text
= g_strdup (text
);
526 widget_want_hotkey (c
->widget
, 1);
528 /* Scan for the hotkey */
529 for (s
= text
, t
= c
->text
; *s
; s
++, t
++){
536 c
->hotkey
= tolower (*s
);
537 c
->hotpos
= t
- c
->text
;
549 label_callback (Dlg_head
*h
, WLabel
*l
, int Msg
, int Par
)
551 if (Msg
== WIDGET_INIT
)
552 return x_create_label (h
, h
->wdata
, l
);
554 /* We don't want to get the focus */
555 if (Msg
== WIDGET_FOCUS
)
558 if (Msg
== WIDGET_DRAW
&& l
->text
){
559 char *p
= l
->text
, *q
, c
= 0;
562 attrset (DEFAULT_COLOR
);
568 q
= strchr (p
, '\n');
573 widget_move (&l
->widget
, y
, 0);
575 xlen
= l
->widget
.cols
- strlen (p
);
577 printw ("%*s", xlen
, " ");
587 return default_proc (h
, Msg
, Par
);
591 label_set_text (WLabel
*label
, char *text
)
593 int newcols
= label
->widget
.cols
;
595 if (label
->text
&& text
&& !strcmp (label
->text
, text
))
596 return; /* Flickering is not nice */
599 g_free (label
->text
);
602 label
->text
= g_strdup (text
);
603 if (label
->auto_adjust_cols
) {
604 newcols
= strlen (text
);
605 if (newcols
> label
->widget
.cols
)
606 label
->widget
.cols
= newcols
;
611 if (label
->widget
.parent
)
613 x_label_set_text (label
, text
);
615 label_callback (label
->widget
.parent
, label
, WIDGET_DRAW
, 0);
617 if (newcols
< label
->widget
.cols
)
618 label
->widget
.cols
= newcols
;
622 label_destroy (WLabel
*l
)
630 label_new (int y
, int x
, char *text
, char *tkname
)
632 WLabel
*l
= g_new (WLabel
, 1);
634 init_widget (&l
->widget
, y
, x
, 1, 1,
635 (callback_fn
) label_callback
,
636 (destroy_fn
) label_destroy
, NULL
, tkname
);
637 l
->text
= text
? g_strdup (text
) : 0;
638 l
->auto_adjust_cols
= 1;
640 widget_want_cursor (l
->widget
, 0);
645 /* Gauge widget (progress indicator) */
646 /* Currently width is hardcoded here for text mode */
650 gauge_callback (Dlg_head
*h
, WGauge
*g
, int Msg
, int Par
)
653 if (Msg
== WIDGET_INIT
)
654 return x_create_gauge (h
, h
->wdata
, g
);
656 /* We don't want to get the focus */
657 if (Msg
== WIDGET_FOCUS
)
661 if (Msg
== WIDGET_DRAW
){
662 widget_move (&g
->widget
, 0, 0);
665 printw ("%*s", gauge_len
, "");
667 long percentage
, columns
;
668 long total
= g
->max
, done
= g
->current
;
670 if (total
<= 0 || done
< 0) {
676 while (total
> 65535) {
680 percentage
= (200 * done
/ total
+ 1) / 2;
681 columns
= (2 * (gauge_len
- 7) * done
/ total
+ 1) / 2;
683 attrset (GAUGE_COLOR
);
684 printw ("%*s", columns
, "");
686 printw ("%*s] %3d%%", gauge_len
- 7 - columns
, "", percentage
);
691 return default_proc (h
, Msg
, Par
);
695 gauge_set_value (WGauge
*g
, int max
, int current
)
697 if (g
->current
== current
&& g
->max
== max
)
698 return; /* Do not flicker */
700 max
= 1; /* I do not like division by zero :) */
702 /* NOTE: x_gauge_set_value has to be called before we change actual
703 * max and current values in g, since it assumes g->max and
704 * g->current as the previous values and max and current
705 * as the new ones :) */
706 x_gauge_set_value (g
, max
, current
);
708 g
->current
= current
;
711 gauge_callback (g
->widget
.parent
, g
, WIDGET_DRAW
, 0);
716 gauge_show (WGauge
*g
, int shown
)
718 if (g
->shown
== shown
)
724 gauge_callback (g
->widget
.parent
, g
, WIDGET_DRAW
, 0);
729 gauge_destroy (WGauge
*g
)
735 gauge_new (int y
, int x
, int shown
, int max
, int current
, char *tkname
)
737 WGauge
*g
= g_new (WGauge
, 1);
739 init_widget (&g
->widget
, y
, x
, 1, gauge_len
,
740 (callback_fn
) gauge_callback
,
741 (destroy_fn
) gauge_destroy
, NULL
, tkname
);
744 max
= 1; /* I do not like division by zero :) */
746 g
->current
= current
;
748 widget_want_cursor (g
->widget
, 0);
755 /* {{{ history button */
757 #define LARGE_HISTORY_BUTTON 1
759 #ifdef LARGE_HISTORY_BUTTON
760 # define HISTORY_BUTTON_WIDTH 3
762 # define HISTORY_BUTTON_WIDTH 1
765 #define should_show_history_button(in) \
766 (in->history && in->field_len > HISTORY_BUTTON_WIDTH * 2 + 1 && in->widget.parent)
769 static void draw_history_button (WInput
* in
)
772 c
= in
->history
->next
? (in
->history
->prev
? '|' : 'v') : '^';
773 widget_move (&in
->widget
, 0, in
->field_len
- HISTORY_BUTTON_WIDTH
);
774 #ifdef LARGE_HISTORY_BUTTON
777 h
= in
->widget
.parent
;
779 attrset (NORMALC
); /* button has the same colour as other buttons */
781 attrset (HOT_NORMALC
);
783 attrset (NORMAL_COLOR
);
785 /* Too distracting: attrset (MARKED_COLOR); */
787 widget_move (&in
->widget
, 0, in
->field_len
- HISTORY_BUTTON_WIDTH
+ 1);
791 attrset (MARKED_COLOR
);
797 /* }}} history button */
800 /* Input widgets now have a global kill ring */
801 /* Pointer to killed data */
802 static char *kill_buffer
= 0;
805 update_input (WInput
*in
, int clear_first
)
812 int buf_len
= strlen (in
->buffer
);
814 if (should_show_history_button (in
))
815 has_history
= HISTORY_BUTTON_WIDTH
;
817 if (in
->disable_update
)
820 /* Make the point visible */
821 if ((in
->point
< in
->first_shown
) ||
822 (in
->point
>= in
->first_shown
+in
->field_len
- has_history
)){
823 in
->first_shown
= in
->point
- (in
->field_len
/ 3);
824 if (in
->first_shown
< 0)
828 /* Adjust the mark */
829 if (in
->mark
> buf_len
)
833 if (clear_first
&& in
->first
)
839 draw_history_button (in
);
843 widget_move (&in
->widget
, 0, 0);
844 for (i
= 0; i
< in
->field_len
- has_history
; i
++)
846 widget_move (&in
->widget
, 0, 0);
848 for (i
= 0, j
= in
->first_shown
; i
< in
->field_len
- has_history
&& in
->buffer
[j
]; i
++){
849 c
= in
->buffer
[j
++];
850 c
= is_printable (c
) ? c
: '.';
855 widget_move (&in
->widget
, 0, in
->point
- in
->first_shown
);
863 winput_set_origin (WInput
*in
, int x
, int field_len
)
866 in
->field_len
= in
->widget
.cols
= field_len
;
867 update_input (in
, 0);
870 /* {{{ history saving and loading */
873 This loads and saves the history of an input line to and from the
874 widget. It is called with the widgets tk name on creation of the
875 widget, and returns the Hist list. It stores histories in the file
876 ~/.mc/history in using the profile code.
878 If def_text is passed as INPUT_LAST_TEXT (to the input_new()
879 function) then input_new assigns the default text to be the last text
880 entered, or "" if not found.
883 int num_history_items_recorded
= 60;
885 Hist
*history_get (char *input_name
)
893 if (!num_history_items_recorded
) /* this is how to disable */
899 profile
= concat_dir_and_file (home_dir
, HISTORY_FILE_NAME
);
901 char key_name
[BUF_TINY
];
902 char this_entry
[BUF_LARGE
];
903 g_snprintf (key_name
, sizeof (key_name
), "%d", i
);
904 GetPrivateProfileString (input_name
, key_name
, "", this_entry
, sizeof (this_entry
), profile
);
907 new = g_new0 (Hist
, 1);
908 new->text
= g_strdup (this_entry
);
909 new->prev
= old
; /* set up list pointers */
915 return new; /* return pointer to last entry in list */
918 void history_put (char *input_name
, Hist
*h
)
920 #ifdef PORT_WIDGET_WANTS_HISTORY
933 if (!num_history_items_recorded
) /* this is how to disable */
936 profile
= concat_dir_and_file (home_dir
, HISTORY_FILE_NAME
);
938 if ((i
= open (profile
, O_CREAT
| O_EXCL
, S_IRUSR
| S_IWUSR
)) != -1)
940 /* Just in case I forgot to strip passwords somewhere -- Norbert */
941 if (chmod (profile
, S_IRUSR
| S_IWUSR
) == -1 && errno
!= ENOENT
){
946 while (h
->next
) /* go to end of list */
949 /* go back 60 places */
950 for (i
= 0; i
< num_history_items_recorded
- 1 && h
->prev
; i
++)
954 profile_clean_section (input_name
, profile
);
956 /* dump histories into profile */
957 for (i
= 0; h
; h
= h
->next
){
960 /* probably aren't any null entries, but lets be sure */
962 char key_name
[BUF_TINY
];
963 g_snprintf (key_name
, sizeof(key_name
), "%d", i
++);
964 WritePrivateProfileString (input_name
, key_name
, h
->text
, profile
);
972 /* }}} history saving and loading */
975 /* {{{ history display */
980 static char *history_title
= NULL
;
982 if (history_title
== NULL
)
983 history_title
= _(" History ");
984 return history_title
;
988 history_callback (Dlg_head
* h
, int Par
, int Msg
)
993 attrset (COLOR_NORMAL
);
995 draw_box (h
, 0, 0, h
->lines
, h
->cols
);
996 attrset (COLOR_HOT_NORMAL
);
997 dlg_move (h
, 0, (h
->cols
- strlen (i18n_htitle())) / 2);
998 printw (i18n_htitle());
1005 static inline int listbox_fwd (WListbox
*l
);
1007 char *show_hist (Hist
*history
, int widget_x
, int widget_y
)
1010 size_t maxlen
= strlen (i18n_htitle()), i
, count
= 0;
1013 Dlg_head
*query_dlg
;
1014 WListbox
*query_list
;
1020 while (z
->prev
) /* goto first */
1024 if ((i
= strlen (hi
->text
)) > maxlen
)
1032 if (h
<= y
|| y
> LINES
- 6)
1040 h
= min(h
, LINES
- y
);
1047 if ((w
= maxlen
+ 4) + x
> COLS
)
1053 query_dlg
= create_dlg (y
, x
, h
, w
, dialog_colors
, history_callback
,
1054 "[History-query]", "history", DLG_NONE
);
1055 query_list
= listbox_new (1, 1, w
- 2, h
- 2, listbox_finish
, 0, NULL
);
1056 add_widget (query_dlg
, query_list
);
1059 while (hi
) { /* traverse */
1060 listbox_add_item (query_list
, 0, 0, hi
->text
, NULL
);
1063 while (listbox_fwd (query_list
));
1067 while (hi
) { /* traverse backwards */
1068 listbox_add_item (query_list
, 0, 0, hi
->text
, NULL
);
1072 run_dlg (query_dlg
);
1074 if (query_dlg
->ret_value
!= B_CANCEL
) {
1075 listbox_get_current (query_list
, &q
, NULL
);
1079 destroy_dlg (query_dlg
);
1083 static void do_show_hist (WInput
* in
)
1086 r
= show_hist (in
->history
, in
->widget
.x
, in
->widget
.y
);
1088 assign_text (in
, r
);
1093 /* }}} history display */
1096 input_destroy (WInput
*in
)
1099 fprintf (stderr
, "Internal error: null Input *\n");
1105 Hist
*current
, *old
;
1107 if (!in
->is_password
&& PORT_WIDGET_WANTS_HISTORY
) /* don't save passwords ;-) */
1108 history_put (in
->history_name
, in
->history
);
1110 current
= in
->history
;
1111 while (current
->next
)
1112 current
= current
->next
;
1115 current
= current
->prev
;
1121 g_free (in
->buffer
);
1122 free_completions (in
);
1123 if (in
->history_name
)
1124 g_free (in
->history_name
);
1127 static char disable_update
= 0;
1130 input_disable_update (WInput
*in
)
1132 in
->disable_update
++;
1136 input_enable_update (WInput
*in
)
1138 in
->disable_update
--;
1139 update_input (in
, 0);
1142 #define ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
1145 push_history (WInput
*in
, char *text
)
1148 /* input widget where urls with passwords are entered without any
1150 static const char *password_input_fields
[] = {
1151 N_(" Link to a remote machine "),
1152 N_(" FTP to machine "),
1153 N_(" SMB link to machine ")
1161 for (i
= 0; i
< ELEMENTS(password_input_fields
); i
++)
1162 password_input_fields
[i
] = _(password_input_fields
[i
]);
1165 for (p
= text
; *p
== ' ' || *p
== '\t'; p
++);
1169 while (in
->history
->next
)
1170 in
->history
= in
->history
->next
;
1171 if (!strcmp (in
->history
->text
, text
))
1173 new = g_new (Hist
, 1);
1174 in
->history
->next
= new;
1176 new = g_new (Hist
, 1);
1179 new->prev
= in
->history
;
1180 new->text
= g_strdup (text
);
1181 if (in
->history_name
) {
1182 p
= in
->history_name
+ 3;
1183 for (i
= 0; i
< ELEMENTS(password_input_fields
); i
++)
1184 if (strcmp (p
, password_input_fields
[i
]) == 0)
1186 if (i
< ELEMENTS(password_input_fields
))
1187 strip_password (new->text
, 0);
1189 strip_password (new->text
, 1);
1198 /* Cleans the input line and adds the current text to the history */
1200 new_input (WInput
*in
)
1203 push_history (in
, in
->buffer
);
1208 free_completions (in
);
1209 update_input (in
, 0);
1213 insert_char (WInput
*in
, int c_code
)
1221 if (strlen (in
->buffer
)+1 == in
->current_max_len
){
1222 /* Expand the buffer */
1223 char *narea
= g_malloc (in
->current_max_len
+ in
->field_len
);
1225 char *p
= in
->buffer
;
1227 strcpy (narea
, in
->buffer
);
1229 in
->current_max_len
+= in
->field_len
;
1233 if (strlen (in
->buffer
)+1 < in
->current_max_len
){
1234 int l
= strlen (&in
->buffer
[in
->point
]);
1235 for (i
= l
+1; i
> 0; i
--)
1236 in
->buffer
[in
->point
+i
] = in
->buffer
[in
->point
+i
-1];
1237 in
->buffer
[in
->point
] = c_code
;
1244 beginning_of_line (WInput
*in
)
1250 end_of_line (WInput
*in
)
1252 in
->point
= strlen (in
->buffer
);
1256 backward_char (WInput
*in
)
1263 forward_char (WInput
*in
)
1265 if (in
->buffer
[in
->point
])
1270 forward_word (WInput
*in
)
1272 unsigned char *p
= in
->buffer
+in
->point
;
1274 while (*p
&& (isspace (*p
) || ispunct (*p
)))
1276 while (*p
&& isalnum (*p
))
1278 in
->point
= p
- in
->buffer
;
1282 backward_word (WInput
*in
)
1284 unsigned char *p
= in
->buffer
+in
->point
;
1286 while (p
-1 > in
->buffer
-1 && (isspace (*(p
-1)) || ispunct (*(p
-1))))
1288 while (p
-1 > in
->buffer
-1 && isalnum (*(p
-1)))
1290 in
->point
= p
- in
->buffer
;
1293 #if defined(__linux__) && !defined(HAVE_X)
1295 key_left (WInput
*in
)
1297 if (ctrl_pressed ())
1304 key_right (WInput
*in
)
1306 if (ctrl_pressed ())
1312 #define key_left backward_char
1313 #define key_right forward_char
1317 backward_delete (WInput
*in
)
1323 for (i
= in
->point
; in
->buffer
[i
-1]; i
++)
1324 in
->buffer
[i
-1] = in
->buffer
[i
];
1330 delete_char (WInput
*in
)
1334 for (i
= in
->point
; in
->buffer
[i
]; i
++)
1335 in
->buffer
[i
] = in
->buffer
[i
+1];
1340 copy_region (WInput
*in
, int x_first
, int x_last
)
1342 int first
= min (x_first
, x_last
);
1343 int last
= max (x_first
, x_last
);
1349 g_free (kill_buffer
);
1351 kill_buffer
= g_malloc (last
-first
+ 1);
1352 strncpy (kill_buffer
, in
->buffer
+first
, last
-first
);
1353 kill_buffer
[last
-first
] = 0;
1357 delete_region (WInput
*in
, int x_first
, int x_last
)
1359 int first
= min (x_first
, x_last
);
1360 int last
= max (x_first
, x_last
);
1364 strcpy (&in
->buffer
[first
], &in
->buffer
[last
]);
1369 kill_word (WInput
*in
)
1371 int old_point
= in
->point
;
1375 new_point
= in
->point
;
1376 in
->point
= old_point
;
1378 copy_region (in
, old_point
, new_point
);
1379 delete_region (in
, old_point
, new_point
);
1384 back_kill_word (WInput
*in
)
1386 int old_point
= in
->point
;
1390 new_point
= in
->point
;
1391 in
->point
= old_point
;
1393 copy_region (in
, old_point
, new_point
);
1394 delete_region (in
, old_point
, new_point
);
1399 set_mark (WInput
*in
)
1401 in
->mark
= in
->point
;
1405 kill_save (WInput
*in
)
1407 copy_region (in
, in
->mark
, in
->point
);
1411 kill_region (WInput
*in
)
1414 delete_region (in
, in
->point
, in
->mark
);
1424 for (p
= kill_buffer
; *p
; p
++)
1425 insert_char (in
, *p
);
1429 kill_line (WInput
*in
)
1432 g_free (kill_buffer
);
1433 kill_buffer
= g_strdup (&in
->buffer
[in
->point
]);
1434 in
->buffer
[in
->point
] = 0;
1438 assign_text (WInput
*in
, char *text
)
1440 free_completions (in
);
1441 g_free (in
->buffer
);
1442 in
->buffer
= g_strdup (text
); /* was in->buffer->text */
1443 in
->current_max_len
= strlen (in
->buffer
) + 1;
1444 in
->point
= strlen (in
->buffer
);
1450 hist_prev (WInput
*in
)
1455 if (in
->need_push
) {
1456 switch (push_history (in
, in
->buffer
)) {
1457 case 2: in
->history
= in
->history
->prev
; break;
1458 case 1: if (in
->history
->prev
) in
->history
= in
->history
->prev
; break;
1461 } else if (in
->history
->prev
)
1462 in
->history
= in
->history
->prev
;
1465 assign_text (in
, in
->history
->text
);
1470 hist_next (WInput
*in
)
1472 if (in
->need_push
) {
1473 switch (push_history (in
, in
->buffer
)) {
1475 assign_text (in
, "");
1485 if (!in
->history
->next
) {
1486 assign_text (in
, "");
1490 in
->history
= in
->history
->next
;
1491 assign_text (in
, in
->history
->text
);
1495 static const struct {
1497 void (*fn
)(WInput
*in
);
1500 { XCTRL('a'), beginning_of_line
},
1501 { KEY_HOME
, beginning_of_line
},
1502 { KEY_A1
, beginning_of_line
},
1503 { XCTRL('e'), end_of_line
},
1504 { KEY_END
, end_of_line
},
1505 { KEY_C1
, end_of_line
},
1506 { KEY_LEFT
, key_left
},
1507 { XCTRL('b'), backward_char
},
1508 { ALT('b'), backward_word
},
1509 { KEY_RIGHT
, key_right
},
1510 { XCTRL('f'), forward_char
},
1511 { ALT('f'), forward_word
},
1514 { 0177, backward_delete
},
1515 { KEY_BACKSPACE
, backward_delete
},
1516 { XCTRL('h'), backward_delete
},
1517 { KEY_DC
, delete_char
},
1518 { XCTRL('d'), delete_char
},
1519 { ALT('d'), kill_word
},
1520 { ALT(KEY_BACKSPACE
), back_kill_word
},
1521 { ALT(XCTRL('h')), back_kill_word
},
1522 { ALT(127), back_kill_word
},
1524 /* Region manipulation */
1526 { XCTRL('w'), kill_region
},
1527 { ALT('w'), kill_save
},
1528 { XCTRL('y'), yank
},
1529 { XCTRL('k'), kill_line
},
1532 { ALT('p'), hist_prev
},
1533 { ALT('n'), hist_next
},
1534 { ALT('h'), do_show_hist
},
1537 { ALT('\t'), complete
},
1542 /* This function is a test for a special input key used in complete.c */
1543 /* Returns 0 if it is not a special key, 1 if it is a non-complete key
1544 and 2 if it is a complete key */
1546 is_in_input_map (WInput
*in
, int c_code
)
1550 for (i
= 0; input_map
[i
].fn
; i
++)
1551 if (c_code
== input_map
[i
].key_code
) {
1552 if (input_map
[i
].fn
== complete
)
1560 #ifdef PORT_WINPUT_DELETES_MARKED
1562 port_region_marked_for_delete (WInput
*in
)
1564 if (in
->first
== 1 && (in
->point
== in
->mark
))
1565 in
->point
= strlen (in
->buffer
);
1571 port_region_marked_for_delete (WInput
*in
)
1580 handle_char (WInput
*in
, int c_code
)
1588 free_completions (in
);
1589 v
= insert_char (in
, c_code
);
1590 update_input (in
, 1);
1595 for (i
= 0; input_map
[i
].fn
; i
++){
1596 if (c_code
== input_map
[i
].key_code
){
1597 if (input_map
[i
].fn
!= complete
)
1598 free_completions (in
);
1599 (*input_map
[i
].fn
)(in
);
1604 if (!input_map
[i
].fn
){
1605 if (c_code
> 255 || !is_printable (c_code
))
1608 port_region_marked_for_delete (in
);
1610 free_completions (in
);
1611 v
= insert_char (in
, c_code
);
1612 in
->inserted_one
= c_code
;
1614 if (!disable_update
)
1615 update_input (in
, 1);
1619 /* Inserts text in input line */
1621 stuff (WInput
*in
, char *text
, int insert_extra_space
)
1623 input_disable_update (in
);
1625 handle_char (in
, *text
++);
1626 if (insert_extra_space
)
1627 handle_char (in
, ' ');
1628 input_enable_update (in
);
1629 update_input (in
, 1);
1633 input_set_point (WInput
*in
, int pos
)
1635 if (pos
> in
->current_max_len
)
1636 pos
= in
->current_max_len
;
1637 if (pos
!= in
->point
)
1638 free_completions (in
);
1640 update_input (in
, 1);
1643 int input_event (Gpm_Event
*event
, WInput
*b
);
1646 input_callback (Dlg_head
*h
, WInput
*in
, int Msg
, int Par
)
1650 return x_create_input (h
, h
->wdata
, in
);
1653 if (Par
== XCTRL('q')){
1657 v
= handle_char (in
, mi_getch ());
1661 if (Par
== KEY_UP
|| Par
== KEY_DOWN
||
1662 Par
== ESC_CHAR
|| Par
== KEY_F(10) ||
1664 return 0; /* We don't handle up/down */
1670 return handle_char (in
, Par
);
1673 case WIDGET_UNFOCUS
:
1675 update_input (in
, 0);
1679 widget_move (&in
->widget
, 0, in
->point
- in
->first_shown
);
1684 return default_proc (h
, Msg
, Par
);
1687 /* Not declared static, since we check against this value in dlg.c */
1688 /* FIXME: Declare static again and provide an identification mechanism */
1690 input_event (Gpm_Event
*event
, WInput
*in
)
1693 if (event
->type
& (GPM_DOWN
|GPM_DRAG
)){
1694 dlg_select_widget (in
->widget
.parent
, in
);
1696 if (event
->x
>= in
->field_len
- HISTORY_BUTTON_WIDTH
+ 1 && should_show_history_button (in
)) {
1699 in
->point
= strlen (in
->buffer
);
1700 if (event
->x
- in
->first_shown
- 1 < in
->point
)
1701 in
->point
= event
->x
- in
->first_shown
- 1;
1705 update_input (in
, 1);
1712 input_new (int y
, int x
, int color
, int len
, const char *def_text
, char *tkname
)
1714 WInput
*in
= g_new (WInput
, 1);
1715 int initial_buffer_len
;
1717 init_widget (&in
->widget
, y
, x
, 1, len
,
1718 (callback_fn
) input_callback
,
1719 (destroy_fn
) input_destroy
, (mouse_h
) input_event
, tkname
);
1723 in
->history_name
= 0;
1724 if (tkname
&& PORT_WIDGET_WANTS_HISTORY
){
1726 in
->history_name
= g_strdup (tkname
);
1727 in
->history
= history_get (tkname
);
1734 if (def_text
== INPUT_LAST_TEXT
) {
1737 if (in
->history
->text
)
1738 def_text
= in
->history
->text
;
1740 initial_buffer_len
= 1 + max (len
, strlen (def_text
));
1741 in
->widget
.options
|= W_IS_INPUT
;
1742 in
->completions
= NULL
;
1743 in
->completion_flags
=
1744 INPUT_COMPLETE_FILENAMES
| INPUT_COMPLETE_HOSTNAMES
|
1745 INPUT_COMPLETE_VARIABLES
| INPUT_COMPLETE_USERNAMES
;
1746 in
->current_max_len
= initial_buffer_len
;
1747 in
->buffer
= g_malloc (initial_buffer_len
);
1749 in
->field_len
= len
;
1751 in
->first_shown
= 0;
1752 in
->disable_update
= 0;
1755 in
->is_password
= 0;
1757 strcpy (in
->buffer
, def_text
);
1758 in
->point
= strlen (in
->buffer
);
1763 /* Listbox widget */
1765 /* Should draw the scrollbar, but currently draws only
1766 * indications that there is more information
1768 static int listbox_cdiff (WLEntry
*s
, WLEntry
*e
);
1772 listbox_draw (WListbox
*l
, Dlg_head
*h
, int focused
)
1778 listbox_drawscroll (WListbox
*l
)
1780 extern int slow_terminal
;
1783 int max_line
= l
->height
-1;
1785 /* Are we at the top? */
1786 widget_move (&l
->widget
, 0, l
->width
);
1787 if (l
->list
== l
->top
)
1792 /* Are we at the bottom? */
1793 widget_move (&l
->widget
, max_line
, l
->width
);
1794 top
= listbox_cdiff (l
->list
, l
->top
);
1795 if ((top
+ l
->height
== l
->count
) || l
->height
>= l
->count
)
1800 /* Now draw the nice relative pointer */
1802 line
= 1+ ((l
->pos
* (l
->height
-2)) / l
->count
);
1806 for (i
= 1; i
< max_line
; i
++){
1807 widget_move (&l
->widget
, i
, l
->width
);
1816 listbox_draw (WListbox
*l
, Dlg_head
*h
, int focused
)
1821 int normalc
= NORMALC
;
1832 for (e
= l
->top
, i
= 0; (i
< l
->height
); i
++){
1834 /* Display the entry */
1835 if (e
== l
->current
&& sel_line
== -1){
1841 widget_move (&l
->widget
, i
, 0);
1843 if ((i
> 0 && e
== l
->list
) || !l
->list
)
1849 printw (" %-*s ", l
->width
-2, name_trunc (text
, l
->width
-2));
1851 l
->cursor_y
= sel_line
;
1855 listbox_drawscroll (l
);
1859 /* Returns the number of items between s and e,
1860 must be on the same linked list */
1862 listbox_cdiff (WLEntry
*s
, WLEntry
*e
)
1866 for (count
= 0; s
!= e
; count
++)
1872 listbox_check_hotkey (WListbox
*l
, int key
)
1884 /* If we didn't find anything, return */
1885 if (i
&& e
== l
->list
)
1888 if (e
->hotkey
== key
)
1896 /* Used only for display updating, for avoiding line at a time scroll */
1898 listbox_select_last (WListbox
*l
, int set_top
)
1901 l
->current
= l
->list
->prev
;
1902 l
->pos
= l
->count
- 1;
1904 l
->top
= l
->list
->prev
;
1905 x_listbox_select_nth (l
, l
->pos
);
1910 listbox_remove_list (WListbox
*l
)
1918 if (l
->widget
.wdata
!= (widget_data
) NULL
) {
1920 for (i
= 0; i
< l
->count
; i
++)
1921 x_listbox_delete_nth (l
, i
);
1926 while (l
->count
--) {
1932 l
->pos
= l
->count
= 0;
1933 l
->list
= l
->top
= l
->current
= 0;
1937 * bor 30.10.96: added force flag to remove *last* entry as well
1938 * bor 30.10.96: corrected selection bug if last entry was removed
1942 listbox_remove_current (WListbox
*l
, int force
)
1946 /* Ok, note: this won't allow for emtpy lists */
1947 if (!force
&& (!l
->count
|| l
->count
== 1))
1951 if (l
->widget
.wdata
!= (widget_data
) NULL
) {
1952 x_listbox_delete_nth (l
, l
->pos
);
1954 if (l
->current
->next
!= l
->list
)
1955 x_listbox_select_nth (l
, l
->pos
);
1956 else if (l
->current
!= l
->list
)
1957 x_listbox_select_nth (l
, l
->pos
- 1);
1959 x_listbox_select_nth (l
, 0);
1966 l
->current
->next
->prev
= l
->current
->prev
;
1967 l
->current
->prev
->next
= l
->current
->next
;
1968 if (p
->next
== l
->list
) {
1969 l
->current
= p
->prev
;
1973 l
->current
= p
->next
;
1976 l
->list
= l
->top
= p
->next
;
1979 l
->list
= l
->top
= l
->current
= 0;
1986 /* Makes *e the selected entry (sets current and pos) */
1988 listbox_select_entry (WListbox
*l
, WLEntry
*dest
)
1997 for (pos
= 0, e
= l
->list
; pos
< l
->count
; e
= e
->next
, pos
++){
2005 while (listbox_cdiff (l
->top
, l
->current
) >= l
->height
)
2006 l
->top
= l
->top
->next
;
2008 l
->top
= l
->current
;
2011 x_listbox_select_nth (l
, l
->pos
);
2015 /* If we are unable to find it, set decent values */
2016 l
->current
= l
->top
= l
->list
;
2018 x_listbox_select_nth (l
, l
->pos
);
2021 /* Selects from base the pos element */
2023 listbox_select_pos (WListbox
*l
, WLEntry
*base
, int pos
)
2025 WLEntry
*last
= l
->list
->prev
;
2038 listbox_back (WListbox
*l
)
2041 listbox_select_entry (l
, listbox_select_pos (l
, l
->list
, l
->pos
-1));
2048 listbox_fwd (WListbox
*l
)
2050 if (l
->current
!= l
->list
->prev
){
2051 listbox_select_entry (l
, listbox_select_pos (l
, l
->list
, l
->pos
+1));
2057 /* Returns 1 if we want a redraw */
2059 listbox_key (WListbox
*l
, int key
)
2070 l
->current
= l
->top
= l
->list
;
2076 l
->current
= l
->top
= l
->list
->prev
;
2077 for (i
= min (l
->height
- 1, l
->count
- 1); i
; i
--)
2078 l
->top
= l
->top
->prev
;
2079 l
->pos
= l
->count
- 1;
2094 for (i
= 0; i
< l
->height
-1; i
++)
2095 j
|= listbox_fwd (l
);
2100 for (i
= 0; i
< l
->height
-1; i
++)
2101 j
|= listbox_back (l
);
2107 static int listbox_event (Gpm_Event
*event
, WListbox
*l
);
2109 listbox_callback (Dlg_head
*h
, WListbox
*l
, int msg
, int par
)
2112 /* int selected_color; Never used */
2117 return x_create_listbox (h
, h
->wdata
, l
);
2120 if ((e
= listbox_check_hotkey (l
, par
)) != NULL
){
2121 listbox_select_entry (l
, e
);
2123 /* Take the appropriate action */
2124 if (l
->action
== listbox_finish
){
2125 l
->widget
.parent
->running
= 0;
2126 l
->widget
.parent
->ret_value
= B_ENTER
;
2127 } else if (l
->action
== listbox_cback
){
2128 if ((*l
->cback
)(l
) == listbox_finish
){
2129 l
->widget
.parent
->running
= 0;
2130 l
->widget
.parent
->ret_value
= B_ENTER
;
2138 if ((ret_code
= listbox_key (l
, par
)))
2139 listbox_draw (l
, h
, 1);
2144 widget_move (&l
->widget
, l
->cursor_y
, 0);
2148 case WIDGET_UNFOCUS
:
2150 listbox_draw (l
, h
, msg
!= WIDGET_UNFOCUS
);
2154 return default_proc (h
, msg
, par
);
2158 listbox_event (Gpm_Event
*event
, WListbox
*l
)
2163 Dlg_head
*h
= l
->widget
.parent
;
2166 if (event
->type
& GPM_DOWN
)
2167 dlg_select_widget (l
->widget
.parent
, l
);
2170 if (event
->type
& (GPM_DOWN
|GPM_DRAG
)){
2171 if (event
->x
< 0 || event
->x
>= l
->width
)
2174 for (i
= -event
->y
; i
>= 0; i
--)
2176 else if (event
->y
> l
->height
)
2177 for (i
= event
->y
- l
->height
; i
> 0; i
--)
2180 listbox_select_entry (l
, listbox_select_pos (l
, l
->top
,
2183 /* We need to refresh ourselves since the dialog manager doesn't */
2184 /* know about this event */
2185 listbox_callback (h
, l
, WIDGET_DRAW
, 0);
2191 if ((event
->type
& (GPM_DOUBLE
|GPM_UP
)) == (GPM_UP
|GPM_DOUBLE
)){
2192 if (event
->x
< 0 || event
->x
>= l
->width
)
2194 if (event
->y
< 1 || event
->y
> l
->height
)
2197 dlg_select_widget (l
->widget
.parent
, l
);
2198 listbox_select_entry (l
, listbox_select_pos (l
, l
->top
, event
->y
- 1));
2201 case listbox_nothing
:
2204 case listbox_finish
:
2205 h
->ret_value
= B_ENTER
;
2210 if ((*l
->cback
)(l
) == listbox_finish
)
2219 listbox_destroy (WListbox
*l
)
2221 WLEntry
*n
, *p
= l
->list
;
2225 for (i
= 0; i
< l
->count
; i
++){
2234 listbox_new (int y
, int x
, int width
, int height
,
2235 int action
, lcback callback
, char *tkname
)
2237 WListbox
*l
= g_new (WListbox
, 1);
2238 extern int slow_terminal
;
2240 init_widget (&l
->widget
, y
, x
, height
, width
,
2241 (callback_fn
)listbox_callback
,
2242 (destroy_fn
) listbox_destroy
, (mouse_h
)listbox_event
, tkname
);
2244 l
->list
= l
->top
= l
->current
= 0;
2254 l
->cback
= callback
;
2256 l
->allow_duplicates
= 1;
2257 l
->scrollbar
= slow_terminal
? 0 : 1;
2258 widget_want_hotkey (l
->widget
, 1);
2263 /* Listbox item adding function. They still lack a lot of functionality */
2265 /* 1.11.96 bor: added pos argument to control placement of new entry */
2267 listbox_append_item (WListbox
*l
, WLEntry
*e
, enum append_pos pos
)
2275 } else if (pos
== LISTBOX_APPEND_AT_END
) {
2277 e
->prev
= l
->list
->prev
;
2278 l
->list
->prev
->next
= e
;
2280 } else if (pos
== LISTBOX_APPEND_BEFORE
){
2281 e
->next
= l
->current
;
2282 e
->prev
= l
->current
->prev
;
2283 l
->current
->prev
->next
= e
;
2284 l
->current
->prev
= e
;
2285 if (l
->list
== l
->current
) { /* move list one position down */
2289 } else if (pos
== LISTBOX_APPEND_AFTER
) {
2290 e
->prev
= l
->current
;
2291 e
->next
= l
->current
->next
;
2292 l
->current
->next
->prev
= e
;
2293 l
->current
->next
= e
;
2295 x_list_insert (l
, l
->list
, e
);
2300 listbox_add_item (WListbox
*l
, enum append_pos pos
, int hotkey
, char *text
,
2308 if (!l
->allow_duplicates
)
2309 if (listbox_search_text (l
, text
))
2312 entry
= g_new (WLEntry
, 1);
2313 entry
->text
= g_strdup (text
);
2315 entry
->hotkey
= hotkey
;
2317 listbox_append_item (l
, entry
, pos
);
2322 /* Selects the nth entry in the listbox */
2324 listbox_select_by_number (WListbox
*l
, int n
)
2326 listbox_select_entry (l
, listbox_select_pos (l
, l
->list
, n
));
2330 listbox_search_text (WListbox
*l
, char *text
)
2339 if(!strcmp (e
->text
, text
))
2342 } while (e
!=l
->list
);
2347 /* Returns the current string text as well as the associated extra data */
2349 listbox_get_current (WListbox
*l
, char **string
, char **extra
)
2355 if (string
&& l
->current
)
2356 *string
= l
->current
->text
;
2357 if (extra
&& l
->current
)
2358 *extra
= l
->current
->data
;
2362 buttonbar_callback (Dlg_head
*h
, WButtonBar
*bb
, int msg
, int par
)
2368 return x_create_buttonbar (h
, h
->wdata
, bb
);
2374 for (i
= 0; i
< 10; i
++){
2375 if (par
== KEY_F(i
+1) && bb
->labels
[i
].function
){
2376 (*bb
->labels
[i
].function
)(bb
->labels
[i
].data
);
2386 widget_move (&bb
->widget
, 0, 0);
2387 attrset (DEFAULT_COLOR
);
2388 printw ("%-*s", bb
->widget
.cols
- 1, "");
2389 for (i
= 0; i
< COLS
/8 && i
< 10; i
++){
2390 widget_move (&bb
->widget
, 0, i
*8);
2391 attrset (DEFAULT_COLOR
);
2393 attrset (SELECTED_COLOR
);
2394 printw ("%-*s", ((i
+1) * 8 == COLS
? 5 : 6),
2395 bb
->labels
[i
].text
? bb
->labels
[i
].text
: "");
2396 attrset (DEFAULT_COLOR
);
2398 attrset (SELECTED_COLOR
);
2402 return default_proc (h
, msg
, par
);
2406 buttonbar_destroy (WButtonBar
*bb
)
2410 for (i
= 0; i
< 10; i
++){
2411 if (bb
->labels
[i
].text
)
2412 g_free (bb
->labels
[i
].text
);
2417 buttonbar_event (Gpm_Event
*event
, WButtonBar
*bb
)
2422 if (!(event
->type
& GPM_UP
))
2426 button
= event
->x
/ 8;
2427 if (button
< 10 && bb
->labels
[button
].function
)
2428 (*bb
->labels
[button
].function
)(bb
->labels
[button
].data
);
2434 buttonbar_new (int visible
)
2437 WButtonBar
*bb
= g_new (WButtonBar
, 1);
2439 init_widget (&bb
->widget
, LINES
-1, 0, 1, COLS
,
2440 (callback_fn
) buttonbar_callback
,
2441 (destroy_fn
) buttonbar_destroy
, (mouse_h
) buttonbar_event
, NULL
);
2443 bb
->visible
= visible
;
2444 for (i
= 0; i
< 10; i
++){
2445 bb
->labels
[i
].text
= 0;
2446 bb
->labels
[i
].function
= 0;
2448 widget_want_hotkey (bb
->widget
, 1);
2449 widget_want_cursor (bb
->widget
, 0);
2455 set_label_text (WButtonBar
*bb
, int index
, char *text
)
2457 if (bb
->labels
[index
-1].text
)
2458 g_free (bb
->labels
[index
-1].text
);
2460 bb
->labels
[index
-1].text
= g_strdup (text
);
2463 /* paneletc is either the panel widget, or info or view or tree widget */
2465 find_buttonbar (Dlg_head
*h
, Widget
*paneletc
)
2472 for (i
= 0, item
= h
->current
; i
< h
->count
; i
++, item
= item
->next
){
2473 if (item
->widget
->callback
== (callback_fn
) buttonbar_callback
){
2474 bb
= (WButtonBar
*) item
->widget
;
2482 define_label_data (Dlg_head
*h
, Widget
*paneletc
, int idx
, char *text
,
2483 buttonbarfn cback
, void *data
)
2485 WButtonBar
*bb
= find_buttonbar (h
, paneletc
);
2489 set_label_text (bb
, idx
, text
);
2490 bb
->labels
[idx
-1].function
= (void (*)(void *)) cback
;
2491 bb
->labels
[idx
-1].data
= data
;
2492 x_redefine_label (bb
, idx
);
2496 define_label (Dlg_head
*h
, Widget
*paneletc
, int idx
, char *text
, void (*cback
)(void))
2498 define_label_data (h
, paneletc
, idx
, text
, (void (*)(void *)) cback
, 0);
2502 void redraw_labels (Dlg_head
*h
, Widget
*paneletc
)
2508 redraw_labels (Dlg_head
*h
, Widget
*paneletc
)
2513 for (i
= 0, item
= h
->current
; i
< h
->count
; i
++, item
= item
->next
){
2514 if (item
->widget
->callback
== (callback_fn
) buttonbar_callback
){
2515 widget_redraw (h
, item
);