screen-devel
[Top][All Lists]
Advanced

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

[screen-devel] [screen-v4] [PATCH] Add multi-select copy mode


From: Volodymyr Boiko
Subject: [screen-devel] [screen-v4] [PATCH] Add multi-select copy mode
Date: Sat, 6 Nov 2021 02:47:55 +0200

Multi-select mode allows user to make multiple copy/append
operations without leaving copy-mode, i.e. in a single copy-mode
session.

This commit extends copy-mode with the following controls:
'm' (multi-select) - toggles in multi-select mode. Setting a second mark will
                     modify the paste buffer without exiting copy-mode.
'd' (discard) - discards (cancels) a selection without exiting copy mode.

Signed-off-by: Volodymyr Boiko <boyko.cxx@gmail.com>
---
 src/doc/screen.1 |  5 +++++
 src/mark.c       | 49 +++++++++++++++++++++++++++++++++++-------------
 src/mark.h       |  1 +
 3 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/src/doc/screen.1 b/src/doc/screen.1
index 68570a0..c47c69f 100644
--- a/src/doc/screen.1
+++ b/src/doc/screen.1
@@ -1625,6 +1625,11 @@ the contents of the paste buffer will not be 
overwritten, but is appended to.
 the screen-exchange file (/tmp/screen\-exchange per default) once copy-mode is
 finished. 
 .PP
+\fBm\fP toggles in multi-select mode. Setting a second mark will
+modify the paste buffer without exiting copy-mode.
+.PP
+\fBd\fP discards (cancels) a selection without exiting copy-mode.
+.PP
 This example demonstrates how to dump the whole scrollback buffer 
 to that file: \*QC-A [ g SPACE G $ >\*U.
 .PP
diff --git a/src/mark.c b/src/mark.c
index 33333de..ec5cfba 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -490,6 +490,21 @@ GetHistory()       /* return value 1 if copybuffer changed 
*/
   return 1;
 }
 
+static int
+yend_get(void)
+{
+  int yend = fore->w_height - 1;
+  if (fore->w_histheight - markdata->hist_offset < fore->w_height)
+  {
+    int n = fore->w_histheight - markdata->hist_offset;
+    if (n < 0) n = 0;
+    if (n > markdata->hist_offset)
+      n = markdata->hist_offset;
+    yend -= n;
+  }
+  return yend;
+}
+
 /**********************************************************************/
 
 
@@ -513,6 +528,7 @@ MarkRoutine()
   markdata->second = 0;
   markdata->rep_cnt = 0;
   markdata->append_mode = 0;
+  markdata->multiselect_mode = 0;
   markdata->write_buffer = 0;
   markdata->nonl = 0;
   markdata->left_mar  = 0;
@@ -835,6 +851,10 @@ processchar:
          debug1("append mode %d--\n", markdata->append_mode);
          LMsg(0, (markdata->append_mode) ? ":set append" : ":set noappend");
          break;
+       case 'm':
+         markdata->multiselect_mode = 1 - markdata->multiselect_mode;
+         LMsg(0, (markdata->multiselect_mode) ? ":set multiselect" : ":set 
nomultiselect");
+         break;
        case 'v':
        case 'V':
          /* this sets start column to column 9 for VI :set nu users */
@@ -896,6 +916,14 @@ processchar:
              break;
            }
          break;
+       case 'd':
+         if (markdata->second)
+         {
+               int yend = yend_get();
+               rem(markdata->x1, markdata->y1, cx, cy, 1, NULL, yend);
+               LMsg(0, "Selection discarded");
+         }
+         break;
        case '/':
          Search(1);
          in_mark = 0;
@@ -975,12 +1003,7 @@ processchar:
              newcopylen = rem(markdata->x1, markdata->y1, x2, y2, 2, (char 
*)0, 0); /* count */
              if (md_user->u_plop.buf && !append_mode)
                UserFreeCopyBuffer(md_user);
-             yend = fore->w_height - 1;
-             if (fore->w_histheight - markdata->hist_offset < fore->w_height)
-               {
-                 markdata->second = 0;
-                 yend -= MarkScrollUpDisplay(fore->w_histheight - 
markdata->hist_offset);
-               }
+             yend = yend_get();
              if (newcopylen > 0)
                {
                  /* the +3 below is for : cr + lf + \0 */
@@ -1030,17 +1053,17 @@ processchar:
                        }
                    }
                  md_user->u_plop.len += rem(markdata->x1, markdata->y1, x2, y2,
-                   markdata->hist_offset == fore->w_histheight,
-                   md_user->u_plop.buf + md_user->u_plop.len, yend);
+                   1, md_user->u_plop.buf + md_user->u_plop.len, yend);
 #ifdef ENCODINGS
                  md_user->u_plop.enc = fore->w_encoding;
 #endif
                }
-             if (markdata->hist_offset != fore->w_histheight)
-               {
-                 LAY_CALL_UP(LRefreshAll(flayer, 0));
-               }
-             ExitOverlayPage();
+             if (!markdata->multiselect_mode) {
+               if (markdata->hist_offset != fore->w_histheight) {
+                 LAY_CALL_UP(LRefreshAll(flayer, 0));
+               }
+               ExitOverlayPage();
+             }
              WindowChanged(fore, 'P');
              if (append_mode)
                LMsg(0, "Appended %d characters to buffer",
diff --git a/src/mark.h b/src/mark.h
index 2c55e39..6ee726a 100644
--- a/src/mark.h
+++ b/src/mark.h
@@ -37,6 +37,7 @@ struct markdata
   int  left_mar, right_mar, nonl;
   int  rep_cnt;        /* number of repeats */
   int  append_mode;    /* shall we overwrite or append to copybuffer */
+  int  multiselect_mode;       /* do not exit on second mark set */
   int  write_buffer;   /* shall we do a KEY_WRITE_EXCHANGE right away? */
   int  hist_offset;    /* how many lines are on top of the screen */
   char isstr[100];     /* string we are searching for */
-- 
2.25.1




reply via email to

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