ttyin.c revision 221715
190075Sobrien/* 290075Sobrien * Copyright (C) 1984-2011 Mark Nudelman 390075Sobrien * 490075Sobrien * You may distribute under the terms of either the GNU General Public 590075Sobrien * License or the Less License, as specified in the README file. 690075Sobrien * 790075Sobrien * For more information about less, or for information on how to 890075Sobrien * contact the author, see the README file. 990075Sobrien */ 1090075Sobrien 1190075Sobrien 1290075Sobrien/* 1390075Sobrien * Routines dealing with getting input from the keyboard (i.e. from the user). 1490075Sobrien */ 1590075Sobrien 1690075Sobrien#include "less.h" 1790075Sobrien#if OS2 1890075Sobrien#include "cmd.h" 1990075Sobrien#include "pckeys.h" 2090075Sobrien#endif 2190075Sobrien#if MSDOS_COMPILER==WIN32C 2290075Sobrien#include "windows.h" 2390075Sobrienextern char WIN32getch(); 2490075Sobrienstatic DWORD console_mode; 2590075Sobrien#endif 2690075Sobrien 2790075Sobrienpublic int tty; 2890075Sobrienextern int sigs; 2990075Sobrienextern int utf_mode; 3090075Sobrien 3190075Sobrien/* 3290075Sobrien * Open keyboard for input. 3390075Sobrien */ 3490075Sobrien public void 3590075Sobrienopen_getchr() 3690075Sobrien{ 3790075Sobrien#if MSDOS_COMPILER==WIN32C 3890075Sobrien /* Need this to let child processes inherit our console handle */ 3990075Sobrien SECURITY_ATTRIBUTES sa; 4090075Sobrien memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); 4190075Sobrien sa.nLength = sizeof(SECURITY_ATTRIBUTES); 4290075Sobrien sa.bInheritHandle = TRUE; 4390075Sobrien tty = (int) CreateFile("CONIN$", GENERIC_READ, 4490075Sobrien FILE_SHARE_READ, &sa, 4590075Sobrien OPEN_EXISTING, 0L, NULL); 4690075Sobrien GetConsoleMode((HANDLE)tty, &console_mode); 4790075Sobrien /* Make sure we get Ctrl+C events. */ 4890075Sobrien SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_INPUT); 4990075Sobrien#else 5090075Sobrien#if MSDOS_COMPILER 5190075Sobrien extern int fd0; 5290075Sobrien /* 5390075Sobrien * Open a new handle to CON: in binary mode 5490075Sobrien * for unbuffered keyboard read. 5590075Sobrien */ 5690075Sobrien fd0 = dup(0); 5790075Sobrien close(0); 5890075Sobrien tty = open("CON", OPEN_READ); 5990075Sobrien#if MSDOS_COMPILER==DJGPPC 6090075Sobrien /* 6190075Sobrien * Setting stdin to binary causes Ctrl-C to not 6290075Sobrien * raise SIGINT. We must undo that side-effect. 6390075Sobrien */ 6490075Sobrien (void) __djgpp_set_ctrl_c(1); 6590075Sobrien#endif 6690075Sobrien#else 6790075Sobrien /* 6890075Sobrien * Try /dev/tty. 6990075Sobrien * If that doesn't work, use file descriptor 2, 7090075Sobrien * which in Unix is usually attached to the screen, 7190075Sobrien * but also usually lets you read from the keyboard. 7290075Sobrien */ 7390075Sobrien#if OS2 7490075Sobrien /* The __open() system call translates "/dev/tty" to "con". */ 7590075Sobrien tty = __open("/dev/tty", OPEN_READ); 7690075Sobrien#else 7790075Sobrien tty = open("/dev/tty", OPEN_READ); 7890075Sobrien#endif 7990075Sobrien if (tty < 0) 8090075Sobrien tty = 2; 8190075Sobrien#endif 8290075Sobrien#endif 8390075Sobrien} 8490075Sobrien 8590075Sobrien/* 8690075Sobrien * Close the keyboard. 8790075Sobrien */ 8890075Sobrien public void 8990075Sobrienclose_getchr() 9090075Sobrien{ 9190075Sobrien#if MSDOS_COMPILER==WIN32C 9290075Sobrien SetConsoleMode((HANDLE)tty, console_mode); 9390075Sobrien CloseHandle((HANDLE)tty); 9490075Sobrien#endif 9590075Sobrien} 9690075Sobrien 9790075Sobrien/* 9890075Sobrien * Get a character from the keyboard. 9990075Sobrien */ 10090075Sobrien public int 10190075Sobriengetchr() 10290075Sobrien{ 10390075Sobrien char c; 10490075Sobrien int result; 10590075Sobrien 10690075Sobrien do 10790075Sobrien { 10890075Sobrien#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC 10990075Sobrien /* 11090075Sobrien * In raw read, we don't see ^C so look here for it. 11190075Sobrien */ 11290075Sobrien flush(); 11390075Sobrien#if MSDOS_COMPILER==WIN32C 11490075Sobrien if (ABORT_SIGS()) 11590075Sobrien return (READ_INTR); 11690075Sobrien c = WIN32getch(tty); 11790075Sobrien#else 11890075Sobrien c = getch(); 11990075Sobrien#endif 12090075Sobrien result = 1; 12190075Sobrien if (c == '\003') 12290075Sobrien return (READ_INTR); 12390075Sobrien#else 12490075Sobrien result = iread(tty, &c, sizeof(char)); 12590075Sobrien if (result == READ_INTR) 12690075Sobrien return (READ_INTR); 12790075Sobrien if (result < 0) 12890075Sobrien { 12990075Sobrien /* 13090075Sobrien * Don't call error() here, 13190075Sobrien * because error calls getchr! 13290075Sobrien */ 13390075Sobrien quit(QUIT_ERROR); 13490075Sobrien } 13590075Sobrien#endif 13690075Sobrien#if 0 /* allow entering arbitrary hex chars for testing */ 13790075Sobrien /* ctrl-A followed by two hex chars makes a byte */ 13890075Sobrien { 13990075Sobrien int hex_in = 0; 14090075Sobrien int hex_value = 0; 14190075Sobrien if (c == CONTROL('A')) 14290075Sobrien { 14390075Sobrien hex_in = 2; 14490075Sobrien result = 0; 14590075Sobrien continue; 14690075Sobrien } 14790075Sobrien if (hex_in > 0) 14890075Sobrien { 14990075Sobrien int v; 15090075Sobrien if (c >= '0' && c <= '9') 15190075Sobrien v = c - '0'; 15290075Sobrien else if (c >= 'a' && c <= 'f') 15390075Sobrien v = c - 'a' + 10; 154 else if (c >= 'A' && c <= 'F') 155 v = c - 'A' + 10; 156 else 157 hex_in = 0; 158 hex_value = (hex_value << 4) | v; 159 if (--hex_in > 0) 160 { 161 result = 0; 162 continue; 163 } 164 c = hex_value; 165 } 166 } 167#endif 168 /* 169 * Various parts of the program cannot handle 170 * an input character of '\0'. 171 * If a '\0' was actually typed, convert it to '\340' here. 172 */ 173 if (c == '\0') 174 c = '\340'; 175 } while (result != 1); 176 177 return (c & 0xFF); 178} 179