17784Swpaul/* 27784Swpaul * Copyright (C) 1984-2012 Mark Nudelman 37784Swpaul * 47784Swpaul * You may distribute under the terms of either the GNU General Public 57784Swpaul * License or the Less License, as specified in the README file. 67784Swpaul * 77784Swpaul * For more information, see the README file. 87784Swpaul */ 97784Swpaul 107784Swpaul 117784Swpaul/* 127784Swpaul * Routines dealing with getting input from the keyboard (i.e. from the user). 137784Swpaul */ 147784Swpaul 157784Swpaul#include "less.h" 167784Swpaul#if OS2 177784Swpaul#include "cmd.h" 187784Swpaul#include "pckeys.h" 197784Swpaul#endif 207784Swpaul#if MSDOS_COMPILER==WIN32C 217784Swpaul#include "windows.h" 227784Swpaulextern char WIN32getch(); 237784Swpaulstatic DWORD console_mode; 247784Swpaul#endif 257784Swpaul 267784Swpaulpublic int tty; 277784Swpaulextern int sigs; 287784Swpaulextern int utf_mode; 297784Swpaul 307784Swpaul/* 3150476Speter * Open keyboard for input. 327784Swpaul */ 337784Swpaul public void 347784Swpaulopen_getchr() 3579538Sru{ 367784Swpaul#if MSDOS_COMPILER==WIN32C 377784Swpaul /* Need this to let child processes inherit our console handle */ 387784Swpaul SECURITY_ATTRIBUTES sa; 397784Swpaul memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); 407784Swpaul sa.nLength = sizeof(SECURITY_ATTRIBUTES); 4168962Sru sa.bInheritHandle = TRUE; 427784Swpaul tty = (int) CreateFile("CONIN$", GENERIC_READ, 4357731Ssheldonh FILE_SHARE_READ, &sa, 4457731Ssheldonh OPEN_EXISTING, 0L, NULL); 457784Swpaul GetConsoleMode((HANDLE)tty, &console_mode); 467784Swpaul /* Make sure we get Ctrl+C events. */ 477784Swpaul SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_INPUT); 48140293Sru#else 49140293Sru#if MSDOS_COMPILER 507784Swpaul extern int fd0; 5157731Ssheldonh /* 5257731Ssheldonh * Open a new handle to CON: in binary mode 5357731Ssheldonh * for unbuffered keyboard read. 5457731Ssheldonh */ 557784Swpaul fd0 = dup(0); 567784Swpaul close(0); 5732302Ssteve tty = open("CON", OPEN_READ); 58140567Sru#if MSDOS_COMPILER==DJGPPC 597784Swpaul /* 607784Swpaul * Setting stdin to binary causes Ctrl-C to not 617784Swpaul * raise SIGINT. We must undo that side-effect. 627784Swpaul */ 637784Swpaul (void) __djgpp_set_ctrl_c(1); 647784Swpaul#endif 657784Swpaul#else 667784Swpaul /* 677784Swpaul * Try /dev/tty. 687784Swpaul * If that doesn't work, use file descriptor 2, 697784Swpaul * which in Unix is usually attached to the screen, 7057731Ssheldonh * but also usually lets you read from the keyboard. 7157731Ssheldonh */ 7257731Ssheldonh#if OS2 7357731Ssheldonh /* The __open() system call translates "/dev/tty" to "con". */ 747784Swpaul tty = __open("/dev/tty", OPEN_READ); 757784Swpaul#else 767784Swpaul tty = open("/dev/tty", OPEN_READ); 777784Swpaul#endif 787784Swpaul if (tty < 0) 797784Swpaul tty = 2; 807784Swpaul#endif 8113744Smpp#endif 827784Swpaul} 837784Swpaul 8413744Smpp/* 857784Swpaul * Close the keyboard. 867784Swpaul */ 877784Swpaul public void 887784Swpaulclose_getchr() 897784Swpaul{ 907784Swpaul#if MSDOS_COMPILER==WIN32C 917784Swpaul SetConsoleMode((HANDLE)tty, console_mode); 9268962Sru CloseHandle((HANDLE)tty); 937784Swpaul#endif 947784Swpaul} 957784Swpaul 967784Swpaul/* 9732302Ssteve * Get a character from the keyboard. 9889362Sru */ 997784Swpaul public int 1007784Swpaulgetchr() 10168962Sru{ 1027784Swpaul char c; 103 int result; 104 105 do 106 { 107#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC 108 /* 109 * In raw read, we don't see ^C so look here for it. 110 */ 111 flush(); 112#if MSDOS_COMPILER==WIN32C 113 if (ABORT_SIGS()) 114 return (READ_INTR); 115 c = WIN32getch(tty); 116#else 117 c = getch(); 118#endif 119 result = 1; 120 if (c == '\003') 121 return (READ_INTR); 122#else 123 result = iread(tty, &c, sizeof(char)); 124 if (result == READ_INTR) 125 return (READ_INTR); 126 if (result < 0) 127 { 128 /* 129 * Don't call error() here, 130 * because error calls getchr! 131 */ 132 quit(QUIT_ERROR); 133 } 134#endif 135#if 0 /* allow entering arbitrary hex chars for testing */ 136 /* ctrl-A followed by two hex chars makes a byte */ 137 { 138 int hex_in = 0; 139 int hex_value = 0; 140 if (c == CONTROL('A')) 141 { 142 hex_in = 2; 143 result = 0; 144 continue; 145 } 146 if (hex_in > 0) 147 { 148 int v; 149 if (c >= '0' && c <= '9') 150 v = c - '0'; 151 else if (c >= 'a' && c <= 'f') 152 v = c - 'a' + 10; 153 else if (c >= 'A' && c <= 'F') 154 v = c - 'A' + 10; 155 else 156 hex_in = 0; 157 hex_value = (hex_value << 4) | v; 158 if (--hex_in > 0) 159 { 160 result = 0; 161 continue; 162 } 163 c = hex_value; 164 } 165 } 166#endif 167 /* 168 * Various parts of the program cannot handle 169 * an input character of '\0'. 170 * If a '\0' was actually typed, convert it to '\340' here. 171 */ 172 if (c == '\0') 173 c = '\340'; 174 } while (result != 1); 175 176 return (c & 0xFF); 177} 178