2 Widgets for the Midnight Commander
4 Copyright (C) 1994-2024
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-2022
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 /*** forward declarations (file scope functions) *************************************************/
66 /*** file scope variables ************************************************************************/
68 /* --------------------------------------------------------------------------------------------- */
69 /*** file scope functions ************************************************************************/
70 /* --------------------------------------------------------------------------------------------- */
73 history_dlg_reposition (WDialog
* dlg_head
)
75 history_dlg_data
*data
;
80 if (dlg_head
== NULL
|| dlg_head
->data
.p
== NULL
)
81 return MSG_NOT_HANDLED
;
83 data
= (history_dlg_data
*) dlg_head
->data
.p
;
88 if (he
<= y
|| y
> (LINES
- 6))
96 he
= MIN (he
, LINES
- y
);
102 wi
= data
->max_width
+ 4;
110 rect_init (&r
, y
, x
, he
, wi
);
112 return dlg_default_callback (WIDGET (dlg_head
), NULL
, MSG_RESIZE
, 0, &r
);
115 /* --------------------------------------------------------------------------------------------- */
118 history_dlg_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
, void *data
)
123 return history_dlg_reposition (DIALOG (w
));
127 /* message from listbox */
128 WDialog
*d
= DIALOG (w
);
133 d
->ret_value
= B_VIEW
;
136 d
->ret_value
= B_EDIT
;
139 d
->ret_value
= B_ENTER
;
142 return MSG_NOT_HANDLED
;
150 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
154 /* --------------------------------------------------------------------------------------------- */
157 history_create_item (history_descriptor_t
* hd
, void *data
)
159 char *text
= (char *) data
;
162 width
= str_term_width1 (text
);
163 hd
->max_width
= MAX (width
, hd
->max_width
);
165 listbox_add_item (hd
->listbox
, LISTBOX_APPEND_AT_END
, 0, text
, NULL
, TRUE
);
168 /* --------------------------------------------------------------------------------------------- */
171 history_release_item (history_descriptor_t
* hd
, WLEntry
* le
)
183 /* --------------------------------------------------------------------------------------------- */
184 /*** public functions ****************************************************************************/
185 /* --------------------------------------------------------------------------------------------- */
188 history_descriptor_init (history_descriptor_t
* hd
, int y
, int x
, GList
* history
, int current
)
193 hd
->current
= current
;
194 hd
->action
= CK_IgnoreKey
;
197 hd
->listbox
= listbox_new (1, 1, 2, 2, TRUE
, NULL
);
198 /* in most cases history list contains string only and no any other data */
199 hd
->create
= history_create_item
;
200 hd
->release
= history_release_item
;
204 /* --------------------------------------------------------------------------------------------- */
207 history_show (history_descriptor_t
* hd
)
212 history_dlg_data hist_data
;
215 if (hd
== NULL
|| hd
->list
== NULL
)
218 hd
->max_width
= str_term_width1 (_("History")) + 2;
220 for (z
= hd
->list
; z
!= NULL
; z
= g_list_previous (z
))
221 hd
->create (hd
, z
->data
);
222 /* after this, the order of history items is following: recent at begin, oldest at end */
224 count
= listbox_get_length (hd
->listbox
);
228 hist_data
.count
= count
;
229 hist_data
.max_width
= hd
->max_width
;
232 dlg_create (TRUE
, 0, 0, 4, 4, WPOS_KEEP_DEFAULT
, TRUE
, dialog_colors
, history_dlg_callback
,
233 NULL
, "[History-query]", _("History"));
234 query_dlg
->data
.p
= &hist_data
;
236 /* this call makes list stick to all sides of dialog, effectively make
237 it be resized with dialog */
238 group_add_widget_autopos (GROUP (query_dlg
), hd
->listbox
, WPOS_KEEP_ALL
, NULL
);
240 /* to avoid diplicating of (calculating sizes in two places)
241 code, call history_dlg_callback function here, to set dialog and
243 The main idea - create 4x4 dialog and add 2x2 list in
244 center of it, and let dialog function resize it to needed size. */
245 send_message (query_dlg
, NULL
, MSG_RESIZE
, 0, NULL
);
247 if (WIDGET (query_dlg
)->rect
.y
< hd
->y
)
249 /* history is above base widget -- revert order to place recent item at bottom */
250 /* revert history direction */
251 g_queue_reverse (hd
->listbox
->list
);
252 if (hd
->current
< 0 || (size_t) hd
->current
>= count
)
253 listbox_select_last (hd
->listbox
);
255 listbox_set_current (hd
->listbox
, count
- 1 - (size_t) hd
->current
);
259 /* history is below base widget -- keep order to place recent item on top */
261 listbox_set_current (hd
->listbox
, hd
->current
);
264 dlg_ret
= dlg_run (query_dlg
);
265 if (dlg_ret
!= B_CANCEL
)
272 hd
->action
= CK_Edit
;
275 hd
->action
= CK_View
;
278 hd
->action
= CK_Enter
;
281 listbox_get_current (hd
->listbox
, &q
, NULL
);
282 hd
->text
= g_strdup (q
);
285 /* get modified history from dialog */
287 for (hi
= listbox_get_first_link (hd
->listbox
); hi
!= NULL
; hi
= g_list_next (hi
))
288 /* history is being reverted here again */
289 z
= g_list_prepend (z
, hd
->release (hd
, LENTRY (hi
->data
)));
291 /* restore history direction */
292 if (WIDGET (query_dlg
)->rect
.y
< hd
->y
)
293 z
= g_list_reverse (z
);
295 widget_destroy (WIDGET (query_dlg
));
297 hd
->list
= g_list_first (hd
->list
);
298 g_list_free_full (hd
->list
, hd
->free
);
299 hd
->list
= g_list_last (z
);
302 /* --------------------------------------------------------------------------------------------- */