Search in plain text (not nroff'ed) now worked.
[midnight-commander.git] / src / viewer / search.c
blobc5c237af037b71cc627bcaaf866bf889366a3f2b
1 /*
2 Internal file viewer for the Midnight Commander
3 Function for search data
5 Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003,
6 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
8 Written by: 1994, 1995, 1998 Miguel de Icaza
9 1994, 1995 Janne Kukonlehto
10 1995 Jakub Jelinek
11 1996 Joseph M. Hinkle
12 1997 Norbert Warmuth
13 1998 Pavel Machek
14 2004 Roland Illig <roland.illig@gmx.de>
15 2005 Roland Illig <roland.illig@gmx.de>
16 2009 Slava Zanko <slavazanko@google.com>
17 2009 Andrew Borodin <aborodin@vmail.ru>
18 2009 Ilia Maslakov <il.smind@gmail.com>
20 This file is part of the Midnight Commander.
22 The Midnight Commander is free software; you can redistribute it
23 and/or modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2 of the
25 License, or (at your option) any later version.
27 The Midnight Commander is distributed in the hope that it will be
28 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
29 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
35 MA 02110-1301, USA.
38 #include <config.h>
40 #include "../src/global.h"
41 #include "../src/setup.h"
42 #include "../src/wtools.h"
43 #include "../src/tty/tty.h"
44 #include "../src/viewer/internal.h"
46 /*** global variables ****************************************************************************/
48 /*** file scope macro definitions ****************************************************************/
50 /*** file scope type declarations ****************************************************************/
52 /*** file scope variables ************************************************************************/
54 /*** file scope functions ************************************************************************/
57 /* --------------------------------------------------------------------------------------------- */
58 static void
59 mcview_search_update_steps (mcview_t * view)
61 off_t filesize = mcview_get_filesize (view);
62 if (filesize != 0)
63 view->update_steps = 40000;
64 else /* viewing a data stream, not a file */
65 view->update_steps = filesize / 100;
67 /* Do not update the percent display but every 20 ks */
68 if (view->update_steps < 20000)
69 view->update_steps = 20000;
72 /* --------------------------------------------------------------------------------------------- */
74 static gboolean
75 mcview_find (mcview_t * view, gsize search_start, gsize * len)
77 gsize search_end;
79 view->search_numNeedSkipChar = 0;
81 if (view->search_backwards) {
82 search_end = mcview_get_filesize (view);
83 while ((int) search_start >= 0) {
84 if (search_end > search_start + view->search->original_len
85 && mc_search_is_fixed_search_str (view->search))
86 search_end = search_start + view->search->original_len;
88 if (mc_search_run (view->search, (void *) view, search_start, search_end, len)
89 && view->search->normal_offset == search_start)
90 return TRUE;
92 search_start--;
94 view->search->error_str = g_strdup (_(" Search string not found "));
95 return FALSE;
97 return mc_search_run (view->search, (void *) view, search_start, mcview_get_filesize (view),
98 len);
101 /* --------------------------------------------------------------------------------------------- */
103 /*** public functions ****************************************************************************/
105 /* --------------------------------------------------------------------------------------------- */
108 mcview_search_cmd_callback (const void *user_data, gsize char_offset)
110 int byte;
111 mcview_t *view = (mcview_t *) user_data;
113 byte = mcview_get_byte (view, char_offset);
114 if (byte == -1)
115 return MC_SEARCH_CB_ABORT;
116 /* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
118 if (view->search_numNeedSkipChar) {
119 view->search_numNeedSkipChar--;
120 if (view->search_numNeedSkipChar) {
121 return byte;
123 return MC_SEARCH_CB_SKIP;
125 #if 0 /* AB:FIXME */
126 if (view_read_test_nroff_back (view, &view->search_onechar_info)) {
127 if (cmp (view->search_onechar_info.chi1, "_") && (!cmp (view->search_onechar_info.cnxt, "_")
128 || !cmp (view->search_onechar_info.chi2,
129 "\b"))
131 view->search_numNeedSkipChar = 2;
132 else
133 view->search_numNeedSkipChar = 1;
135 return MC_SEARCH_CB_SKIP;
137 if (byte == '_' && *view->search_onechar_info.cnxt == 0x8) {
138 view->search_numNeedSkipChar = 1;
139 return MC_SEARCH_CB_SKIP;
141 #endif
143 return byte;
146 /* --------------------------------------------------------------------------------------------- */
149 mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
151 mcview_t *view = (mcview_t *) user_data;
153 if (char_offset >= view->update_activate) {
154 view->update_activate += view->update_steps;
155 if (verbose) {
156 mcview_percent (view, char_offset);
157 tty_refresh ();
159 if (tty_got_interrupt ())
160 return MC_SEARCH_CB_ABORT;
162 /* may be in future return from this callback will change current position
163 * in searching block. Now this just constant return value.
165 return 1;
168 /* --------------------------------------------------------------------------------------------- */
170 void
171 mcview_do_search (mcview_t * view)
173 off_t search_start;
174 gboolean isFound = FALSE;
176 Dlg_head *d = NULL;
178 size_t match_len;
180 if (verbose) {
181 d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
182 tty_refresh ();
185 /*for avoid infinite search loop we need to increase or decrease start offset of search */
187 if (view->search_start) {
188 search_start = (view->search_backwards) ? -2 : 2;
189 search_start = view->search_start + search_start +
190 mcview__get_nroff_real_len (view, view->search_start, 2) * search_start;
191 } else {
192 search_start = view->search_start;
195 if (view->search_backwards && (int) search_start < 0)
196 search_start = 0;
198 /* Compute the percent steps */
199 mcview_search_update_steps (view);
200 view->update_activate = 0;
202 tty_enable_interrupt_key ();
204 do {
205 if (mcview_find (view, search_start, &match_len)) {
206 view->search_start = view->search->normal_offset + 1 +
207 mcview__get_nroff_real_len (view,
208 view->search->start_buffer,
209 view->search->normal_offset -
210 view->search->start_buffer);
212 view->search_end = view->search_start + match_len +
213 mcview__get_nroff_real_len (view, view->search_start, match_len + 1);
215 if (view->hex_mode) {
216 view->hex_cursor = view->search_start;
217 view->hexedit_lownibble = FALSE;
218 view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
219 view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
222 if (verbose) {
223 dlg_run_done (d);
224 destroy_dlg (d);
225 d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
226 tty_refresh ();
229 mcview_moveto_match (view);
230 isFound = TRUE;
231 break;
233 } while (mcview_may_still_grow (view));
235 if (!isFound) {
236 if (view->search->error_str)
237 message (D_NORMAL, _("Search"), "%s", view->search->error_str);
240 view->dirty++;
241 mcview_update (view);
244 tty_disable_interrupt_key ();
245 if (verbose) {
246 dlg_run_done (d);
247 destroy_dlg (d);
252 /* --------------------------------------------------------------------------------------------- */