On the E325 screen (Found a swap file...), the user can choose different keys to
press (e.g. [O]pen Read-Only, (E)dit anyway,...). If she presses <Esc>, vim
freezes (and the terminal session has to be killed).

Reproduce as follows:
1) in one terminal, $ vim a.txt
2) in another terminal, $ vim a.txt
3) vim prompts with E325, warning that there already is a swap file
4) press <Esc> - vim freezes

It turns out that vim (on VMS) uses select() to poll on the terminal input.
Unfortunately, select() has never been ported fully and only works for sockets
(same as on Windows).

The full details of how/why this manifests only for <Esc> are probably
unnecessary here. (If someone is interested, I'm ready to share them, of
course.)

The idea of the patch is to replace select() by the native IO-sniffing call,
sys$qiow(). VMS thus gets its very own RealWaitForChar(), rather than using
Unix's one. The time-out is implemented manually by looping (just like on
Windows).

Thanks,
Sam




diff -r 3a32cbcc2449 src/os_unix.c
--- a/src/os_unix.c     Wed Sep 25 23:24:58 2013 +0200
+++ b/src/os_unix.c     Sat Sep 28 23:17:03 2013 +0200
@@ -168,7 +168,7 @@
 static pid_t wait4pid __ARGS((pid_t, waitstatus *));
 
 static int  WaitForChar __ARGS((long));
-#if defined(__BEOS__)
+#if defined(__BEOS__) || defined(VMS)
 int  RealWaitForChar __ARGS((int, long, int *));
 #else
 static int  RealWaitForChar __ARGS((int, long, int *));
@@ -435,7 +435,6 @@
        /* Process the queued netbeans messages. */
        netbeans_parse_messages();
 #endif
-#ifndef VMS  /* VMS: must try reading, WaitForChar() does nothing. */
        /*
         * We want to be interrupted by the winch signal
         * or by an event on the monitored file descriptors.
@@ -446,7 +445,6 @@
                handle_resize();
            return 0;
        }
-#endif
 
        /* If input was put directly in typeahead buffer bail out here. */
        if (typebuf_changed(tb_change_cnt))
@@ -5035,6 +5033,7 @@
     return avail;
 }
 
+#ifndef VMS
 /*
  * Wait "msec" msec until a character is available from file descriptor "fd".
  * "msec" == 0 will check for characters once.
@@ -5334,13 +5333,7 @@
        }
 # endif
 
-# ifdef OLD_VMS
-       /* Old VMS as v6.2 and older have broken select(). It waits more than
-        * required. Should not be used */
-       ret = 0;
-# else
        ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
-# endif
 # ifdef EINTR
        if (ret == -1 && errno == EINTR)
        {
@@ -5462,8 +5455,6 @@
     return (ret > 0);
 }
 
-#ifndef VMS
-
 #ifndef NO_EXPANDPATH
 /*
  * Expand a path into all matching files and/or directories.  Handles "*",
diff -r 3a32cbcc2449 src/os_unix.h
--- a/src/os_unix.h     Wed Sep 25 23:24:58 2013 +0200
+++ b/src/os_unix.h     Sat Sep 28 23:17:03 2013 +0200
@@ -225,6 +225,9 @@
 # include <starlet.h>
 # include <socket.h>
 # include <lib$routines.h>
+# include <gen64def.h>
+# include <libdef.h>
+# include <libdtdef.h>
 
 # ifdef FEAT_GUI_GTK
 #  include "gui_gtk_vms.h"
diff -r 3a32cbcc2449 src/os_vms.c
--- a/src/os_vms.c      Wed Sep 25 23:24:58 2013 +0200
+++ b/src/os_vms.c      Sat Sep 28 23:17:03 2013 +0200
@@ -669,3 +669,92 @@
     }
     return ;
 }
+
+struct typeahead_st {
+    unsigned short numchars;
+    unsigned char  firstchar;
+    unsigned char  reserved0;
+    unsigned long  reserved1;
+} typeahead;
+
+/*
+ * Wait "msec" msec until a character is available from file descriptor "fd".
+ * "msec" == 0 will check for characters once.
+ * "msec" == -1 will block until a character is available.
+ */
+    int
+RealWaitForChar(fd, msec, check_for_gpm)
+    int                fd UNUSED; /* always read from iochan */
+    long       msec;
+    int                *check_for_gpm UNUSED;
+{
+    int status;
+    struct _generic_64 time_curr;
+    struct _generic_64 time_diff;
+    struct _generic_64 time_out;
+    unsigned int convert_operation = LIB$K_DELTA_SECONDS_F;
+    float sec = (float) msec / 1000;
+
+    /* make sure the iochan is set */
+    if (!iochan)
+       get_tty();
+
+    if (msec > 0) {
+        /* time-out specified; convert it to absolute time */
+
+        /* get current time (number of 100ns ticks since the VMS Epoch) */
+        status = sys$gettim(&time_curr);
+        if (status != SS$_NORMAL)
+            return 0; /* error */
+
+        /* construct the delta time */
+        status = lib$cvtf_to_internal_time(
+                &convert_operation, &sec, &time_diff);
+        if (status != LIB$_NORMAL)
+            return 0; /* error */
+
+        /* add them up */
+        status = lib$add_times(
+                &time_curr,
+                &time_diff,
+                &time_out);
+        if (status != LIB$_NORMAL)
+            return 0; /* error */
+    }
+
+    while (TRUE) {
+        /* select() */
+        status = sys$qiow(0, iochan, IO$_SENSEMODE | IO$M_TYPEAHDCNT, iosb,
+                0, 0, &typeahead, 8, 0, 0, 0, 0);
+       if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
+            return 0; /* error */
+
+        if (typeahead.numchars)
+            return 1; /* ready to read */
+
+        /* there's nothing to read; what now? */
+        if (msec == 0) {
+            /* immediate time-out; return impatiently */
+            return 0;
+        }
+        else if (msec < 0) {
+            /* no time-out; wait on indefinitely */
+            continue;
+        }
+        else {
+            /* time-out needs to be checked */
+            status = sys$gettim(&time_curr);
+            if (status != SS$_NORMAL)
+                return 0; /* error */
+
+            status = lib$sub_times(
+                    &time_out,
+                    &time_curr,
+                    &time_diff);
+            if (status != LIB$_NORMAL)
+                return 0; /* error, incl. time_diff < 0 (i.e. time-out) */
+
+            /* otherwise wait some more */
+        }
+    }
+}

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Raspunde prin e-mail lui