search.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. Search functions for diffviewer.
  3. Copyright (C) 2010, 2011
  4. The Free Software Foundation, Inc.
  5. Written by:
  6. Slava Zanko <slavazanko@gmail.com>, 2010.
  7. This file is part of the Midnight Commander.
  8. The Midnight Commander is free software: you can redistribute it
  9. and/or modify it under the terms of the GNU General Public License as
  10. published by the Free Software Foundation, either version 3 of the License,
  11. or (at your option) any later version.
  12. The Midnight Commander is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <config.h>
  20. #include <stdio.h>
  21. #include "lib/global.h"
  22. #include "lib/strutil.h"
  23. #include "lib/tty/key.h"
  24. #include "lib/widget.h"
  25. #include "lib/charsets.h"
  26. #include "src/history.h"
  27. #include "internal.h"
  28. /*** global variables ****************************************************************************/
  29. /*** file scope macro definitions ****************************************************************/
  30. #define SEARCH_DLG_WIDTH 58
  31. #define SEARCH_DLG_HEIGHT 13
  32. /*** file scope type declarations ****************************************************************/
  33. typedef struct mcdiffview_search_options_struct
  34. {
  35. mc_search_type_t type;
  36. gboolean case_sens;
  37. gboolean backwards;
  38. gboolean whole_words;
  39. gboolean all_codepages;
  40. } mcdiffview_search_options_t;
  41. /*** file scope variables ************************************************************************/
  42. static mcdiffview_search_options_t mcdiffview_search_options = {
  43. .type = MC_SEARCH_T_NORMAL,
  44. .case_sens = FALSE,
  45. .backwards = FALSE,
  46. .whole_words = FALSE,
  47. .all_codepages = FALSE,
  48. };
  49. /*** file scope functions ************************************************************************/
  50. /* --------------------------------------------------------------------------------------------- */
  51. #define DLG_BTN1_text N_("&Cancel")
  52. #define DLG_BTN2_text N_("&OK")
  53. static void
  54. mcdiffview_dialog_fix_buttons_positions (QuickDialog * dlg)
  55. {
  56. size_t str_cancel_len, str_ok_len;
  57. size_t first_start_position;
  58. str_cancel_len = str_term_width1 (_(DLG_BTN1_text)) + 4;
  59. str_ok_len = str_term_width1 (_(DLG_BTN2_text)) + 6;
  60. first_start_position = (SEARCH_DLG_WIDTH - str_cancel_len - str_ok_len - 1) / 2;
  61. dlg->widgets[1].relative_x = first_start_position;
  62. dlg->widgets[0].relative_x = first_start_position + str_ok_len + 1;
  63. }
  64. /* --------------------------------------------------------------------------------------------- */
  65. static gboolean
  66. mcdiffview_dialog_search (WDiff * dview)
  67. {
  68. char *exp = NULL;
  69. int qd_result;
  70. size_t num_of_types;
  71. gchar **list_of_types = mc_search_get_types_strings_array (&num_of_types);
  72. QuickWidget search_widgets[] = {
  73. /* 0 */
  74. QUICK_BUTTON (3, SEARCH_DLG_WIDTH, SEARCH_DLG_HEIGHT - 3, SEARCH_DLG_HEIGHT, DLG_BTN1_text,
  75. B_CANCEL, NULL),
  76. /* 1 */
  77. QUICK_BUTTON (3, SEARCH_DLG_WIDTH, SEARCH_DLG_HEIGHT - 3, SEARCH_DLG_HEIGHT, DLG_BTN2_text,
  78. B_ENTER, NULL),
  79. /* 2 */
  80. #ifdef HAVE_CHARSET
  81. QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 8, SEARCH_DLG_HEIGHT, N_("&All charsets"),
  82. &mcdiffview_search_options.all_codepages),
  83. #endif
  84. QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 7, SEARCH_DLG_HEIGHT, N_("&Whole words"),
  85. &mcdiffview_search_options.whole_words),
  86. /* 3 */
  87. QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 6, SEARCH_DLG_HEIGHT, N_("&Backwards"),
  88. &mcdiffview_search_options.backwards),
  89. /* 4 */
  90. QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 5, SEARCH_DLG_HEIGHT, N_("Cas&e sensitive"),
  91. &mcdiffview_search_options.case_sens),
  92. /* 5 */
  93. QUICK_RADIO (3, SEARCH_DLG_WIDTH, 5, SEARCH_DLG_HEIGHT,
  94. num_of_types, (const char **) list_of_types,
  95. (int *) &mcdiffview_search_options.type),
  96. /* 6 */
  97. QUICK_INPUT (3, SEARCH_DLG_WIDTH, 3, SEARCH_DLG_HEIGHT,
  98. INPUT_LAST_TEXT, SEARCH_DLG_WIDTH - 6, 0,
  99. MC_HISTORY_SHARED_SEARCH,
  100. &exp),
  101. /* 7 */
  102. QUICK_LABEL (3, SEARCH_DLG_WIDTH, 2, SEARCH_DLG_HEIGHT, N_("Enter search string:")),
  103. QUICK_END
  104. };
  105. QuickDialog search_input = {
  106. SEARCH_DLG_WIDTH, SEARCH_DLG_HEIGHT, -1, -1,
  107. N_("Search"), "[Input Line Keys]",
  108. search_widgets, NULL, FALSE
  109. };
  110. mcdiffview_dialog_fix_buttons_positions (&search_input);
  111. qd_result = quick_dialog (&search_input);
  112. g_strfreev (list_of_types);
  113. if ((qd_result == B_CANCEL) || (exp == NULL) || (exp[0] == '\0'))
  114. {
  115. g_free (exp);
  116. return FALSE;
  117. }
  118. #ifdef HAVE_CHARSET
  119. {
  120. GString *tmp = str_convert_to_input (exp);
  121. if (tmp)
  122. {
  123. g_free (exp);
  124. exp = g_string_free (tmp, FALSE);
  125. }
  126. }
  127. #endif
  128. g_free (dview->search.last_string);
  129. dview->search.last_string = exp;
  130. return TRUE;
  131. }
  132. /* --------------------------------------------------------------------------------------------- */
  133. static gboolean
  134. mcdiffview_do_search_backward (WDiff * dview)
  135. {
  136. ssize_t ind;
  137. DIFFLN *p;
  138. if (dview->search.last_accessed_num_line < 0)
  139. {
  140. dview->search.last_accessed_num_line = -1;
  141. return FALSE;
  142. }
  143. if ((size_t) dview->search.last_accessed_num_line >= dview->a[dview->ord]->len)
  144. dview->search.last_accessed_num_line = (ssize_t) dview->a[dview->ord]->len;
  145. for (ind = --dview->search.last_accessed_num_line; ind >= 0; ind--)
  146. {
  147. p = (DIFFLN *) & g_array_index (dview->a[dview->ord], DIFFLN, (size_t) ind);
  148. if (p->u.len == 0)
  149. continue;
  150. if (mc_search_run (dview->search.handle, p->p, 0, p->u.len, NULL))
  151. {
  152. dview->skip_rows = dview->search.last_found_line =
  153. dview->search.last_accessed_num_line = ind;
  154. return TRUE;
  155. }
  156. }
  157. return FALSE;
  158. }
  159. /* --------------------------------------------------------------------------------------------- */
  160. static gboolean
  161. mcdiffview_do_search_forward (WDiff * dview)
  162. {
  163. size_t ind;
  164. DIFFLN *p;
  165. if (dview->search.last_accessed_num_line < 0)
  166. dview->search.last_accessed_num_line = -1;
  167. else if ((size_t) dview->search.last_accessed_num_line >= dview->a[dview->ord]->len)
  168. {
  169. dview->search.last_accessed_num_line = (ssize_t) dview->a[dview->ord]->len;
  170. return FALSE;
  171. }
  172. for (ind = (size_t)++ dview->search.last_accessed_num_line; ind < dview->a[dview->ord]->len;
  173. ind++)
  174. {
  175. p = (DIFFLN *) & g_array_index (dview->a[dview->ord], DIFFLN, ind);
  176. if (p->u.len == 0)
  177. continue;
  178. if (mc_search_run (dview->search.handle, p->p, 0, p->u.len, NULL))
  179. {
  180. dview->skip_rows = dview->search.last_found_line =
  181. dview->search.last_accessed_num_line = (ssize_t) ind;
  182. return TRUE;
  183. }
  184. }
  185. return FALSE;
  186. }
  187. /* --------------------------------------------------------------------------------------------- */
  188. static void
  189. mcdiffview_do_search (WDiff * dview)
  190. {
  191. gboolean present_result = FALSE;
  192. tty_enable_interrupt_key ();
  193. if (mcdiffview_search_options.backwards)
  194. {
  195. present_result = mcdiffview_do_search_backward (dview);
  196. }
  197. else
  198. {
  199. present_result = mcdiffview_do_search_forward (dview);
  200. }
  201. tty_disable_interrupt_key ();
  202. if (!present_result)
  203. {
  204. dview->search.last_found_line = -1;
  205. error_dialog (_("Search"), _("Search string not found"));
  206. }
  207. }
  208. /* --------------------------------------------------------------------------------------------- */
  209. /*** public functions ****************************************************************************/
  210. /* --------------------------------------------------------------------------------------------- */
  211. void
  212. dview_search_cmd (WDiff * dview)
  213. {
  214. if (dview->dsrc != DATA_SRC_MEM)
  215. {
  216. error_dialog (_("Search"), _("Search is disabled"));
  217. return;
  218. }
  219. if (!mcdiffview_dialog_search (dview))
  220. return;
  221. mc_search_free (dview->search.handle);
  222. dview->search.handle = mc_search_new (dview->search.last_string, -1);
  223. if (dview->search.handle == NULL)
  224. return;
  225. dview->search.handle->search_type = mcdiffview_search_options.type;
  226. dview->search.handle->is_all_charsets = mcdiffview_search_options.all_codepages;
  227. dview->search.handle->is_case_sensitive = mcdiffview_search_options.case_sens;
  228. dview->search.handle->whole_words = mcdiffview_search_options.whole_words;
  229. mcdiffview_do_search (dview);
  230. }
  231. /* --------------------------------------------------------------------------------------------- */
  232. void
  233. dview_continue_search_cmd (WDiff * dview)
  234. {
  235. if (dview->dsrc != DATA_SRC_MEM)
  236. error_dialog (_("Search"), _("Search is disabled"));
  237. else if (dview->search.handle == NULL)
  238. dview_search_cmd (dview);
  239. else
  240. mcdiffview_do_search (dview);
  241. }
  242. /* --------------------------------------------------------------------------------------------- */