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., 675 Mass Ave, Cambridge, MA 02139, USA.
32 #include <sys/types.h>
44 #include "key.h" /* XCTRL and ALT macros */
46 #include "profile.h" /* for history loading and saving */
49 # define x_create_button(a,b,c) 1
50 # define x_create_radio(a,b,c) 1
51 # define x_create_check(a,b,c) 1
52 # define x_create_label(a,b,c) 1
53 # define x_create_input(a,b,c) 1
54 # define x_create_listbox(a,b,c) 1
55 # define x_create_buttonbar(a,b,c) 1
56 # define x_create_gauge(a,b,c) 1
57 # define x_listbox_select_nth(a,b)
58 # define x_list_insert(a,b,c)
59 # define x_redefine_label(a,b)
62 #ifndef PORT_HAS_DESTROY_CMD
63 # define x_destroy_cmd(w)
66 #ifndef PORT_HAS_RADIO_FOCUS_ITEM
67 # define x_radio_focus_item(r)
70 #ifndef PORT_HAS_RADIO_TOGGLE
71 # define x_radio_toggle
74 static int button_event (Gpm_Event
*event
, WButton
*b
);
79 button_callback (Dlg_head
*h
, WButton
*b
, int Msg
, int Par
)
82 char *txt
, buf
[BUF_SMALL
];
89 return x_create_button (h
, h
->wdata
, b
);
92 if (b
->hotkey
== Par
|| toupper(b
->hotkey
) == Par
){
93 button_callback (h
, b
, WIDGET_KEY
, ' '); /* to make action */
99 if (Par
!= ' ' && Par
!= '\n')
103 stop
= (*b
->callback
)(b
->action
, b
->callback_data
);
104 if (!b
->callback
|| stop
){
105 h
->ret_value
= b
->action
;
126 widget_move (&b
->widget
, 0, b
->hotpos
+ off
);
133 if (Msg
==WIDGET_UNFOCUS
)
135 else if (Msg
==WIDGET_FOCUS
)
140 g_snprintf (buf
, sizeof(buf
), "[< %s >]", b
->text
);
144 g_snprintf (buf
, sizeof(buf
), "[ %s ]", b
->text
);
148 g_snprintf (buf
, sizeof(buf
), "[%s]", b
->text
);
159 attrset ((b
->selected
) ? FOCUSC
: NORMALC
);
160 widget_move (&b
->widget
, 0, 0);
165 attrset ((b
->selected
) ? HOT_FOCUSC
: HOT_NORMALC
);
166 widget_move (&b
->widget
, 0, b
->hotpos
+off
);
167 addch ((unsigned char)b
->text
[b
->hotpos
]);
170 if (Msg
== WIDGET_FOCUS
)
176 return default_proc (h
, Msg
, Par
);
180 button_event (Gpm_Event
*event
, WButton
*b
)
183 if (event
->type
& (GPM_DOWN
|GPM_UP
)){
184 Dlg_head
*h
=b
->widget
.parent
;
185 dlg_select_widget (h
, b
);
186 if (event
->type
& GPM_UP
){
187 button_callback (h
, b
, WIDGET_KEY
, ' ');
188 (*h
->callback
) (h
, ' ', DLG_POST_KEY
);
197 button_destroy (WButton
*b
)
204 button_len (const char *text
, unsigned int flags
)
207 int ret
= strlen (text
);
224 return strlen (text
);
229 * Assuming that button text is malloc'ed, we may safely change it
230 * (as opposed to statically allocated); from other hand, excluding &
231 * and shifting data past it to the left results to one unused byte.
232 * This does not harm though :)
235 button_scan_hotkey(WButton
* b
)
237 char* cp
= strchr (b
->text
, '&');
239 if (cp
!= NULL
&& cp
[1] != '\0'){
241 b
->hotkey
= tolower (*cp
);
242 b
->hotpos
= cp
- b
->text
;
247 button_new (int y
, int x
, int action
, int flags
, char *text
,
248 int (*callback
)(int, void *), void *callback_data
, char *tkname
)
250 WButton
*b
= g_new (WButton
, 1);
252 init_widget (&b
->widget
, y
, x
, 1, button_len (text
, flags
),
253 (callback_fn
) button_callback
,
254 (destroy_fn
) button_destroy
, (mouse_h
)button_event
, tkname
);
259 b
->text
= g_strdup (text
);
260 b
->callback
= callback
;
261 b
->callback_data
= callback_data
;
262 widget_want_hotkey (b
->widget
, 1);
266 button_scan_hotkey(b
);
271 button_set_text (WButton
*b
, char *text
)
274 b
->text
= g_strdup (text
);
275 b
->widget
.cols
= button_len (text
, b
->flags
);
276 button_scan_hotkey(b
);
278 x_button_set (b
, b
->text
);
280 dlg_redraw (b
->widget
.parent
);
285 /* Radio button widget */
286 static int radio_event (Gpm_Event
*event
, WRadio
*r
);
289 radio_callback (Dlg_head
*h
, WRadio
*r
, int Msg
, int Par
)
297 return x_create_radio (h
, h
->wdata
, r
);
301 int i
, lp
= tolower(Par
);
304 for (i
= 0; i
< r
->count
; i
++){
305 cp
= strchr (r
->texts
[i
], '&');
306 if (cp
!= NULL
&& cp
[1] != '\0'){
307 int c
= tolower (cp
[1]);
312 radio_callback (h
, r
, WIDGET_KEY
, ' '); /* Take action */
323 (*h
->callback
) (h
, h
->current
->dlg_id
, DLG_ACTION
);
324 radio_callback (h
, r
, WIDGET_FOCUS
, ' ');
332 x_radio_focus_item (r
);
339 if (r
->count
- 1 > r
->pos
) {
341 x_radio_focus_item (r
);
350 x_radio_focus_item (r
);
356 (*h
->callback
) (h
, h
->current
->dlg_id
, DLG_ACTION
);
357 radio_callback (h
, r
, WIDGET_FOCUS
, ' ');
358 widget_move (&r
->widget
, r
->pos
, 1);
364 for (i
= 0; i
< r
->count
; i
++){
365 register unsigned char* cp
;
366 attrset ((i
==r
->pos
&& Msg
==WIDGET_FOCUS
) ? FOCUSC
:NORMALC
);
367 widget_move (&r
->widget
, i
, 0);
369 printw("(%c) ", (r
->sel
== i
) ? '*' : ' ');
370 for (cp
= r
->texts
[i
]; *cp
; cp
++)
374 attrset ((i
==r
->pos
&& Msg
==WIDGET_FOCUS
)
375 ? HOT_FOCUSC
: HOT_NORMALC
);
377 attrset ((i
==r
->pos
&& Msg
==WIDGET_FOCUS
) ? FOCUSC
: NORMALC
);
387 return default_proc (h
, Msg
, Par
);
391 static void Radio_destroy (WRadio
*r
)
395 # define radio_destroy (destroy_fn) Radio_destroy
397 # define radio_destroy 0
401 radio_event (Gpm_Event
*event
, WRadio
*r
)
404 if (event
->type
& (GPM_DOWN
|GPM_UP
)){
405 Dlg_head
*h
= r
->widget
.parent
;
407 r
->pos
= event
->y
- 1;
408 dlg_select_widget (h
, r
);
409 if (event
->type
& GPM_UP
){
410 radio_callback (h
, r
, WIDGET_KEY
, ' ');
411 radio_callback (h
, r
, WIDGET_FOCUS
, 0);
412 (*h
->callback
) (h
, ' ', DLG_POST_KEY
);
421 radio_new (int y
, int x
, int count
, char **texts
, int use_hotkey
, char *tkname
)
423 WRadio
*r
= g_new (WRadio
, 1);
426 /* Compute the longest string */
428 for (i
= 0; i
< count
; i
++){
429 m
= strlen (texts
[i
]);
434 init_widget (&r
->widget
, y
, x
, count
, max
, (callback_fn
) radio_callback
,
435 radio_destroy
, (mouse_h
) radio_event
, tkname
);
441 r
->upper_letter_is_hotkey
= use_hotkey
;
442 widget_want_hotkey (r
->widget
, 1);
448 /* Checkbutton widget */
450 static int check_event (Gpm_Event
*event
, WCheck
*b
);
453 check_callback (Dlg_head
*h
, WCheck
*c
, int Msg
, int Par
)
457 return x_create_check (h
, h
->wdata
, c
);
460 if (c
->hotkey
==Par
||
461 (c
->hotkey
>='a' && c
->hotkey
<='z' && c
->hotkey
-32==Par
)){
462 check_callback (h
, c
, WIDGET_KEY
, ' '); /* make action */
471 c
->state
^= C_CHANGE
;
472 (*h
->callback
) (h
, h
->current
->dlg_id
, DLG_ACTION
);
473 check_callback (h
, c
, WIDGET_FOCUS
, ' ');
478 widget_move (&c
->widget
, 0, 1);
484 attrset ((Msg
== WIDGET_FOCUS
) ? FOCUSC
: NORMALC
);
485 widget_move (&c
->widget
, 0, 0);
486 printw ("[%c] %s", (c
->state
& C_BOOL
) ? 'x' : ' ', c
->text
);
489 attrset ((Msg
== WIDGET_FOCUS
) ? HOT_FOCUSC
: HOT_NORMALC
);
490 widget_move (&c
->widget
, 0, + c
->hotpos
+4);
491 addch ((unsigned char)c
->text
[c
->hotpos
]);
496 return default_proc (h
, Msg
, Par
);
500 check_event (Gpm_Event
*event
, WCheck
*c
)
503 if (event
->type
& (GPM_DOWN
|GPM_UP
)){
504 Dlg_head
*h
= c
->widget
.parent
;
506 dlg_select_widget (h
, c
);
507 if (event
->type
& GPM_UP
){
508 check_callback (h
, c
, WIDGET_KEY
, ' ');
509 check_callback (h
, c
, WIDGET_FOCUS
, 0);
510 (*h
->callback
) (h
, ' ', DLG_POST_KEY
);
519 check_destroy (WCheck
*c
)
526 check_new (int y
, int x
, int state
, char *text
, char *tkname
)
528 WCheck
*c
= g_new (WCheck
, 1);
531 init_widget (&c
->widget
, y
, x
, 1, strlen (text
),
532 (callback_fn
)check_callback
,
533 (destroy_fn
)check_destroy
, (mouse_h
) check_event
, tkname
);
534 c
->state
= state
? C_BOOL
: 0;
535 c
->text
= g_strdup (text
);
538 widget_want_hotkey (c
->widget
, 1);
540 /* Scan for the hotkey */
541 for (s
= text
, t
= c
->text
; *s
; s
++, t
++){
548 c
->hotkey
= tolower (*s
);
549 c
->hotpos
= t
- c
->text
;
561 label_callback (Dlg_head
*h
, WLabel
*l
, int Msg
, int Par
)
563 if (Msg
== WIDGET_INIT
)
564 return x_create_label (h
, h
->wdata
, l
);
566 /* We don't want to get the focus */
567 if (Msg
== WIDGET_FOCUS
)
570 if (Msg
== WIDGET_DRAW
&& l
->text
){
571 char *p
= l
->text
, *q
, c
= 0;
574 attrset (DEFAULT_COLOR
);
580 q
= strchr (p
, '\n');
585 widget_move (&l
->widget
, y
, 0);
587 xlen
= l
->widget
.cols
- strlen (p
);
589 printw ("%*s", xlen
, " ");
599 return default_proc (h
, Msg
, Par
);
603 label_set_text (WLabel
*label
, char *text
)
605 int newcols
= label
->widget
.cols
;
607 if (label
->text
&& text
&& !strcmp (label
->text
, text
))
608 return; /* Flickering is not nice */
611 g_free (label
->text
);
614 label
->text
= g_strdup (text
);
615 if (label
->auto_adjust_cols
) {
616 newcols
= strlen (text
);
617 if (newcols
> label
->widget
.cols
)
618 label
->widget
.cols
= newcols
;
623 if (label
->widget
.parent
)
625 x_label_set_text (label
, text
);
627 label_callback (label
->widget
.parent
, label
, WIDGET_DRAW
, 0);
629 if (newcols
< label
->widget
.cols
)
630 label
->widget
.cols
= newcols
;
634 label_destroy (WLabel
*l
)
642 label_new (int y
, int x
, char *text
, char *tkname
)
644 WLabel
*l
= g_new (WLabel
, 1);
646 init_widget (&l
->widget
, y
, x
, 1, 1,
647 (callback_fn
) label_callback
,
648 (destroy_fn
) label_destroy
, NULL
, tkname
);
649 l
->text
= text
? g_strdup (text
) : 0;
650 l
->auto_adjust_cols
= 1;
652 widget_want_cursor (l
->widget
, 0);
657 /* Gauge widget (progress indicator) */
658 /* Currently width is hardcoded here for text mode */
662 gauge_callback (Dlg_head
*h
, WGauge
*g
, int Msg
, int Par
)
665 if (Msg
== WIDGET_INIT
)
666 return x_create_gauge (h
, h
->wdata
, g
);
668 /* We don't want to get the focus */
669 if (Msg
== WIDGET_FOCUS
)
673 if (Msg
== WIDGET_DRAW
){
674 widget_move (&g
->widget
, 0, 0);
677 printw ("%*s", gauge_len
, "");
679 long percentage
, columns
;
680 long total
= g
->max
, done
= g
->current
;
682 if (total
<= 0 || done
< 0) {
688 while (total
> 65535) {
692 percentage
= (200 * done
/ total
+ 1) / 2;
693 columns
= (2 * (gauge_len
- 7) * done
/ total
+ 1) / 2;
695 attrset (GAUGE_COLOR
);
696 printw ("%*s", columns
, "");
698 printw ("%*s] %3d%%", gauge_len
- 7 - columns
, "", percentage
);
703 return default_proc (h
, Msg
, Par
);
707 gauge_set_value (WGauge
*g
, int max
, int current
)
709 if (g
->current
== current
&& g
->max
== max
)
710 return; /* Do not flicker */
712 max
= 1; /* I do not like division by zero :) */
714 /* NOTE: x_gauge_set_value has to be called before we change actual
715 * max and current values in g, since it assumes g->max and
716 * g->current as the previous values and max and current
717 * as the new ones :) */
718 x_gauge_set_value (g
, max
, current
);
720 g
->current
= current
;
723 gauge_callback (g
->widget
.parent
, g
, WIDGET_DRAW
, 0);
728 gauge_show (WGauge
*g
, int shown
)
730 if (g
->shown
== shown
)
736 gauge_callback (g
->widget
.parent
, g
, WIDGET_DRAW
, 0);
741 gauge_destroy (WGauge
*g
)
747 gauge_new (int y
, int x
, int shown
, int max
, int current
, char *tkname
)
749 WGauge
*g
= g_new (WGauge
, 1);
751 init_widget (&g
->widget
, y
, x
, 1, gauge_len
,
752 (callback_fn
) gauge_callback
,
753 (destroy_fn
) gauge_destroy
, NULL
, tkname
);
756 max
= 1; /* I do not like division by zero :) */
758 g
->current
= current
;
760 widget_want_cursor (g
->widget
, 0);
767 /* {{{ history button */
769 #define LARGE_HISTORY_BUTTON 1
771 #ifdef LARGE_HISTORY_BUTTON
772 # define HISTORY_BUTTON_WIDTH 3
774 # define HISTORY_BUTTON_WIDTH 1
777 #define should_show_history_button(in) \
778 (in->history && in->field_len > HISTORY_BUTTON_WIDTH * 2 + 1 && in->widget.parent)
781 static void draw_history_button (WInput
* in
)
784 c
= in
->history
->next
? (in
->history
->prev
? '|' : 'v') : '^';
785 widget_move (&in
->widget
, 0, in
->field_len
- HISTORY_BUTTON_WIDTH
);
786 #ifdef LARGE_HISTORY_BUTTON
789 h
= in
->widget
.parent
;
791 attrset (NORMALC
); /* button has the same colour as other buttons */
793 attrset (HOT_NORMALC
);
795 attrset (NORMAL_COLOR
);
797 /* Too distracting: attrset (MARKED_COLOR); */
799 widget_move (&in
->widget
, 0, in
->field_len
- HISTORY_BUTTON_WIDTH
+ 1);
803 attrset (MARKED_COLOR
);
809 /* }}} history button */
812 /* Input widgets now have a global kill ring */
813 /* Pointer to killed data */
814 static char *kill_buffer
= 0;
817 update_input (WInput
*in
, int clear_first
)
824 int buf_len
= strlen (in
->buffer
);
826 if (should_show_history_button (in
))
827 has_history
= HISTORY_BUTTON_WIDTH
;
829 if (in
->disable_update
)
832 /* Make the point visible */
833 if ((in
->point
< in
->first_shown
) ||
834 (in
->point
>= in
->first_shown
+in
->field_len
- has_history
)){
835 in
->first_shown
= in
->point
- (in
->field_len
/ 3);
836 if (in
->first_shown
< 0)
840 /* Adjust the mark */
841 if (in
->mark
> buf_len
)
845 if (clear_first
&& in
->first
)
851 draw_history_button (in
);
855 widget_move (&in
->widget
, 0, 0);
856 for (i
= 0; i
< in
->field_len
- has_history
; i
++)
858 widget_move (&in
->widget
, 0, 0);
860 for (i
= 0, j
= in
->first_shown
; i
< in
->field_len
- has_history
&& in
->buffer
[j
]; i
++){
861 c
= in
->buffer
[j
++];
862 c
= is_printable (c
) ? c
: '.';
867 widget_move (&in
->widget
, 0, in
->point
- in
->first_shown
);
875 winput_set_origin (WInput
*in
, int x
, int field_len
)
878 in
->field_len
= in
->widget
.cols
= field_len
;
879 update_input (in
, 0);
882 /* {{{ history saving and loading */
885 This loads and saves the history of an input line to and from the
886 widget. It is called with the widgets tk name on creation of the
887 widget, and returns the Hist list. It stores histories in the file
888 ~/.mc/history in using the profile code.
890 If def_text is passed as INPUT_LAST_TEXT (to the input_new()
891 function) then input_new assigns the default text to be the last text
892 entered, or "" if not found.
895 int num_history_items_recorded
= 60;
897 Hist
*history_get (char *input_name
)
905 if (!num_history_items_recorded
) /* this is how to disable */
911 profile
= concat_dir_and_file (home_dir
, HISTORY_FILE_NAME
);
913 char key_name
[BUF_TINY
];
914 char this_entry
[BUF_LARGE
];
915 g_snprintf (key_name
, sizeof (key_name
), "%d", i
);
916 GetPrivateProfileString (input_name
, key_name
, "", this_entry
, sizeof (this_entry
), profile
);
919 new = g_new0 (Hist
, 1);
920 new->text
= g_strdup (this_entry
);
921 new->prev
= old
; /* set up list pointers */
927 return new; /* return pointer to last entry in list */
930 #ifdef PORT_WIDGET_WANTS_HISTORY
931 void history_put (char *input_name
, Hist
*h
)
945 if (!num_history_items_recorded
) /* this is how to disable */
948 profile
= concat_dir_and_file (home_dir
, HISTORY_FILE_NAME
);
950 if ((i
= open (profile
, O_CREAT
| O_EXCL
, S_IRUSR
| S_IWUSR
)) != -1)
952 /* Just in case I forgot to strip passwords somewhere -- Norbert */
953 if (chmod (profile
, S_IRUSR
| S_IWUSR
) == -1 && errno
!= ENOENT
)
956 while (h
->next
) /* go to end of list */
959 /* go back 60 places */
960 for (i
= 0; i
< num_history_items_recorded
- 1 && h
->prev
; i
++)
965 profile_clean_section (input_name
, profile
);
967 /* dump histories into profile */
971 /* probably aren't any null entries, but lets be sure */
973 char key_name
[BUF_TINY
];
974 g_snprintf (key_name
, sizeof(key_name
), "%d", i
++);
975 WritePrivateProfileString (input_name
, key_name
, h
->text
, profile
);
983 void history_put (char *input_name
, Hist
*h
)
988 /* }}} history saving and loading */
991 /* {{{ history display */
996 static char *history_title
= NULL
;
998 if (history_title
== NULL
)
999 history_title
= _(" History ");
1000 return history_title
;
1004 history_callback (Dlg_head
* h
, int Par
, int Msg
)
1009 attrset (COLOR_NORMAL
);
1011 draw_box (h
, 0, 0, h
->lines
, h
->cols
);
1012 attrset (COLOR_HOT_NORMAL
);
1013 dlg_move (h
, 0, (h
->cols
- strlen (i18n_htitle())) / 2);
1014 printw (i18n_htitle());
1021 static inline int listbox_fwd (WListbox
*l
);
1023 char *show_hist (Hist
*history
, int widget_x
, int widget_y
)
1026 size_t maxlen
= strlen (i18n_htitle()), i
, count
= 0;
1029 Dlg_head
*query_dlg
;
1030 WListbox
*query_list
;
1036 while (z
->prev
) /* goto first */
1040 if ((i
= strlen (hi
->text
)) > maxlen
)
1048 if (h
<= y
|| y
> LINES
- 6)
1056 h
= min(h
, LINES
- y
);
1063 if ((w
= maxlen
+ 4) + x
> COLS
)
1069 query_dlg
= create_dlg (y
, x
, h
, w
, dialog_colors
, history_callback
,
1070 "[History-query]", "history", DLG_NONE
);
1071 query_list
= listbox_new (1, 1, w
- 2, h
- 2, listbox_finish
, 0, NULL
);
1072 add_widget (query_dlg
, query_list
);
1075 while (hi
) { /* traverse */
1076 listbox_add_item (query_list
, 0, 0, hi
->text
, NULL
);
1079 while (listbox_fwd (query_list
));
1083 while (hi
) { /* traverse backwards */
1084 listbox_add_item (query_list
, 0, 0, hi
->text
, NULL
);
1088 run_dlg (query_dlg
);
1090 if (query_dlg
->ret_value
!= B_CANCEL
) {
1091 listbox_get_current (query_list
, &q
, NULL
);
1095 destroy_dlg (query_dlg
);
1099 static void do_show_hist (WInput
* in
)
1102 r
= show_hist (in
->history
, in
->widget
.x
, in
->widget
.y
);
1104 assign_text (in
, r
);
1109 /* }}} history display */
1112 input_destroy (WInput
*in
)
1115 fprintf (stderr
, "Internal error: null Input *\n");
1121 Hist
*current
, *old
;
1123 if (!in
->is_password
&& PORT_WIDGET_WANTS_HISTORY
) /* don't save passwords ;-) */
1124 history_put (in
->history_name
, in
->history
);
1126 current
= in
->history
;
1127 while (current
->next
)
1128 current
= current
->next
;
1131 current
= current
->prev
;
1137 g_free (in
->buffer
);
1138 free_completions (in
);
1139 if (in
->history_name
)
1140 g_free (in
->history_name
);
1143 static char disable_update
= 0;
1146 input_disable_update (WInput
*in
)
1148 in
->disable_update
++;
1152 input_enable_update (WInput
*in
)
1154 in
->disable_update
--;
1155 update_input (in
, 0);
1158 #define ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
1161 push_history (WInput
*in
, char *text
)
1164 /* input widget where urls with passwords are entered without any
1166 static const char *password_input_fields
[] = {
1167 " Link to a remote machine ",
1169 " SMB link to machine "
1177 for (i
= 0; i
< ELEMENTS(password_input_fields
); i
++)
1178 password_input_fields
[i
] = _(password_input_fields
[i
]);
1181 for (p
= text
; *p
== ' ' || *p
== '\t'; p
++);
1185 while (in
->history
->next
)
1186 in
->history
= in
->history
->next
;
1187 if (!strcmp (in
->history
->text
, text
))
1189 new = g_new (Hist
, 1);
1190 in
->history
->next
= new;
1192 new = g_new (Hist
, 1);
1195 new->prev
= in
->history
;
1196 new->text
= g_strdup (text
);
1197 if (in
->history_name
) {
1198 p
= in
->history_name
+ 3;
1199 for (i
= 0; i
< ELEMENTS(password_input_fields
); i
++)
1200 if (strcmp (p
, password_input_fields
[i
]) == 0)
1202 if (i
< ELEMENTS(password_input_fields
))
1203 strip_password (new->text
, 0);
1205 strip_password (new->text
, 1);
1214 /* Cleans the input line and adds the current text to the history */
1216 new_input (WInput
*in
)
1219 push_history (in
, in
->buffer
);
1224 free_completions (in
);
1225 update_input (in
, 0);
1229 insert_char (WInput
*in
, int c_code
)
1237 if (strlen (in
->buffer
)+1 == in
->current_max_len
){
1238 /* Expand the buffer */
1239 char *narea
= g_malloc (in
->current_max_len
+ in
->field_len
);
1241 char *p
= in
->buffer
;
1243 strcpy (narea
, in
->buffer
);
1245 in
->current_max_len
+= in
->field_len
;
1249 if (strlen (in
->buffer
)+1 < in
->current_max_len
){
1250 int l
= strlen (&in
->buffer
[in
->point
]);
1251 for (i
= l
+1; i
> 0; i
--)
1252 in
->buffer
[in
->point
+i
] = in
->buffer
[in
->point
+i
-1];
1253 in
->buffer
[in
->point
] = c_code
;
1260 beginning_of_line (WInput
*in
)
1266 end_of_line (WInput
*in
)
1268 in
->point
= strlen (in
->buffer
);
1272 backward_char (WInput
*in
)
1279 forward_char (WInput
*in
)
1281 if (in
->buffer
[in
->point
])
1286 forward_word (WInput
*in
)
1288 char *p
= in
->buffer
+in
->point
;
1290 while ((*p
&& isspace (*p
)) || ispunct (*p
))
1292 while (*p
&& isalnum (*p
))
1294 in
->point
= p
- in
->buffer
;
1298 backward_word (WInput
*in
)
1300 char *p
= in
->buffer
+in
->point
;
1302 while (p
-1 > in
->buffer
-1 && (isspace (*(p
-1)) || ispunct (*(p
-1))))
1304 while (p
-1 > in
->buffer
-1 && isalnum (*(p
-1)))
1306 in
->point
= p
- in
->buffer
;
1311 key_left (WInput
*in
)
1313 if (ctrl_pressed ())
1320 key_right (WInput
*in
)
1322 if (ctrl_pressed ())
1328 #define key_left backward_char
1329 #define key_right forward_char
1333 backward_delete (WInput
*in
)
1339 for (i
= in
->point
; in
->buffer
[i
-1]; i
++)
1340 in
->buffer
[i
-1] = in
->buffer
[i
];
1346 delete_char (WInput
*in
)
1350 for (i
= in
->point
; in
->buffer
[i
]; i
++)
1351 in
->buffer
[i
] = in
->buffer
[i
+1];
1356 copy_region (WInput
*in
, int x_first
, int x_last
)
1358 int first
= min (x_first
, x_last
);
1359 int last
= max (x_first
, x_last
);
1365 g_free (kill_buffer
);
1367 kill_buffer
= g_malloc (last
-first
+ 1);
1368 strncpy (kill_buffer
, in
->buffer
+first
, last
-first
);
1369 kill_buffer
[last
-first
] = 0;
1373 delete_region (WInput
*in
, int x_first
, int x_last
)
1375 int first
= min (x_first
, x_last
);
1376 int last
= max (x_first
, x_last
);
1380 strcpy (&in
->buffer
[first
], &in
->buffer
[last
]);
1385 kill_word (WInput
*in
)
1387 int old_point
= in
->point
;
1391 new_point
= in
->point
;
1392 in
->point
= old_point
;
1394 copy_region (in
, old_point
, new_point
);
1395 delete_region (in
, old_point
, new_point
);
1400 back_kill_word (WInput
*in
)
1402 int old_point
= in
->point
;
1406 new_point
= in
->point
;
1407 in
->point
= old_point
;
1409 copy_region (in
, old_point
, new_point
);
1410 delete_region (in
, old_point
, new_point
);
1415 set_mark (WInput
*in
)
1417 in
->mark
= in
->point
;
1421 kill_save (WInput
*in
)
1423 copy_region (in
, in
->mark
, in
->point
);
1427 kill_region (WInput
*in
)
1430 delete_region (in
, in
->point
, in
->mark
);
1440 for (p
= kill_buffer
; *p
; p
++)
1441 insert_char (in
, *p
);
1445 kill_line (WInput
*in
)
1448 g_free (kill_buffer
);
1449 kill_buffer
= g_strdup (&in
->buffer
[in
->point
]);
1450 in
->buffer
[in
->point
] = 0;
1454 assign_text (WInput
*in
, char *text
)
1456 free_completions (in
);
1457 g_free (in
->buffer
);
1458 in
->buffer
= g_strdup (text
); /* was in->buffer->text */
1459 in
->current_max_len
= strlen (in
->buffer
) + 1;
1460 in
->point
= strlen (in
->buffer
);
1466 hist_prev (WInput
*in
)
1471 if (in
->need_push
) {
1472 switch (push_history (in
, in
->buffer
)) {
1473 case 2: in
->history
= in
->history
->prev
; break;
1474 case 1: if (in
->history
->prev
) in
->history
= in
->history
->prev
; break;
1477 } else if (in
->history
->prev
)
1478 in
->history
= in
->history
->prev
;
1481 assign_text (in
, in
->history
->text
);
1486 hist_next (WInput
*in
)
1488 if (in
->need_push
) {
1489 switch (push_history (in
, in
->buffer
)) {
1491 assign_text (in
, "");
1501 if (!in
->history
->next
) {
1502 assign_text (in
, "");
1506 in
->history
= in
->history
->next
;
1507 assign_text (in
, in
->history
->text
);
1513 void (*fn
)(WInput
*in
);
1516 { XCTRL('a'), beginning_of_line
},
1517 { KEY_HOME
, beginning_of_line
},
1518 { KEY_A1
, beginning_of_line
},
1519 { XCTRL('e'), end_of_line
},
1520 { KEY_END
, end_of_line
},
1521 { KEY_C1
, end_of_line
},
1522 { KEY_LEFT
, key_left
},
1523 { XCTRL('b'), backward_char
},
1524 { ALT('b'), backward_word
},
1525 { KEY_RIGHT
, key_right
},
1526 { XCTRL('f'), forward_char
},
1527 { ALT('f'), forward_word
},
1530 { 0177, backward_delete
},
1531 { KEY_BACKSPACE
, backward_delete
},
1532 { XCTRL('h'), backward_delete
},
1533 { KEY_DC
, delete_char
},
1534 { XCTRL('d'), delete_char
},
1535 { ALT('d'), kill_word
},
1536 { ALT(KEY_BACKSPACE
), back_kill_word
},
1537 { ALT(XCTRL('h')), back_kill_word
},
1538 { ALT(127), back_kill_word
},
1540 /* Region manipulation */
1542 { XCTRL('w'), kill_region
},
1543 { ALT('w'), kill_save
},
1544 { XCTRL('y'), yank
},
1545 { XCTRL('k'), kill_line
},
1548 { ALT('p'), hist_prev
},
1549 { ALT('n'), hist_next
},
1550 { ALT('h'), do_show_hist
},
1553 { ALT('\t'), complete
},
1558 /* This function is a test for a special input key used in complete.c */
1559 /* Returns 0 if it is not a special key, 1 if it is a non-complete key
1560 and 2 if it is a complete key */
1562 is_in_input_map (WInput
*in
, int c_code
)
1566 for (i
= 0; input_map
[i
].fn
; i
++)
1567 if (c_code
== input_map
[i
].key_code
) {
1568 if (input_map
[i
].fn
== complete
)
1576 #ifdef PORT_WINPUT_DELETES_MARKED
1578 port_region_marked_for_delete (WInput
*in
)
1580 if (in
->first
== 1 && (in
->point
== in
->mark
))
1581 in
->point
= strlen (in
->buffer
);
1587 port_region_marked_for_delete (WInput
*in
)
1596 handle_char (WInput
*in
, int c_code
)
1604 in
->inserted_one
= 0;
1607 free_completions (in
);
1608 v
= insert_char (in
, c_code
);
1609 update_input (in
, 1);
1614 for (i
= 0; input_map
[i
].fn
; i
++){
1615 if (c_code
== input_map
[i
].key_code
){
1616 if (input_map
[i
].fn
!= complete
)
1617 free_completions (in
);
1618 (*input_map
[i
].fn
)(in
);
1623 if (!input_map
[i
].fn
){
1624 if (c_code
> 255 || !is_printable (c_code
))
1627 port_region_marked_for_delete (in
);
1629 free_completions (in
);
1630 v
= insert_char (in
, c_code
);
1631 in
->inserted_one
= c_code
;
1633 if (!disable_update
)
1634 update_input (in
, 1);
1638 /* Inserts text in input line */
1640 stuff (WInput
*in
, char *text
, int insert_extra_space
)
1642 input_disable_update (in
);
1644 handle_char (in
, *text
++);
1645 if (insert_extra_space
)
1646 handle_char (in
, ' ');
1647 input_enable_update (in
);
1648 update_input (in
, 1);
1652 input_set_point (WInput
*in
, int pos
)
1654 if (pos
> in
->current_max_len
)
1655 pos
= in
->current_max_len
;
1656 if (pos
!= in
->point
)
1657 free_completions (in
);
1659 update_input (in
, 1);
1662 int input_event (Gpm_Event
*event
, WInput
*b
);
1665 input_callback (Dlg_head
*h
, WInput
*in
, int Msg
, int Par
)
1669 return x_create_input (h
, h
->wdata
, in
);
1672 if (Par
== XCTRL('q')){
1676 v
= handle_char (in
, mi_getch ());
1680 if (Par
== KEY_UP
|| Par
== KEY_DOWN
||
1681 Par
== ESC_CHAR
|| Par
== KEY_F(10) ||
1683 return 0; /* We don't handle up/down */
1689 return handle_char (in
, Par
);
1692 case WIDGET_UNFOCUS
:
1694 update_input (in
, 0);
1698 widget_move (&in
->widget
, 0, in
->point
- in
->first_shown
);
1703 return default_proc (h
, Msg
, Par
);
1706 /* Not declared static, since we check against this value in dlg.c */
1707 /* FIXME: Declare static again and provide an identification mechanism */
1709 input_event (Gpm_Event
*event
, WInput
*in
)
1712 if (event
->type
& (GPM_DOWN
|GPM_DRAG
)){
1713 dlg_select_widget (in
->widget
.parent
, in
);
1715 if (event
->x
>= in
->field_len
- HISTORY_BUTTON_WIDTH
+ 1 && should_show_history_button (in
)) {
1717 update_input (in
, 1);
1719 in
->point
= strlen (in
->buffer
);
1720 if (event
->x
- in
->first_shown
- 1 < in
->point
)
1721 in
->point
= event
->x
- in
->first_shown
- 1;
1725 update_input (in
, 1);
1733 input_new (int y
, int x
, int color
, int len
, char *def_text
, char *tkname
)
1735 WInput
*in
= g_new (WInput
, 1);
1736 int initial_buffer_len
;
1738 init_widget (&in
->widget
, y
, x
, 1, len
,
1739 (callback_fn
) input_callback
,
1740 (destroy_fn
) input_destroy
, (mouse_h
) input_event
, tkname
);
1744 in
->history_name
= 0;
1745 if (tkname
&& PORT_WIDGET_WANTS_HISTORY
){
1747 in
->history_name
= g_strdup (tkname
);
1748 in
->history
= history_get (tkname
);
1751 if (def_text
== INPUT_LAST_TEXT
) {
1754 if (in
->history
->text
)
1755 def_text
= in
->history
->text
;
1757 initial_buffer_len
= 1 + max (len
, strlen (def_text
));
1758 in
->widget
.options
|= W_IS_INPUT
;
1759 in
->completions
= NULL
;
1760 in
->completion_flags
=
1761 INPUT_COMPLETE_FILENAMES
| INPUT_COMPLETE_HOSTNAMES
|
1762 INPUT_COMPLETE_VARIABLES
| INPUT_COMPLETE_USERNAMES
;
1763 in
->current_max_len
= initial_buffer_len
;
1764 in
->buffer
= g_malloc (initial_buffer_len
);
1766 in
->field_len
= len
;
1768 in
->first_shown
= 0;
1769 in
->disable_update
= 0;
1772 in
->is_password
= 0;
1774 strcpy (in
->buffer
, def_text
);
1775 in
->point
= strlen (in
->buffer
);
1780 /* Listbox widget */
1782 /* Should draw the scrollbar, but currently draws only
1783 * indications that there is more information
1785 static int listbox_cdiff (WLEntry
*s
, WLEntry
*e
);
1789 listbox_draw (WListbox
*l
, Dlg_head
*h
, int focused
)
1795 listbox_drawscroll (WListbox
*l
)
1797 extern int slow_terminal
;
1800 int max_line
= l
->height
-1;
1802 /* Are we at the top? */
1803 widget_move (&l
->widget
, 0, l
->width
);
1804 if (l
->list
== l
->top
)
1809 /* Are we at the bottom? */
1810 widget_move (&l
->widget
, max_line
, l
->width
);
1811 top
= listbox_cdiff (l
->list
, l
->top
);
1812 if ((top
+ l
->height
== l
->count
) || l
->height
>= l
->count
)
1817 /* Now draw the nice relative pointer */
1819 line
= 1+ ((l
->pos
* (l
->height
-2)) / l
->count
);
1823 for (i
= 1; i
< max_line
; i
++){
1824 widget_move (&l
->widget
, i
, l
->width
);
1833 listbox_draw (WListbox
*l
, Dlg_head
*h
, int focused
)
1850 for (e
= l
->top
, i
= 0; (i
< l
->height
); i
++){
1852 /* Display the entry */
1853 if (e
== l
->current
&& sel_line
== -1){
1859 widget_move (&l
->widget
, i
, 0);
1861 if ((i
> 0 && e
== l
->list
) || !l
->list
)
1867 printw (" %-*s ", l
->width
-2, name_trunc (text
, l
->width
-2));
1869 l
->cursor_y
= sel_line
;
1873 listbox_drawscroll (l
);
1877 /* Returns the number of items between s and e,
1878 must be on the same linked list */
1880 listbox_cdiff (WLEntry
*s
, WLEntry
*e
)
1884 for (count
= 0; s
!= e
; count
++)
1890 listbox_check_hotkey (WListbox
*l
, int key
)
1902 /* If we didn't find anything, return */
1903 if (i
&& e
== l
->list
)
1906 if (e
->hotkey
== key
)
1914 /* Used only for display updating, for avoiding line at a time scroll */
1916 listbox_select_last (WListbox
*l
, int set_top
)
1919 l
->current
= l
->list
->prev
;
1920 l
->pos
= l
->count
- 1;
1922 l
->top
= l
->list
->prev
;
1923 x_listbox_select_nth (l
, l
->pos
);
1928 listbox_remove_list (WListbox
*l
)
1936 if (l
->widget
.wdata
!= (widget_data
) NULL
) {
1938 for (i
= 0; i
< l
->count
; i
++)
1939 x_listbox_delete_nth (l
, i
);
1944 while (l
->count
--) {
1950 l
->pos
= l
->count
= 0;
1951 l
->list
= l
->top
= l
->current
= 0;
1955 * bor 30.10.96: added force flag to remove *last* entry as well
1956 * bor 30.10.96: corrected selection bug if last entry was removed
1960 listbox_remove_current (WListbox
*l
, int force
)
1964 /* Ok, note: this won't allow for emtpy lists */
1965 if (!force
&& (!l
->count
|| l
->count
== 1))
1969 if (l
->widget
.wdata
!= (widget_data
) NULL
) {
1970 x_listbox_delete_nth (l
, l
->pos
);
1972 if (l
->current
->next
!= l
->list
)
1973 x_listbox_select_nth (l
, l
->pos
);
1974 else if (l
->current
!= l
->list
)
1975 x_listbox_select_nth (l
, l
->pos
- 1);
1977 x_listbox_select_nth (l
, 0);
1984 l
->current
->next
->prev
= l
->current
->prev
;
1985 l
->current
->prev
->next
= l
->current
->next
;
1986 if (p
->next
== l
->list
) {
1987 l
->current
= p
->prev
;
1991 l
->current
= p
->next
;
1994 l
->list
= l
->top
= p
->next
;
1997 l
->list
= l
->top
= l
->current
= 0;
2004 /* Makes *e the selected entry (sets current and pos) */
2006 listbox_select_entry (WListbox
*l
, WLEntry
*dest
)
2015 for (pos
= 0, e
= l
->list
; pos
< l
->count
; e
= e
->next
, pos
++){
2023 while (listbox_cdiff (l
->top
, l
->current
) >= l
->height
)
2024 l
->top
= l
->top
->next
;
2026 l
->top
= l
->current
;
2029 x_listbox_select_nth (l
, l
->pos
);
2033 /* If we are unable to find it, set decent values */
2034 l
->current
= l
->top
= l
->list
;
2036 x_listbox_select_nth (l
, l
->pos
);
2039 /* Selects from base the pos element */
2041 listbox_select_pos (WListbox
*l
, WLEntry
*base
, int pos
)
2043 WLEntry
*last
= l
->list
->prev
;
2056 listbox_back (WListbox
*l
)
2059 listbox_select_entry (l
, listbox_select_pos (l
, l
->list
, l
->pos
-1));
2066 listbox_fwd (WListbox
*l
)
2068 if (l
->current
!= l
->list
->prev
){
2069 listbox_select_entry (l
, listbox_select_pos (l
, l
->list
, l
->pos
+1));
2075 /* Returns 1 if we want a redraw */
2077 listbox_key (WListbox
*l
, int key
)
2088 l
->current
= l
->top
= l
->list
;
2094 l
->current
= l
->top
= l
->list
->prev
;
2095 for (i
= min (l
->height
- 1, l
->count
- 1); i
; i
--)
2096 l
->top
= l
->top
->prev
;
2097 l
->pos
= l
->count
- 1;
2112 for (i
= 0; i
< l
->height
-1; i
++)
2113 j
|= listbox_fwd (l
);
2118 for (i
= 0; i
< l
->height
-1; i
++)
2119 j
|= listbox_back (l
);
2125 static int listbox_event (Gpm_Event
*event
, WListbox
*l
);
2127 listbox_callback (Dlg_head
*h
, WListbox
*l
, int msg
, int par
)
2130 /* int selected_color; Never used */
2135 return x_create_listbox (h
, h
->wdata
, l
);
2138 if ((e
= listbox_check_hotkey (l
, par
)) != NULL
){
2139 listbox_select_entry (l
, e
);
2141 /* Take the appropriate action */
2142 if (l
->action
== listbox_finish
){
2143 l
->widget
.parent
->running
= 0;
2144 l
->widget
.parent
->ret_value
= B_ENTER
;
2145 } else if (l
->action
== listbox_cback
){
2146 if ((*l
->cback
)(l
) == listbox_finish
){
2147 l
->widget
.parent
->running
= 0;
2148 l
->widget
.parent
->ret_value
= B_ENTER
;
2156 if ((ret_code
= listbox_key (l
, par
)))
2157 listbox_draw (l
, h
, 1);
2162 widget_move (&l
->widget
, l
->cursor_y
, 0);
2166 case WIDGET_UNFOCUS
:
2168 listbox_draw (l
, h
, msg
!= WIDGET_UNFOCUS
);
2172 return default_proc (h
, msg
, par
);
2176 listbox_event (Gpm_Event
*event
, WListbox
*l
)
2181 Dlg_head
*h
= l
->widget
.parent
;
2184 if (event
->type
& GPM_DOWN
)
2185 dlg_select_widget (l
->widget
.parent
, l
);
2188 if (event
->type
& (GPM_DOWN
|GPM_DRAG
)){
2189 if (event
->x
< 0 || event
->x
>= l
->width
)
2192 for (i
= -event
->y
; i
>= 0; i
--)
2194 else if (event
->y
> l
->height
)
2195 for (i
= event
->y
- l
->height
; i
> 0; i
--)
2198 listbox_select_entry (l
, listbox_select_pos (l
, l
->top
,
2201 /* We need to refresh ourselves since the dialog manager doesn't */
2202 /* know about this event */
2203 listbox_callback (h
, l
, WIDGET_DRAW
, 0);
2209 if ((event
->type
& (GPM_DOUBLE
|GPM_UP
)) == (GPM_UP
|GPM_DOUBLE
)){
2210 if (event
->x
< 0 || event
->x
>= l
->width
)
2212 if (event
->y
< 1 || event
->y
> l
->height
)
2215 dlg_select_widget (l
->widget
.parent
, l
);
2216 listbox_select_entry (l
, listbox_select_pos (l
, l
->top
, event
->y
- 1));
2219 case listbox_nothing
:
2222 case listbox_finish
:
2223 h
->ret_value
= B_ENTER
;
2228 if ((*l
->cback
)(l
) == listbox_finish
)
2237 listbox_destroy (WListbox
*l
)
2239 WLEntry
*n
, *p
= l
->list
;
2243 for (i
= 0; i
< l
->count
; i
++){
2252 listbox_new (int y
, int x
, int width
, int height
,
2253 int action
, lcback callback
, char *tkname
)
2255 WListbox
*l
= g_new (WListbox
, 1);
2256 extern int slow_terminal
;
2258 init_widget (&l
->widget
, y
, x
, height
, width
,
2259 (callback_fn
)listbox_callback
,
2260 (destroy_fn
) listbox_destroy
, (mouse_h
)listbox_event
, tkname
);
2262 l
->list
= l
->top
= l
->current
= 0;
2272 l
->cback
= callback
;
2274 l
->allow_duplicates
= 1;
2275 l
->scrollbar
= slow_terminal
? 0 : 1;
2276 widget_want_hotkey (l
->widget
, 1);
2281 /* Listbox item adding function. They still lack a lot of functionality */
2283 /* 1.11.96 bor: added pos argument to control placement of new entry */
2285 listbox_append_item (WListbox
*l
, WLEntry
*e
, enum append_pos pos
)
2293 } else if (pos
== LISTBOX_APPEND_AT_END
) {
2295 e
->prev
= l
->list
->prev
;
2296 l
->list
->prev
->next
= e
;
2298 } else if (pos
== LISTBOX_APPEND_BEFORE
){
2299 e
->next
= l
->current
;
2300 e
->prev
= l
->current
->prev
;
2301 l
->current
->prev
->next
= e
;
2302 l
->current
->prev
= e
;
2303 if (l
->list
== l
->current
) { /* move list one position down */
2307 } else if (pos
== LISTBOX_APPEND_AFTER
) {
2308 e
->prev
= l
->current
;
2309 e
->next
= l
->current
->next
;
2310 l
->current
->next
->prev
= e
;
2311 l
->current
->next
= e
;
2313 x_list_insert (l
, l
->list
, e
);
2318 listbox_add_item (WListbox
*l
, enum append_pos pos
, int hotkey
, char *text
,
2326 if (!l
->allow_duplicates
)
2327 if (listbox_search_text (l
, text
))
2330 entry
= g_new (WLEntry
, 1);
2331 entry
->text
= g_strdup (text
);
2333 entry
->hotkey
= hotkey
;
2335 listbox_append_item (l
, entry
, pos
);
2340 /* Selects the nth entry in the listbox */
2342 listbox_select_by_number (WListbox
*l
, int n
)
2344 listbox_select_entry (l
, listbox_select_pos (l
, l
->list
, n
));
2348 listbox_search_text (WListbox
*l
, char *text
)
2357 if(!strcmp (e
->text
, text
))
2360 } while (e
!=l
->list
);
2365 /* Returns the current string text as well as the associated extra data */
2367 listbox_get_current (WListbox
*l
, char **string
, char **extra
)
2373 if (string
&& l
->current
)
2374 *string
= l
->current
->text
;
2375 if (extra
&& l
->current
)
2376 *extra
= l
->current
->data
;
2380 buttonbar_callback (Dlg_head
*h
, WButtonBar
*bb
, int msg
, int par
)
2386 return x_create_buttonbar (h
, h
->wdata
, bb
);
2392 for (i
= 0; i
< 10; i
++){
2393 if (par
== KEY_F(i
+1) && bb
->labels
[i
].function
){
2394 (*bb
->labels
[i
].function
)(bb
->labels
[i
].data
);
2404 widget_move (&bb
->widget
, 0, 0);
2405 attrset (DEFAULT_COLOR
);
2406 printw ("%-*s", bb
->widget
.cols
- 1, "");
2407 for (i
= 0; i
< COLS
/8 && i
< 10; i
++){
2408 widget_move (&bb
->widget
, 0, i
*8);
2409 attrset (DEFAULT_COLOR
);
2411 attrset (SELECTED_COLOR
);
2412 printw ("%-*s", ((i
+1) * 8 == COLS
? 5 : 6),
2413 bb
->labels
[i
].text
? bb
->labels
[i
].text
: "");
2414 attrset (DEFAULT_COLOR
);
2416 attrset (SELECTED_COLOR
);
2420 return default_proc (h
, msg
, par
);
2424 buttonbar_destroy (WButtonBar
*bb
)
2428 for (i
= 0; i
< 10; i
++){
2429 if (bb
->labels
[i
].text
)
2430 g_free (bb
->labels
[i
].text
);
2435 buttonbar_event (Gpm_Event
*event
, WButtonBar
*bb
)
2440 if (!(event
->type
& GPM_UP
))
2444 button
= event
->x
/ 8;
2445 if (button
< 10 && bb
->labels
[button
].function
)
2446 (*bb
->labels
[button
].function
)(bb
->labels
[button
].data
);
2452 buttonbar_new (int visible
)
2455 WButtonBar
*bb
= g_new (WButtonBar
, 1);
2457 init_widget (&bb
->widget
, LINES
-1, 0, 1, COLS
,
2458 (callback_fn
) buttonbar_callback
,
2459 (destroy_fn
) buttonbar_destroy
, (mouse_h
) buttonbar_event
, NULL
);
2461 bb
->visible
= visible
;
2462 for (i
= 0; i
< 10; i
++){
2463 bb
->labels
[i
].text
= 0;
2464 bb
->labels
[i
].function
= 0;
2466 widget_want_hotkey (bb
->widget
, 1);
2467 widget_want_cursor (bb
->widget
, 0);
2473 set_label_text (WButtonBar
*bb
, int index
, char *text
)
2475 if (bb
->labels
[index
-1].text
)
2476 g_free (bb
->labels
[index
-1].text
);
2478 bb
->labels
[index
-1].text
= g_strdup (text
);
2481 /* paneletc is either the panel widget, or info or view or tree widget */
2483 find_buttonbar (Dlg_head
*h
, Widget
*paneletc
)
2490 for (i
= 0, item
= h
->current
; i
< h
->count
; i
++, item
= item
->next
){
2491 if (item
->widget
->callback
== (callback_fn
) buttonbar_callback
){
2492 bb
= (WButtonBar
*) item
->widget
;
2500 define_label_data (Dlg_head
*h
, Widget
*paneletc
, int idx
, char *text
,
2501 buttonbarfn cback
, void *data
)
2503 WButtonBar
*bb
= find_buttonbar (h
, paneletc
);
2507 set_label_text (bb
, idx
, text
);
2508 bb
->labels
[idx
-1].function
= (void (*)(void *)) cback
;
2509 bb
->labels
[idx
-1].data
= data
;
2510 x_redefine_label (bb
, idx
);
2514 define_label (Dlg_head
*h
, Widget
*paneletc
, int idx
, char *text
, void (*cback
)(void))
2516 define_label_data (h
, paneletc
, idx
, text
, (void (*)(void *)) cback
, 0);
2520 void redraw_labels (Dlg_head
*h
, Widget
*paneletc
)
2526 redraw_labels (Dlg_head
*h
, Widget
*paneletc
)
2531 for (i
= 0, item
= h
->current
; i
< h
->count
; i
++, item
= item
->next
){
2532 if (item
->widget
->callback
== (callback_fn
) buttonbar_callback
){
2533 widget_redraw (h
, item
);