]> git.neil.brown.name Git - edlib.git/commitdiff
ncurses: don't block in nc_external_viewer
authorNeilBrown <neil@brown.name>
Fri, 2 Jun 2023 03:07:28 +0000 (13:07 +1000)
committerNeilBrown <neil@brown.name>
Thu, 8 Jun 2023 10:38:58 +0000 (20:38 +1000)
Rather than blocking the whole editor while waiting for use to
copy/paste for plain-text screen, set a flag to say that the display is
suspended, and resume on next key stroke collected in the normal way.

Also timeout after 30 seconds.

Signed-off-by: NeilBrown <neil@brown.name>
DOC/Developer/04-events.md
DOC/TODO.md
display-ncurses.c

index 40471b11fe886ee58d9f6e5ff7b6c6f43c06610f..c4a4d016c25306ce4fbf7f5ad33498d53154e3b7 100644 (file)
@@ -44,7 +44,7 @@ The messages that the event subsystem listens for are:
   be a stream that supports "unget".  In such a case there may be
   content to get, but not from the file descriptor.
 
-- event:free - And register event from the focus pane which is supposed
+- event:free - Any register event from the focus pane which is supposed
   to call the given comm2 will be deactivated.  If no comm2 command is
   given, all registered event for the given focus pane are deregistered.
   Note that when a pane is closed, the event subsystem detects this and
index af85751a64ec5d64dbb1b4d3ddf458e42ed5e10e..003888576ab5a8a641bf975bf3d371341a4cd8e4 100644 (file)
@@ -15,7 +15,7 @@ the file.
 - [X] ->replace_pane, ->replace_popup can be deleted (Abort) but we
       don't catch it...
 - [X] notmuch reply should interpolate the first *visible* text part
-- [ ] ncurses - don't block in nc_external_viewer - at least abort after
+- [X] ncurses - don't block in nc_external_viewer - at least abort after
       30 seconds, but preferrably switch to a mode which leaves
       everything else running.
 - [ ] lang-python should put each module in a separate module
@@ -247,7 +247,7 @@ Module features
 
 ### ncurses
 
-- [ ] don't block in nc_external_viewer - at least abort after
+- [X] don't block in nc_external_viewer - at least abort after
       30 seconds, but preferrably switch to a mode which leaves
       everything else running.
 - [ ] add full list of colour names (to lib-colourmap)
index 3f89bdf848ec888b56036c90cdb8c67277e41f93..67f36fa1f900e8a9d97511647ac26562886ebdf8 100644 (file)
@@ -69,6 +69,7 @@ struct display_data {
        long                    last_event;
 
        bool                    did_close;
+       bool                    suspended;
 
        struct buf              paste_buf;
        time_t                  paste_start;
@@ -511,6 +512,18 @@ static void wait_for(struct display_data *dd safe)
        }
 }
 
+DEF_CB(ns_resume)
+{
+       struct display_data *dd = ci->home->data;
+
+       if (dd->suspended) {
+               dd->suspended = False;
+               set_screen(ci->home);
+               doupdate();
+       }
+       return 1;
+}
+
 DEF_CMD(nc_external_viewer)
 {
        struct pane *p = ci->home;
@@ -576,6 +589,9 @@ DEF_CMD(nc_external_viewer)
                n -= read(fileno(dd->scr_file), buf,
                          n <= (int)sizeof(buf) ? n : (int)sizeof(buf));
        endwin();
+       /* stay in raw mode */
+       raw();
+       noecho();
 
        /* Endwin doesn't seem to reset properly, at least on xfce-terminal.
         * So do it manually
@@ -590,7 +606,7 @@ DEF_CMD(nc_external_viewer)
                tputs(dd->clear, 1, nc_putc);
        fflush(dd->scr_file);
 
-       fprintf(dd->scr_file, "# Consider copy-pasting following\n");
+       fprintf(dd->scr_file, "# Consider copy-pasting following\r\n");
        if (fqdn && path[0] == '/') {
                /* File will not be local for the user, so help them copy it. */
                const char *tmp = fnormalize(p, ci->str2 ?: "XXXXXX");
@@ -603,11 +619,11 @@ DEF_CMD(nc_external_viewer)
                        tmp, fqdn, fname);
                path = "$f";
        }
-       fprintf(dd->scr_file, "xdg-open %s\n", path);
-       fprintf(dd->scr_file, "# Press Enter to continue\n");
-       n = read(fileno(dd->scr_file), buf, sizeof(buf));
        free(fqdn);
-       doupdate();
+       fprintf(dd->scr_file, "xdg-open %s\r\n", path);
+       fprintf(dd->scr_file, "# Press Enter to continue\r\n");
+       dd->suspended = True;
+       call_comm("event:timer", p, &ns_resume, 30*1000);
        return 1;
 }
 
@@ -1209,9 +1225,13 @@ DEF_CMD(nc_refresh_size)
 DEF_CMD(nc_refresh_post)
 {
        struct pane *p = ci->home;
+       struct display_data *dd = p->data;
        struct pane *p1;
        PANEL *pan, *pan2;
 
+       if (dd->suspended)
+               return 1;
+
        set_screen(p);
 
        /* Need to ensure stacking order and panel y,x position
@@ -1703,6 +1723,13 @@ REDEF_CMD(input_handle)
        wait_for(dd);
        set_screen(p);
        while ((is_keycode = get_wch(&c)) != ERR) {
+               if (dd->suspended && c != KEY_MOUSE) {
+                       dd->suspended = False;
+                       doupdate();
+                       call_comm("event:free", p, &ns_resume);
+                       /* swallow the key */
+                       continue;
+               }
                if (paste_recv(p, is_keycode, c))
                        continue;
                if (c == KEY_MOUSE) {