summaryrefslogtreecommitdiff
path: root/ttyin.c
diff options
context:
space:
mode:
Diffstat (limited to 'ttyin.c')
-rwxr-xr-xttyin.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/ttyin.c b/ttyin.c
new file mode 100755
index 0000000..db6e72e
--- /dev/null
+++ b/ttyin.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 1984-2012 Mark Nudelman
+ *
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Less License, as specified in the README file.
+ *
+ * For more information, see the README file.
+ */
+
+
+/*
+ * Routines dealing with getting input from the keyboard (i.e. from the user).
+ */
+
+#include "less.h"
+#if OS2
+#include "cmd.h"
+#include "pckeys.h"
+#endif
+#if MSDOS_COMPILER==WIN32C
+#include "windows.h"
+extern char WIN32getch();
+static DWORD console_mode;
+#endif
+
+public int tty;
+extern int sigs;
+extern int utf_mode;
+
+/*
+ * Open keyboard for input.
+ */
+ public void
+open_getchr()
+{
+#if MSDOS_COMPILER==WIN32C
+ /* Need this to let child processes inherit our console handle */
+ SECURITY_ATTRIBUTES sa;
+ memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.bInheritHandle = TRUE;
+ tty = (int) CreateFile("CONIN$", GENERIC_READ,
+ FILE_SHARE_READ, &sa,
+ OPEN_EXISTING, 0L, NULL);
+ GetConsoleMode((HANDLE)tty, &console_mode);
+ /* Make sure we get Ctrl+C events. */
+ SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_INPUT);
+#else
+#if MSDOS_COMPILER
+ extern int fd0;
+ /*
+ * Open a new handle to CON: in binary mode
+ * for unbuffered keyboard read.
+ */
+ fd0 = dup(0);
+ close(0);
+ tty = open("CON", OPEN_READ);
+#if MSDOS_COMPILER==DJGPPC
+ /*
+ * Setting stdin to binary causes Ctrl-C to not
+ * raise SIGINT. We must undo that side-effect.
+ */
+ (void) __djgpp_set_ctrl_c(1);
+#endif
+#else
+ /*
+ * Try /dev/tty.
+ * If that doesn't work, use file descriptor 2,
+ * which in Unix is usually attached to the screen,
+ * but also usually lets you read from the keyboard.
+ */
+#if OS2
+ /* The __open() system call translates "/dev/tty" to "con". */
+ tty = __open("/dev/tty", OPEN_READ);
+#else
+ tty = open("/dev/tty", OPEN_READ);
+#endif
+ if (tty < 0)
+ tty = 2;
+#endif
+#endif
+}
+
+/*
+ * Close the keyboard.
+ */
+ public void
+close_getchr()
+{
+#if MSDOS_COMPILER==WIN32C
+ SetConsoleMode((HANDLE)tty, console_mode);
+ CloseHandle((HANDLE)tty);
+#endif
+}
+
+/*
+ * Get a character from the keyboard.
+ */
+ public int
+getchr()
+{
+ char c;
+ int result;
+
+ do
+ {
+#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
+ /*
+ * In raw read, we don't see ^C so look here for it.
+ */
+ flush();
+#if MSDOS_COMPILER==WIN32C
+ if (ABORT_SIGS())
+ return (READ_INTR);
+ c = WIN32getch(tty);
+#else
+ c = getch();
+#endif
+ result = 1;
+ if (c == '\003')
+ return (READ_INTR);
+#else
+ result = iread(tty, &c, sizeof(char));
+ if (result == READ_INTR)
+ return (READ_INTR);
+ if (result < 0)
+ {
+ /*
+ * Don't call error() here,
+ * because error calls getchr!
+ */
+ quit(QUIT_ERROR);
+ }
+#endif
+#if 0 /* allow entering arbitrary hex chars for testing */
+ /* ctrl-A followed by two hex chars makes a byte */
+ {
+ int hex_in = 0;
+ int hex_value = 0;
+ if (c == CONTROL('A'))
+ {
+ hex_in = 2;
+ result = 0;
+ continue;
+ }
+ if (hex_in > 0)
+ {
+ int v;
+ if (c >= '0' && c <= '9')
+ v = c - '0';
+ else if (c >= 'a' && c <= 'f')
+ v = c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ v = c - 'A' + 10;
+ else
+ hex_in = 0;
+ hex_value = (hex_value << 4) | v;
+ if (--hex_in > 0)
+ {
+ result = 0;
+ continue;
+ }
+ c = hex_value;
+ }
+ }
+#endif
+ /*
+ * Various parts of the program cannot handle
+ * an input character of '\0'.
+ * If a '\0' was actually typed, convert it to '\340' here.
+ */
+ if (c == '\0')
+ c = '\340';
+ } while (result != 1);
+
+ return (c & 0xFF);
+}