]> git.eshelyaron.com Git - emacs.git/commitdiff
Add functions for performing searches on xwidgets
authorPo Lu <luangruo@yahoo.com>
Sat, 6 Nov 2021 07:07:09 +0000 (15:07 +0800)
committerLars Ingebrigtsen <larsi@gnus.org>
Sun, 7 Nov 2021 01:59:41 +0000 (02:59 +0100)
* etc/NEWS:
* doc/lispref/display.texi: Document changes.

* src/xwidget.c (Fxwidget_webkit_search)
(Fxwidget_webkit_next_result)
(Fxwidget_webkit_previous_result)
(Fxwidget_wenkit_finish_search): New functions.

(syms_of_xwidget): Define new built-ins.
(kill_buffer_xwidgets): Free search query if present.
* src/xwidget.h (struct xwidget): Add field for search query.

doc/lispref/display.texi
etc/NEWS
src/xwidget.c
src/xwidget.h

index 2fb89d76b41e68aabf96a7187087c875a61bc87f..b780263fe00d443f34d2c6d0b96782c5b24e0dfe 100644 (file)
@@ -6896,6 +6896,46 @@ through Lisp code, and as such shouldn't require this function to be
 sent.
 @end defun
 
+@defun xwidget-webkit-search query xwidget &optional case-insensitive backwards wrap-around
+Start an incremental search on the WebKit widget @var{xwidget} with
+the string @var{query} as a query.  @var{case-insensitive} denotes
+whether or not the search is case-insensitive, @var{backwards}
+determines if the search is performed backwards towards the start of
+the document, and @var{wrap-around} determines whether or not the
+search terminates at the end of the document.
+
+If the function is called while a search query is already present,
+then the query specified here will replace the existing query.
+
+To stop a search query, use @code{xwidget-webkit-finish-search}.
+@end defun
+
+@defun xwidget-webkit-next-result xwidget
+Display the next search result in @var{xwidget}.  This function will
+error unless a search query has already been started in @var{xwidget}
+through @code{xwidget-webkit-search}.
+
+If @code{wrap-around} was non-nil when @code{xwidget-webkit-search}
+was called, then the search will restart from the beginning of the
+document if the end is reached.
+@end defun
+
+@defun xwidget-webkit-previous-result xwidget
+Display the previous search result in @var{xwidget}.  This function
+will error unless a search query has already been started in
+@var{xwidget} through @code{xwidget-webkit-search}.
+
+If @code{wrap-around} was non-nil when @code{xwidget-webkit-search}
+was called, then the search will restart from the end of the
+document if the beginning is reached.
+@end defun
+
+@defun xwidget-webkit-finish-search xwidget
+Finish a search operation started with @code{xwidget-webkit-search} in
+@var{xwidget}.  If there is no query currently ongoing, then this
+function will error.
+@end defun
+
 @node Buttons
 @section Buttons
 @cindex buttons in buffers
index 9a660edee8d32d02c5ba5b85ba7571ff3f8f558d..f5295ddbdd92b6b6ceebf244336994f04932c729 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -740,6 +740,11 @@ what the widget will actually receive.
 
 On GTK+, only key and function key events are implemented.
 
++++
+** New functions for performing searches on WebKit xwidgets.
+Some new functions, such as `xwidget-webkit-search', have been added
+for performing searches on WebKit xwidgets.
+
 +++
 ** `load-changed' xwidget events are now more detailed.
 In particular, they can now have different arguments based on the
index 36e8cab08da73010d8375739ea1c09677b18a0ee..10bb4ac8e450aed840d9992ff7c402388f9f1170 100644 (file)
@@ -142,6 +142,7 @@ Returns the newly constructed xwidget, or nil if construction fails.  */)
   xw->widgetwindow_osr = NULL;
   xw->widget_osr = NULL;
   xw->hit_result = 0;
+  xw->find_text = NULL;
   if (EQ (xw->type, Qwebkit))
     {
       block_input ();
@@ -1759,6 +1760,166 @@ DEFUN ("xwidget-query-on-exit-flag",
   return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt);
 }
 
+DEFUN ("xwidget-webkit-search", Fxwidget_webkit_search, Sxwidget_webkit_search,
+       2, 5, 0,
+       doc: /* Begin an incremental search operation in an xwidget.
+QUERY should be a string containing the text to search for.  XWIDGET
+should be a WebKit xwidget where the search will take place.  When the
+search operation is complete, callers should also call
+`xwidget-webkit-finish-search' to complete the search operation.
+
+CASE-INSENSITIVE, when non-nil, will cause the search to ignore the
+case of characters inside QUERY.  BACKWARDS, when non-nil, will cause
+the search to proceed towards the beginning of the widget's contents.
+WRAP-AROUND, when nil, will cause the search to stop upon hitting the
+end of the widget's contents.
+
+It is OK to call this function even when a search is already in
+progress.  In that case, the previous search query will be replaced
+with QUERY.  */)
+  (Lisp_Object query, Lisp_Object xwidget, Lisp_Object case_insensitive,
+   Lisp_Object backwards, Lisp_Object wrap_around)
+{
+#ifdef USE_GTK
+  WebKitWebView *webview;
+  WebKitFindController *controller;
+  WebKitFindOptions opt;
+  struct xwidget *xw;
+  gchar *g_query;
+#endif
+
+  CHECK_STRING (query);
+  CHECK_XWIDGET (xwidget);
+
+#ifdef USE_GTK
+  xw = XXWIDGET (xwidget);
+  webview = WEBKIT_WEB_VIEW (xw->widget_osr);
+  query = ENCODE_UTF_8 (query);
+  opt = WEBKIT_FIND_OPTIONS_NONE;
+  g_query = xstrdup (SSDATA (query));
+
+  if (!NILP (case_insensitive))
+    opt |= WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE;
+  if (!NILP (backwards))
+    opt |= WEBKIT_FIND_OPTIONS_BACKWARDS;
+  if (!NILP (wrap_around))
+    opt |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+
+  if (xw->find_text)
+    xfree (xw->find_text);
+  xw->find_text = g_query;
+
+  block_input ();
+  controller = webkit_web_view_get_find_controller (webview);
+  webkit_find_controller_search (controller, g_query, opt, G_MAXUINT);
+  unblock_input ();
+#endif
+
+  return Qnil;
+}
+
+DEFUN ("xwidget-webkit-next-result", Fxwidget_webkit_next_result,
+       Sxwidget_webkit_next_result, 1, 1, 0,
+       doc: /* Show the next result matching the current search query.
+
+XWIDGET should be an xwidget that currently has a search query.
+Before calling this function, you should start a search operation
+using `xwidget-webkit-search'.  */)
+  (Lisp_Object xwidget)
+{
+  struct xwidget *xw;
+#ifdef USE_GTK
+  WebKitWebView *webview;
+  WebKitFindController *controller;
+#endif
+
+  CHECK_XWIDGET (xwidget);
+  xw = XXWIDGET (xwidget);
+
+  if (!xw->find_text)
+    error ("Widget has no ongoing search operation");
+
+#ifdef USE_GTK
+  block_input ();
+  webview = WEBKIT_WEB_VIEW (xw->widget_osr);
+  controller = webkit_web_view_get_find_controller (webview);
+  webkit_find_controller_search_next (controller);
+  unblock_input ();
+#endif
+
+  return Qnil;
+}
+
+DEFUN ("xwidget-webkit-previous-result", Fxwidget_webkit_previous_result,
+       Sxwidget_webkit_previous_result, 1, 1, 0,
+       doc: /* Show the previous result matching the current search query.
+
+XWIDGET should be an xwidget that currently has a search query.
+Before calling this function, you should start a search operation
+using `xwidget-webkit-search'.  */)
+  (Lisp_Object xwidget)
+{
+  struct xwidget *xw;
+#ifdef USE_GTK
+  WebKitWebView *webview;
+  WebKitFindController *controller;
+#endif
+
+  CHECK_XWIDGET (xwidget);
+  xw = XXWIDGET (xwidget);
+
+  if (!xw->find_text)
+    error ("Widget has no ongoing search operation");
+
+#ifdef USE_GTK
+  block_input ();
+  webview = WEBKIT_WEB_VIEW (xw->widget_osr);
+  controller = webkit_web_view_get_find_controller (webview);
+  webkit_find_controller_search_previous (controller);
+
+  if (xw->find_text)
+    {
+      xfree (xw->find_text);
+      xw->find_text = NULL;
+    }
+  unblock_input ();
+#endif
+
+  return Qnil;
+}
+
+DEFUN ("xwidget-webkit-finish-search", Fxwidget_webkit_finish_search,
+       Sxwidget_webkit_finish_search, 1, 1, 0,
+       doc: /* Finish XWIDGET's search operation.
+
+XWIDGET should be an xwidget that currently has a search query.
+Before calling this function, you should start a search operation
+using `xwidget-webkit-search'.  */)
+  (Lisp_Object xwidget)
+{
+  struct xwidget *xw;
+#ifdef USE_GTK
+  WebKitWebView *webview;
+  WebKitFindController *controller;
+#endif
+
+  CHECK_XWIDGET (xwidget);
+  xw = XXWIDGET (xwidget);
+
+  if (!xw->find_text)
+    error ("Widget has no ongoing search operation");
+
+#ifdef USE_GTK
+  block_input ();
+  webview = WEBKIT_WEB_VIEW (xw->widget_osr);
+  controller = webkit_web_view_get_find_controller (webview);
+  webkit_find_controller_search_finish (controller);
+  unblock_input ();
+#endif
+
+  return Qnil;
+}
+
 void
 syms_of_xwidget (void)
 {
@@ -1792,6 +1953,10 @@ syms_of_xwidget (void)
   defsubr (&Sxwidget_buffer);
   defsubr (&Sset_xwidget_plist);
   defsubr (&Sxwidget_perform_lispy_event);
+  defsubr (&Sxwidget_webkit_search);
+  defsubr (&Sxwidget_webkit_finish_search);
+  defsubr (&Sxwidget_webkit_next_result);
+  defsubr (&Sxwidget_webkit_previous_result);
 
   DEFSYM (QCxwidget, ":xwidget");
   DEFSYM (QCtitle, ":title");
@@ -2050,6 +2215,8 @@ kill_buffer_xwidgets (Lisp_Object buffer)
             gtk_widget_destroy (xw->widget_osr);
             gtk_widget_destroy (xw->widgetwindow_osr);
           }
+       if (xw->find_text)
+         xfree (xw->find_text);
        if (!NILP (xw->script_callbacks))
          for (ptrdiff_t idx = 0; idx < ASIZE (xw->script_callbacks); idx++)
            {
index 8b3aef58d01b16b14f93bcf1f77e9544cee4c40c..3bab6d5b00282d6bcbe7a7924133387ebb48947c 100644 (file)
@@ -68,6 +68,7 @@ struct xwidget
   GtkWidget *widget_osr;
   GtkWidget *widgetwindow_osr;
   guint hit_result;
+  gchar *find_text;
 #elif defined (NS_IMPL_COCOA)
 # ifdef __OBJC__
   /* For offscreen widgets, unused if not osr.  */