diff options
Diffstat (limited to 'ttyin.c')
-rwxr-xr-x | ttyin.c | 177 |
1 files changed, 177 insertions, 0 deletions
@@ -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); +} |