root/src/diffviewer/search.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. mcdiffview_dialog_search
  2. mcdiffview_do_search_backward
  3. mcdiffview_do_search_forward
  4. mcdiffview_do_search
  5. dview_search_cmd
  6. dview_continue_search_cmd

   1 /*
   2    Search functions for diffviewer.
   3 
   4    Copyright (C) 2010-2025
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Slava Zanko <slavazanko@gmail.com>, 2010.
   9    Andrew Borodin <aborodin@vmail.ru>, 2012-2022
  10 
  11    This file is part of the Midnight Commander.
  12 
  13    The Midnight Commander is free software: you can redistribute it
  14    and/or modify it under the terms of the GNU General Public License as
  15    published by the Free Software Foundation, either version 3 of the License,
  16    or (at your option) any later version.
  17 
  18    The Midnight Commander is distributed in the hope that it will be useful,
  19    but WITHOUT ANY WARRANTY; without even the implied warranty of
  20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21    GNU General Public License for more details.
  22 
  23    You should have received a copy of the GNU General Public License
  24    along with this program.  If not, see <https://www.gnu.org/licenses/>.
  25  */
  26 
  27 #include <config.h>
  28 
  29 #include <stdio.h>
  30 
  31 #include "lib/global.h"
  32 #include "lib/strutil.h"
  33 #include "lib/tty/key.h"
  34 #include "lib/widget.h"
  35 #ifdef HAVE_CHARSET
  36 #    include "lib/charsets.h"
  37 #endif
  38 
  39 #include "src/history.h"
  40 
  41 #include "internal.h"
  42 
  43 /*** global variables ****************************************************************************/
  44 
  45 /*** file scope macro definitions ****************************************************************/
  46 
  47 /*** file scope type declarations ****************************************************************/
  48 
  49 typedef struct mcdiffview_search_options_struct
  50 {
  51     mc_search_type_t type;
  52     gboolean case_sens;
  53     gboolean backwards;
  54     gboolean whole_words;
  55     gboolean all_codepages;
  56 } mcdiffview_search_options_t;
  57 
  58 /*** forward declarations (file scope functions) *************************************************/
  59 
  60 /*** file scope variables ************************************************************************/
  61 
  62 static mcdiffview_search_options_t mcdiffview_search_options = {
  63     .type = MC_SEARCH_T_NORMAL,
  64     .case_sens = FALSE,
  65     .backwards = FALSE,
  66     .whole_words = FALSE,
  67     .all_codepages = FALSE,
  68 };
  69 
  70 /* --------------------------------------------------------------------------------------------- */
  71 /*** file scope functions ************************************************************************/
  72 /* --------------------------------------------------------------------------------------------- */
  73 
  74 static gboolean
  75 mcdiffview_dialog_search (WDiff *dview)
     /* [previous][next][first][last][top][bottom][index][help]  */
  76 {
  77     char *exp = NULL;
  78     int qd_result;
  79     size_t num_of_types = 0;
  80     gchar **list_of_types;
  81 
  82     list_of_types = mc_search_get_types_strings_array (&num_of_types);
  83 
  84     {
  85         quick_widget_t quick_widgets[] = {
  86             // clang-format off
  87             QUICK_LABELED_INPUT (N_ ("Enter search string:"), input_label_above, INPUT_LAST_TEXT,
  88                                  MC_HISTORY_SHARED_SEARCH, &exp, NULL, FALSE, FALSE,
  89                                  INPUT_COMPLETE_NONE),
  90             QUICK_SEPARATOR (TRUE),
  91             QUICK_START_COLUMNS,
  92                 QUICK_RADIO (num_of_types, (const char **) list_of_types,
  93                              (int *) &mcdiffview_search_options.type, NULL),
  94             QUICK_NEXT_COLUMN,
  95                 QUICK_CHECKBOX (N_ ("Cas&e sensitive"), &mcdiffview_search_options.case_sens, NULL),
  96                 QUICK_CHECKBOX (N_ ("&Backwards"), &mcdiffview_search_options.backwards, NULL),
  97                 QUICK_CHECKBOX (N_ ("&Whole words"), &mcdiffview_search_options.whole_words, NULL),
  98 #ifdef HAVE_CHARSET
  99                 QUICK_CHECKBOX (N_ ("&All charsets"), &mcdiffview_search_options.all_codepages,
 100                                 NULL),
 101 #endif
 102             QUICK_STOP_COLUMNS,
 103             QUICK_BUTTONS_OK_CANCEL,
 104             QUICK_END,
 105             // clang-format on
 106         };
 107 
 108         WRect r = { -1, -1, 0, 58 };
 109 
 110         quick_dialog_t qdlg = {
 111             .rect = r,
 112             .title = N_ ("Search"),
 113             .help = "[Input Line Keys]",
 114             .widgets = quick_widgets,
 115             .callback = NULL,
 116             .mouse_callback = NULL,
 117         };
 118 
 119         qd_result = quick_dialog (&qdlg);
 120     }
 121 
 122     g_strfreev (list_of_types);
 123 
 124     if (qd_result == B_CANCEL || exp[0] == '\0')
 125     {
 126         g_free (exp);
 127         return FALSE;
 128     }
 129 
 130 #ifdef HAVE_CHARSET
 131     {
 132         GString *tmp;
 133 
 134         tmp = str_convert_to_input (exp);
 135         g_free (exp);
 136         if (tmp != NULL)
 137             exp = g_string_free (tmp, FALSE);
 138         else
 139             exp = g_strdup ("");
 140     }
 141 #endif
 142 
 143     g_free (dview->search.last_string);
 144     dview->search.last_string = exp;
 145 
 146     return TRUE;
 147 }
 148 
 149 /* --------------------------------------------------------------------------------------------- */
 150 
 151 static gboolean
 152 mcdiffview_do_search_backward (WDiff *dview)
     /* [previous][next][first][last][top][bottom][index][help]  */
 153 {
 154     ssize_t ind;
 155 
 156     if (dview->search.last_accessed_num_line < 0)
 157     {
 158         dview->search.last_accessed_num_line = -1;
 159         return FALSE;
 160     }
 161 
 162     if ((size_t) dview->search.last_accessed_num_line >= dview->a[dview->ord]->len)
 163         dview->search.last_accessed_num_line = (ssize_t) dview->a[dview->ord]->len;
 164 
 165     for (ind = --dview->search.last_accessed_num_line; ind >= 0; ind--)
 166     {
 167         DIFFLN *p;
 168 
 169         p = (DIFFLN *) &g_array_index (dview->a[dview->ord], DIFFLN, (size_t) ind);
 170         if (p->u.len == 0)
 171             continue;
 172 
 173         if (mc_search_run (dview->search.handle, p->p, 0, p->u.len, NULL))
 174         {
 175             dview->skip_rows = dview->search.last_found_line =
 176                 dview->search.last_accessed_num_line = ind;
 177             return TRUE;
 178         }
 179     }
 180     return FALSE;
 181 }
 182 
 183 /* --------------------------------------------------------------------------------------------- */
 184 
 185 static gboolean
 186 mcdiffview_do_search_forward (WDiff *dview)
     /* [previous][next][first][last][top][bottom][index][help]  */
 187 {
 188     size_t ind;
 189 
 190     if (dview->search.last_accessed_num_line < 0)
 191         dview->search.last_accessed_num_line = -1;
 192     else if ((size_t) dview->search.last_accessed_num_line >= dview->a[dview->ord]->len)
 193     {
 194         dview->search.last_accessed_num_line = (ssize_t) dview->a[dview->ord]->len;
 195         return FALSE;
 196     }
 197 
 198     for (ind = (size_t) ++dview->search.last_accessed_num_line; ind < dview->a[dview->ord]->len;
 199          ind++)
 200     {
 201         DIFFLN *p;
 202 
 203         p = (DIFFLN *) &g_array_index (dview->a[dview->ord], DIFFLN, ind);
 204         if (p->u.len == 0)
 205             continue;
 206 
 207         if (mc_search_run (dview->search.handle, p->p, 0, p->u.len, NULL))
 208         {
 209             dview->skip_rows = dview->search.last_found_line =
 210                 dview->search.last_accessed_num_line = (ssize_t) ind;
 211             return TRUE;
 212         }
 213     }
 214     return FALSE;
 215 }
 216 
 217 /* --------------------------------------------------------------------------------------------- */
 218 
 219 static void
 220 mcdiffview_do_search (WDiff *dview)
     /* [previous][next][first][last][top][bottom][index][help]  */
 221 {
 222     gboolean present_result = FALSE;
 223 
 224     tty_enable_interrupt_key ();
 225 
 226     if (mcdiffview_search_options.backwards)
 227     {
 228         present_result = mcdiffview_do_search_backward (dview);
 229     }
 230     else
 231     {
 232         present_result = mcdiffview_do_search_forward (dview);
 233     }
 234 
 235     tty_disable_interrupt_key ();
 236 
 237     if (!present_result)
 238     {
 239         dview->search.last_found_line = -1;
 240         query_dialog (_ ("Search"), _ (STR_E_NOTFOUND), D_NORMAL, 1, _ ("&Dismiss"));
 241     }
 242 }
 243 
 244 /* --------------------------------------------------------------------------------------------- */
 245 /*** public functions ****************************************************************************/
 246 /* --------------------------------------------------------------------------------------------- */
 247 
 248 void
 249 dview_search_cmd (WDiff *dview)
     /* [previous][next][first][last][top][bottom][index][help]  */
 250 {
 251     if (dview->dsrc != DATA_SRC_MEM)
 252     {
 253         error_dialog (_ ("Search"), _ ("Search is disabled"));
 254         return;
 255     }
 256 
 257     if (!mcdiffview_dialog_search (dview))
 258         return;
 259 
 260     mc_search_free (dview->search.handle);
 261 #ifdef HAVE_CHARSET
 262     dview->search.handle = mc_search_new (dview->search.last_string, cp_source);
 263 #else
 264     dview->search.handle = mc_search_new (dview->search.last_string, NULL);
 265 #endif
 266 
 267     if (dview->search.handle == NULL)
 268         return;
 269 
 270     dview->search.handle->search_type = mcdiffview_search_options.type;
 271 #ifdef HAVE_CHARSET
 272     dview->search.handle->is_all_charsets = mcdiffview_search_options.all_codepages;
 273 #endif
 274     dview->search.handle->is_case_sensitive = mcdiffview_search_options.case_sens;
 275     dview->search.handle->whole_words = mcdiffview_search_options.whole_words;
 276 
 277     mcdiffview_do_search (dview);
 278 }
 279 
 280 /* --------------------------------------------------------------------------------------------- */
 281 
 282 void
 283 dview_continue_search_cmd (WDiff *dview)
     /* [previous][next][first][last][top][bottom][index][help]  */
 284 {
 285     if (dview->dsrc != DATA_SRC_MEM)
 286         error_dialog (_ ("Search"), _ ("Search is disabled"));
 287     else if (dview->search.handle == NULL)
 288         dview_search_cmd (dview);
 289     else
 290         mcdiffview_do_search (dview);
 291 }
 292 
 293 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */