emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 9510e8ad68 2/2: Check in new files


From: Po Lu
Subject: master 9510e8ad68 2/2: Check in new files
Date: Sun, 12 Feb 2023 06:56:52 -0500 (EST)

branch: master
commit 9510e8ad68271f58b4813478703a4b8eb1ba597b
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Check in new files
    
    * src/textconv.c (copy_buffer):
    (textconv_query):
    (report_selected_window_change):
    (register_texconv_interface):
    * src/textconv.h (struct textconv_interface):
    (enum textconv_caret_direction):
    (enum textconv_operation):
    (struct textconv_conversion_text):
    (struct textconv_callback_struct): New files.
---
 src/textconv.c | 312 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/textconv.h | 109 ++++++++++++++++++++
 2 files changed, 421 insertions(+)

diff --git a/src/textconv.c b/src/textconv.c
new file mode 100644
index 0000000000..e91e127b71
--- /dev/null
+++ b/src/textconv.c
@@ -0,0 +1,312 @@
+/* String conversion support for graphics terminals.
+
+Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* String conversion support.
+
+   Many input methods require access to text surrounding the cursor.
+   They may then request that the text editor remove or substitute
+   that text for something else, for example when providing the
+   ability to ``undo'' or ``edit'' previously composed text.  This is
+   most commonly seen in input methods for CJK laguages for X Windows,
+   and is extensively used throughout Android by input methods for all
+   kinds of scripts.  */
+
+#include <config.h>
+
+#include "textconv.h"
+#include "buffer.h"
+#include "syntax.h"
+
+
+
+/* The window system's text conversion interface.
+   NULL when the window system has not set up text conversion.
+
+   This interface will later be heavily extended on the
+   feature/android branch to deal with Android's much less
+   straightforward text conversion protocols.  */
+
+static struct textconv_interface *text_interface;
+
+
+
+/* Copy the portion of the current buffer described by BEG, BEG_BYTE,
+   END, END_BYTE to the buffer BUFFER, which is END_BYTE - BEG_BYTEs
+   long.  */
+
+static void
+copy_buffer (ptrdiff_t beg, ptrdiff_t beg_byte,
+            ptrdiff_t end, ptrdiff_t end_byte,
+            char *buffer)
+{
+  ptrdiff_t beg0, end0, beg1, end1, size;
+
+  if (beg_byte < GPT_BYTE && GPT_BYTE < end_byte)
+    {
+      /* Two regions, before and after the gap.  */
+      beg0 = beg_byte;
+      end0 = GPT_BYTE;
+      beg1 = GPT_BYTE + GAP_SIZE - BEG_BYTE;
+      end1 = end_byte + GAP_SIZE - BEG_BYTE;
+    }
+  else
+    {
+      /* The only region.  */
+      beg0 = beg_byte;
+      end0 = end_byte;
+      beg1 = -1;
+      end1 = -1;
+    }
+
+  size = end0 - beg0;
+  memcpy (buffer, BYTE_POS_ADDR (beg0), size);
+  if (beg1 != -1)
+    memcpy (buffer, BEG_ADDR + beg1, end1 - beg1);
+}
+
+
+
+/* Conversion query.  */
+
+/* Perform the text conversion operation specified in QUERY and return
+   the results.
+
+   Find the text between QUERY->position from point on F's selected
+   window and QUERY->factor times QUERY->direction from that
+   position.  Return it in QUERY->text.
+
+   Then, either delete that text from the buffer if QUERY->operation
+   is TEXTCONV_SUBSTITUTION, or return 0.
+
+   Value is 0 if QUERY->operation was not TEXTCONV_SUBSTITUTION
+   or if deleting the text was successful, and 1 otherwise.  */
+
+int
+textconv_query (struct frame *f, struct textconv_callback_struct *query)
+{
+  specpdl_ref count;
+  ptrdiff_t pos, pos_byte, end, end_byte;
+  ptrdiff_t temp, temp1;
+  char *buffer;
+
+  /* Save the excursion, as there will be extensive changes to the
+     selected window.  */
+  count = SPECPDL_INDEX ();
+  record_unwind_protect_excursion ();
+
+  /* Inhibit quitting.  */
+  specbind (Qinhibit_quit, Qt);
+
+  /* Temporarily switch to F's selected window.  */
+  Fselect_window (f->selected_window, Qt);
+
+  /* Now find the appropriate text bounds for QUERY.  First, move
+     point QUERY->position steps forward or backwards.  */
+
+  pos = PT;
+
+  /* If pos is outside the accessible part of the buffer or if it
+     overflows, move back to point or to the extremes of the
+     accessible region.  */
+
+  if (INT_ADD_WRAPV (pos, query->position, &pos))
+    pos = PT;
+
+  if (pos < BEGV)
+    pos = BEGV;
+
+  if (pos > ZV)
+    pos = ZV;
+
+  /* Move to pos.  */
+  set_point (pos);
+  pos = PT;
+  pos_byte = PT_BYTE;
+
+  /* Now scan forward or backwards according to what is in QUERY.  */
+
+  switch (query->direction)
+    {
+    case TEXTCONV_FORWARD_CHAR:
+      /* Move forward by query->factor characters.  */
+      if (INT_ADD_WRAPV (pos, query->factor, &end) || end > ZV)
+       end = ZV;
+
+      end_byte = CHAR_TO_BYTE (end);
+      break;
+
+    case TEXTCONV_BACKWARD_CHAR:
+      /* Move backward by query->factor characters.  */
+      if (INT_SUBTRACT_WRAPV (pos, query->factor, &end) || end < BEGV)
+       end = BEGV;
+
+      end_byte = CHAR_TO_BYTE (end);
+      break;
+
+    case TEXTCONV_FORWARD_WORD:
+      /* Move forward by query->factor word.  */
+      end = scan_words (pos, (EMACS_INT) query->factor);
+
+      if (!end)
+       {
+         end = ZV;
+         end_byte = ZV_BYTE;
+       }
+      else
+       end_byte = CHAR_TO_BYTE (end);
+
+      break;
+
+    case TEXTCONV_BACKWARD_WORD:
+      /* Move backwards by query->factor word.  */
+      end = scan_words (pos, 0 - (EMACS_INT) query->factor);
+
+      if (!end)
+       {
+         end = BEGV;
+         end_byte = BEGV_BYTE;
+       }
+      else
+       end_byte = CHAR_TO_BYTE (end);
+
+      break;
+
+    case TEXTCONV_CARET_UP:
+      /* Move upwards one visual line, keeping the column intact.  */
+      Fvertical_motion (Fcons (Fcurrent_column (), make_fixnum (-1)),
+                       Qnil, Qnil);
+      end = PT;
+      end_byte = PT_BYTE;
+      break;
+
+    case TEXTCONV_CARET_DOWN:
+      /* Move downwards one visual line, keeping the column
+        intact.  */
+      Fvertical_motion (Fcons (Fcurrent_column (), make_fixnum (1)),
+                       Qnil, Qnil);
+      end = PT;
+      end_byte = PT_BYTE;
+      break;
+
+    case TEXTCONV_NEXT_LINE:
+      /* Move one line forward.  */
+      scan_newline (pos, pos_byte, ZV, ZV_BYTE,
+                   query->factor, false);
+      end = PT;
+      end_byte = PT_BYTE;
+      break;
+
+    case TEXTCONV_PREVIOUS_LINE:
+      /* Move one line backwards.  */
+      scan_newline (pos, pos_byte, BEGV, BEGV_BYTE,
+                   0 - (EMACS_INT) query->factor, false);
+      end = PT;
+      end_byte = PT_BYTE;
+      break;
+
+    case TEXTCONV_LINE_START:
+      /* Move to the beginning of the line.  */
+      Fbeginning_of_line (Qnil);
+      end = PT;
+      end_byte = PT_BYTE;
+      break;
+
+    case TEXTCONV_LINE_END:
+      /* Move to the end of the line.  */
+      Fend_of_line (Qnil);
+      end = PT;
+      end_byte = PT_BYTE;
+      break;
+
+    case TEXTCONV_ABSOLUTE_POSITION:
+      /* How to implement this is unclear.  */
+      SET_PT (query->factor);
+      end = PT;
+      end_byte = PT_BYTE;
+      break;
+
+    default:
+      unbind_to (count, Qnil);
+      return 1;
+    }
+
+  /* Sort end and pos.  */
+
+  if (end < pos)
+    {
+      eassert (end_byte < pos_byte);
+      temp = pos_byte;
+      temp1 = pos;
+      pos_byte = end_byte;
+      pos = end;
+      end = temp1;
+      end_byte = temp;
+    }
+
+  /* Return the string first.  */
+  buffer = xmalloc (end_byte - pos_byte);
+  copy_buffer (pos, pos_byte, end, end_byte, buffer);
+  query->text.text = buffer;
+  query->text.length = end - pos;
+  query->text.bytes = end_byte - pos_byte;
+
+  /* Next, perform any operation specified.  */
+
+  switch (query->operation)
+    {
+    case TEXTCONV_SUBSTITUTION:
+      if (safe_del_range (pos, end))
+       {
+         /* Undo any changes to the excursion.  */
+         unbind_to (count, Qnil);
+         return 1;
+       }
+
+    default:
+    }
+
+  /* Undo any changes to the excursion.  */
+  unbind_to (count, Qnil);
+  return 0;
+}
+
+
+
+/* Window system interface.  These are called from the rest of
+   Emacs.  */
+
+/* Notice that F's selected window has been set from redisplay.
+   Reset F's input method state.  */
+
+void
+report_selected_window_change (struct frame *f)
+{
+  if (!text_interface)
+    return;
+
+  text_interface->reset (f);
+}
+
+/* Register INTERFACE as the text conversion interface.  */
+
+void
+register_texconv_interface (struct textconv_interface *interface)
+{
+  text_interface = interface;
+}
diff --git a/src/textconv.h b/src/textconv.h
new file mode 100644
index 0000000000..f6e7eb7925
--- /dev/null
+++ b/src/textconv.h
@@ -0,0 +1,109 @@
+/* String conversion support for graphics terminals.
+
+Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#ifndef _TEXTCONV_H_
+
+#include "lisp.h"
+#include "frame.h"
+
+/* The function pointers in this structure should be filled out by
+   each GUI backend interested in supporting text conversion.
+
+   Finally, register_texconv_interface must be called at some point
+   during terminal initialization.  */
+
+struct textconv_interface
+{
+  /* Notice that the text conversion context has changed (which can
+     happen if the window is deleted or switches buffers, or an
+     unexpected buffer change occurs.) */
+  void (*reset) (struct frame *);
+};
+
+
+
+enum textconv_caret_direction
+  {
+    TEXTCONV_FORWARD_CHAR,
+    TEXTCONV_BACKWARD_CHAR,
+    TEXTCONV_FORWARD_WORD,
+    TEXTCONV_BACKWARD_WORD,
+    TEXTCONV_CARET_UP,
+    TEXTCONV_CARET_DOWN,
+    TEXTCONV_NEXT_LINE,
+    TEXTCONV_PREVIOUS_LINE,
+    TEXTCONV_LINE_START,
+    TEXTCONV_LINE_END,
+    TEXTCONV_ABSOLUTE_POSITION,
+  };
+
+enum textconv_operation
+  {
+    TEXTCONV_SUBSTITUTION,
+    TEXTCONV_RETRIEVAL,
+  };
+
+/* Structure describing text in a buffer corresponding to a ``struct
+   textconv_callback_struct''.  */
+
+struct textconv_conversion_text
+{
+  /* Length of the text in characters and bytes.  */
+  size_t length, bytes;
+
+  /* Pointer to the text data.  This must be deallocated by the
+     caller.  */
+  char *text;
+};
+
+/* Structure describing a single query submitted by the input
+   method.  */
+
+struct textconv_callback_struct
+{
+  /* Character position, relative to the current spot location, from
+     where on text should be returned.  */
+  EMACS_INT position;
+
+  /* The type of scanning to perform to determine either the start or
+     the end of the conversion.  */
+  enum textconv_caret_direction direction;
+
+  /* The the number of times for which to repeat the scanning in order
+     to determine the starting position of the text to return.  */
+  unsigned short factor;
+
+  /* The operation to perform upon the current buffer contents.
+
+     If this is TEXTCONV_SUBSTITUTION, then the text that is returned
+     will be deleted from the buffer itself.
+
+     Otherwise, the text is simply returned without modifying the
+     buffer contents.  */
+  enum textconv_operation operation;
+
+  /* Structure that will be filled with a description of the resulting
+     text.  */
+  struct textconv_conversion_text text;
+};
+
+extern int textconv_query (struct frame *, struct textconv_callback_struct *);
+extern void register_texconv_interface (struct textconv_interface *);
+
+#endif /* _TEXTCONV_H_ */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]