2 Widgets for the Midnight Commander
4 Copyright (C) 1994-2020
5 Free Software Foundation, Inc.
8 Radek Doulik, 1994, 1995
9 Miguel de Icaza, 1994, 1995
11 Andrej Borsenkow, 1996
13 Andrew Borodin <aborodin@vmail.ru>, 2009-2019
15 This file is part of the Midnight Commander.
17 The Midnight Commander is free software: you can redistribute it
18 and/or modify it under the terms of the GNU General Public License as
19 published by the Free Software Foundation, either version 3 of the License,
20 or (at your option) any later version.
22 The Midnight Commander is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with this program. If not, see <http://www.gnu.org/licenses/>.
32 * \brief Source: show history
38 #include <sys/types.h>
40 #include "lib/global.h"
42 #include "lib/tty/tty.h" /* LINES, COLS */
43 #include "lib/strutil.h"
44 #include "lib/widget.h"
45 #include "lib/keybind.h" /* CK_* */
47 /*** global variables ****************************************************************************/
49 /*** file scope macro definitions ****************************************************************/
51 #define B_VIEW (B_USER + 1)
52 #define B_EDIT (B_USER + 2)
54 /*** file scope type declarations ****************************************************************/
64 /*** file scope variables ************************************************************************/
66 /*** file scope functions ************************************************************************/
69 history_dlg_reposition (WDialog
* dlg_head
)
71 history_dlg_data
*data
;
75 if ((dlg_head
== NULL
) || (dlg_head
->data
== NULL
))
76 return MSG_NOT_HANDLED
;
78 data
= (history_dlg_data
*) dlg_head
->data
;
83 if (he
<= y
|| y
> (LINES
- 6))
91 he
= MIN (he
, LINES
- y
);
97 wi
= data
->max_width
+ 4;
105 dlg_set_position (dlg_head
, y
, x
, he
, wi
);
110 /* --------------------------------------------------------------------------------------------- */
113 history_dlg_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
, void *data
)
118 return history_dlg_reposition (DIALOG (w
));
122 /* message from listbox */
123 WDialog
*d
= DIALOG (w
);
128 d
->ret_value
= B_VIEW
;
131 d
->ret_value
= B_EDIT
;
134 d
->ret_value
= B_ENTER
;
137 return MSG_NOT_HANDLED
;
145 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
149 /* --------------------------------------------------------------------------------------------- */
152 history_create_item (history_descriptor_t
* hd
, void *data
)
154 char *text
= (char *) data
;
157 width
= str_term_width1 (text
);
158 hd
->max_width
= MAX (width
, hd
->max_width
);
160 listbox_add_item (hd
->listbox
, LISTBOX_APPEND_AT_END
, 0, text
, NULL
, TRUE
);
163 /* --------------------------------------------------------------------------------------------- */
166 history_release_item (history_descriptor_t
* hd
, WLEntry
* le
)
178 /* --------------------------------------------------------------------------------------------- */
179 /*** public functions ****************************************************************************/
180 /* --------------------------------------------------------------------------------------------- */
183 history_descriptor_init (history_descriptor_t
* hd
, int y
, int x
, GList
* history
, int current
)
188 hd
->current
= current
;
189 hd
->action
= CK_IgnoreKey
;
192 hd
->listbox
= listbox_new (1, 1, 2, 2, TRUE
, NULL
);
193 /* in most cases history list contains string only and no any other data */
194 hd
->create
= history_create_item
;
195 hd
->release
= history_release_item
;
199 /* --------------------------------------------------------------------------------------------- */
202 history_show (history_descriptor_t
* hd
)
207 history_dlg_data hist_data
;
210 if (hd
== NULL
|| hd
->list
== NULL
)
213 hd
->max_width
= str_term_width1 (_("History")) + 2;
215 for (z
= hd
->list
; z
!= NULL
; z
= g_list_previous (z
))
216 hd
->create (hd
, z
->data
);
217 /* after this, the order of history items is following: recent at begin, oldest at end */
219 count
= listbox_get_length (hd
->listbox
);
223 hist_data
.count
= count
;
224 hist_data
.max_width
= hd
->max_width
;
227 dlg_create (TRUE
, 0, 0, 4, 4, WPOS_KEEP_DEFAULT
, TRUE
, dialog_colors
, history_dlg_callback
,
228 NULL
, "[History-query]", _("History"));
229 query_dlg
->data
= &hist_data
;
231 /* this call makes list stick to all sides of dialog, effectively make
232 it be resized with dialog */
233 group_add_widget_autopos (GROUP (query_dlg
), hd
->listbox
, WPOS_KEEP_ALL
, NULL
);
235 /* to avoid diplicating of (calculating sizes in two places)
236 code, call history_dlg_callback function here, to set dialog and
238 The main idea - create 4x4 dialog and add 2x2 list in
239 center of it, and let dialog function resize it to needed size. */
240 send_message (query_dlg
, NULL
, MSG_RESIZE
, 0, NULL
);
242 if (WIDGET (query_dlg
)->y
< hd
->y
)
244 /* history is above base widget -- revert order to place recent item at bottom */
245 /* revert history direction */
246 g_queue_reverse (hd
->listbox
->list
);
247 if (hd
->current
< 0 || (size_t) hd
->current
>= count
)
248 listbox_select_last (hd
->listbox
);
250 listbox_select_entry (hd
->listbox
, count
- 1 - (size_t) hd
->current
);
254 /* history is below base widget -- keep order to place recent item on top */
256 listbox_select_entry (hd
->listbox
, hd
->current
);
259 dlg_ret
= dlg_run (query_dlg
);
260 if (dlg_ret
!= B_CANCEL
)
267 hd
->action
= CK_Edit
;
270 hd
->action
= CK_View
;
273 hd
->action
= CK_Enter
;
276 listbox_get_current (hd
->listbox
, &q
, NULL
);
277 hd
->text
= g_strdup (q
);
280 /* get modified history from dialog */
282 for (hi
= listbox_get_first_link (hd
->listbox
); hi
!= NULL
; hi
= g_list_next (hi
))
283 /* history is being reverted here again */
284 z
= g_list_prepend (z
, hd
->release (hd
, LENTRY (hi
->data
)));
286 /* restore history direction */
287 if (WIDGET (query_dlg
)->y
< hd
->y
)
288 z
= g_list_reverse (z
);
290 dlg_destroy (query_dlg
);
292 hd
->list
= g_list_first (hd
->list
);
293 g_list_free_full (hd
->list
, hd
->free
);
294 hd
->list
= g_list_last (z
);
297 /* --------------------------------------------------------------------------------------------- */