Ticket #1911: use system realapth(3) function if available.
[midnight-commander.git] / src / viewer / search.c
blob1b4624af97d0c19b13e2d22092f260727025baaf
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 "lib/global.h"
41 #include "src/setup.h"
42 #include "src/wtools.h"
43 #include "lib/tty/tty.h"
44 #include "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)
83 search_end = mcview_get_filesize (view);
84 while ((int) search_start >= 0)
86 view->search_nroff_seq->index = search_start;
87 mcview_nroff_seq_info (view->search_nroff_seq);
89 if (search_end > search_start + view->search->original_len
90 && mc_search_is_fixed_search_str (view->search))
91 search_end = search_start + view->search->original_len;
93 if (mc_search_run (view->search, (void *) view, search_start, search_end, len)
94 && view->search->normal_offset == search_start)
95 return TRUE;
97 search_start--;
99 view->search->error_str = g_strdup (_(" Search string not found "));
100 return FALSE;
102 view->search_nroff_seq->index = search_start;
103 mcview_nroff_seq_info (view->search_nroff_seq);
105 return mc_search_run (view->search, (void *) view, search_start, mcview_get_filesize (view),
106 len);
109 /* --------------------------------------------------------------------------------------------- */
111 static void
112 mcview_search_show_result (mcview_t * view, Dlg_head ** d, size_t match_len)
115 view->search_start = view->search->normal_offset +
116 mcview__get_nroff_real_len (view,
117 view->search->start_buffer,
118 view->search->normal_offset - view->search->start_buffer);
120 if (!view->hex_mode)
121 view->search_start++;
123 view->search_end = view->search_start + match_len +
124 mcview__get_nroff_real_len (view, view->search_start - 1, match_len);
126 if (view->hex_mode)
128 view->hex_cursor = view->search_start;
129 view->hexedit_lownibble = FALSE;
130 view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
131 view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
134 if (verbose)
136 dlg_run_done (*d);
137 destroy_dlg (*d);
138 *d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
139 tty_refresh ();
141 mcview_moveto_match (view);
145 /* --------------------------------------------------------------------------------------------- */
147 /*** public functions ****************************************************************************/
149 /* --------------------------------------------------------------------------------------------- */
152 mcview_search_cmd_callback (const void *user_data, gsize char_offset)
154 int lc_byte;
155 mcview_t *view = (mcview_t *) user_data;
157 /* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
158 if (!view->text_nroff_mode)
160 if (!mcview_get_byte (view, char_offset, &lc_byte))
161 return MC_SEARCH_CB_INVALID;
163 return lc_byte;
166 if (view->search_numNeedSkipChar)
168 view->search_numNeedSkipChar--;
169 return MC_SEARCH_CB_SKIP;
172 lc_byte = view->search_nroff_seq->current_char;
174 if (lc_byte == -1)
175 return MC_SEARCH_CB_INVALID;
177 mcview_nroff_seq_next (view->search_nroff_seq);
179 if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
180 view->search_numNeedSkipChar = 2;
182 return lc_byte;
185 /* --------------------------------------------------------------------------------------------- */
188 mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
190 mcview_t *view = (mcview_t *) user_data;
192 if (char_offset >= view->update_activate)
194 view->update_activate += view->update_steps;
195 if (verbose)
197 mcview_percent (view, char_offset);
198 tty_refresh ();
200 if (tty_got_interrupt ())
201 return MC_SEARCH_CB_ABORT;
203 /* may be in future return from this callback will change current position
204 * in searching block. Now this just constant return value.
206 return MC_SEARCH_CB_OK;
209 /* --------------------------------------------------------------------------------------------- */
211 void
212 mcview_do_search (mcview_t * view)
214 off_t search_start, growbufsize;
215 gboolean isFound = FALSE;
217 Dlg_head *d = NULL;
219 size_t match_len;
221 if (verbose)
223 d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
224 tty_refresh ();
227 /*for avoid infinite search loop we need to increase or decrease start offset of search */
229 if (view->search_start)
231 search_start = (view->search_backwards) ? -2 : 2;
232 search_start = view->search_start + search_start +
233 mcview__get_nroff_real_len (view, view->search_start, 2) * search_start;
235 else
237 search_start = view->search_start;
240 if (view->search_backwards && (int) search_start < 0)
241 search_start = 0;
243 /* Compute the percent steps */
244 mcview_search_update_steps (view);
245 view->update_activate = 0;
247 tty_enable_interrupt_key ();
251 if (view->growbuf_in_use)
252 growbufsize = mcview_growbuf_filesize (view);
253 else
254 growbufsize = view->search->original_len;
256 if (!mcview_find (view, search_start, &match_len))
259 if (view->search->error_str == NULL)
260 break;
262 search_start = growbufsize - view->search->original_len;
263 if (search_start < 0)
264 search_start = 0;
266 continue;
269 mcview_search_show_result (view, &d, match_len);
270 isFound = TRUE;
271 break;
273 while (mcview_may_still_grow (view));
275 if (!isFound && view->search->error_str != NULL && mcview_find (view, search_start, &match_len))
277 mcview_search_show_result (view, &d, match_len);
278 isFound = TRUE;
281 if (!isFound)
283 if (view->search->error_str)
284 message (D_NORMAL, _("Search"), "%s", view->search->error_str);
287 view->dirty++;
288 mcview_update (view);
290 tty_disable_interrupt_key ();
291 if (verbose)
293 dlg_run_done (d);
294 destroy_dlg (d);
299 /* --------------------------------------------------------------------------------------------- */