size_t read() { namespace uf = boost::locale::utf; if(!isatty_) { DWORD read_bytes = 0; if(!ReadFile(handle_,buffer_,buffer_size,&read_bytes,0)) return 0; return read_bytes; } DWORD read_wchars = 0; size_t n = wbuffer_size - wsize_; if(!ReadConsoleW(handle_,wbuffer_,n,&read_wchars,0)) return 0; wsize_ += read_wchars; char *out = buffer_; wchar_t *b = wbuffer_; wchar_t *e = b + wsize_; wchar_t *p = b; uf::code_point c; wsize_ = e-p; while(p < e && (c = uf::utf_traits<wchar_t>::decode(p,e))!=uf::illegal && c!=uf::incomplete) { out = uf::utf_traits<char>::encode(c,out); wsize_ = e-p; } if(c==uf::illegal) return -1; if(c==uf::incomplete) { memmove(b,e-wsize_,sizeof(wchar_t)*wsize_); } return out - buffer_; }
/* ask_confirm() adapted from programs/cmd/builtins.c */ static BOOL ask_confirm(unsigned int msgid, WCHAR *reg_info) { HMODULE hmod; WCHAR Ybuffer[4]; WCHAR Nbuffer[4]; WCHAR defval[32]; WCHAR answer[MAX_PATH]; DWORD count; hmod = GetModuleHandleW(NULL); LoadStringW(hmod, STRING_YES, Ybuffer, ARRAY_SIZE(Ybuffer)); LoadStringW(hmod, STRING_NO, Nbuffer, ARRAY_SIZE(Nbuffer)); LoadStringW(hmod, STRING_DEFAULT_VALUE, defval, ARRAY_SIZE(defval)); while (1) { output_message(msgid, reg_info ? reg_info : defval); output_message(STRING_YESNO); ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), answer, ARRAY_SIZE(answer), &count, NULL); answer[0] = toupperW(answer[0]); if (answer[0] == Ybuffer[0]) return TRUE; if (answer[0] == Nbuffer[0]) return FALSE; } }
static int Twapi_ReadConsole(Tcl_Interp *interp, HANDLE conh, unsigned int numchars) { WCHAR buf[300]; WCHAR *bufP; DWORD len; int status; if (numchars > ARRAYSIZE(buf)) bufP = SWSPushFrame(numchars * sizeof(WCHAR), NULL); else bufP = buf; if (ReadConsoleW(conh, bufP, numchars, &len, NULL)) { ObjSetResult(interp, ObjFromWinCharsN(bufP, len)); status = TCL_OK; } else { TwapiReturnSystemError(interp); status = TCL_ERROR; } if (bufP != buf) SWSPopFrame(); return status; }
int win32_getc(FILE *fp) { const int fd = fileno(fp); HANDLE hStdin; DWORD ret; wchar_t wc[3]; char mbc[5]; int j; static wchar_t wcbuf = L'\0'; if (!(fd == fileno(stdin) && _isatty(fd) && file_system_codepage == CP_UTF8)) return getc(fp); if (getc_len == 0) { hStdin = GetStdHandle(STD_INPUT_HANDLE); if (wcbuf) { wc[0] = wcbuf; wcbuf = L'\0'; } else if (ReadConsoleW(hStdin, wc, 1, &ret, NULL) == 0) return EOF; if (0xd800<=wc[0] && wc[0]<0xdc00) { if (ReadConsoleW(hStdin, wc+1, 1, &ret, NULL) == 0) return EOF; if (0xdc00<=wc[1] && wc[1]<0xe000) { wc[2]=L'\0'; } else { wcbuf=wc[1]; wc[0]=0xfffd; /* illegal surrogate pair */ wc[1]=L'\0'; } } else if (0xdc00<=wc[0] && wc[0]<0xe000) { wc[0]=0xfffd; /* illegal surrogate pair */ wc[1]=L'\0'; } else { wc[1]=L'\0'; } get_utf8_from_wstring(wc,mbc); j=strlen(mbc)-1; while(j>=0) { getc_buff[getc_len++]=(int)mbc[j--]; } } return getc_buff[--getc_len]; }
/*********************************************************************** * ReadConsoleA (KERNEL32.@) */ BOOL WINAPI ReadConsoleA(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved) { LPWSTR ptr = HeapAlloc(GetProcessHeap(), 0, nNumberOfCharsToRead * sizeof(WCHAR)); DWORD ncr = 0; BOOL ret; if ((ret = ReadConsoleW(hConsoleInput, ptr, nNumberOfCharsToRead, &ncr, NULL))) ncr = WideCharToMultiByte(CP_ACP, 0, ptr, ncr, lpBuffer, nNumberOfCharsToRead, NULL, NULL); if (lpNumberOfCharsRead) *lpNumberOfCharsRead = ncr; HeapFree(GetProcessHeap(), 0, ptr); return ret; }
*/ DEVICE_CMD Read_IO(REBREQ *req) /* ** Low level "raw" standard input function. ** ** The request buffer must be long enough to hold result. ** ** Result is NOT terminated (the actual field has length.) ** ***********************************************************************/ { long total = 0; int len; BOOL ok; if (GET_FLAG(req->modes, RDM_NULL)) { req->data[0] = 0; return DR_DONE; } req->actual = 0; if (Std_Inp) { if (Redir_Inp) { // always UTF-8 len = MIN(req->length, BUF_SIZE); ok = ReadFile(Std_Inp, req->data, len, &total, 0); } else { ok = ReadConsoleW(Std_Inp, Std_Buf, BUF_SIZE-1, &total, 0); if (ok) { total = WideCharToMultiByte(CP_UTF8, 0, Std_Buf, total, req->data, req->length, 0, 0); if (!total) ok = FALSE; } } if (!ok) { req->error = GetLastError(); return DR_ERROR; } req->actual = total; } return DR_DONE; }
static ssize_t Sread_win32_console(void *handle, char *buffer, size_t size) { GET_LD ansi_stream *as = handle; BOOL rc; DWORD done; DWORD mode; int isRaw = FALSE; if ( Suser_input && Suser_input->handle == handle && PL_ttymode(Suser_input) == PL_RAWTTY ) { if ( GetConsoleMode(as->hConsole, &mode) && SetConsoleMode(as->hConsole, mode & ~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT)) ) isRaw = TRUE; } if ( !PL_wait_for_console_input(as->hConsole) ) goto error; rc = ReadConsoleW(as->hConsole, buffer, (DWORD)(size / sizeof(wchar_t)), &done, NULL); if ( rc ) { if ( isRaw ) SetConsoleMode(as->hConsole, mode); return done * sizeof(wchar_t); } error: if ( isRaw ) SetConsoleMode(as->hConsole, mode); return -1; }
static DWORD WINAPI _stdinthreadproc(LPVOID lpParameter) { #define STDIN_WCHAR_BUF_SIZE (1024 * 2) #define STDIN_CCHAR_BUF_SIZE (1024 * 4) WCHAR wbuf[STDIN_WCHAR_BUF_SIZE]; char cbuf[STDIN_CCHAR_BUF_SIZE]; HANDLE hconsolein = GetStdHandle(STD_INPUT_HANDLE); UINT oldcp = GetConsoleCP(); SetConsoleCP(CP_UTF8); (void)lpParameter; do { DWORD cmode; if(GetConsoleMode(hconsolein, &cmode)) { SetConsoleMode(hconsolein, cmode | ENABLE_LINE_INPUT); } } while(0); while(1) { DWORD read; int x; if(!ReadConsoleW(hconsolein, wbuf, STDIN_WCHAR_BUF_SIZE, &read, NULL)) break; cbuf[0] = 0; _widetoutf8(wbuf, read, cbuf, STDIN_CCHAR_BUF_SIZE); _fix_stdinsockaddr(); x = bind(_stdinsock, (struct sockaddr*)&_stdinsockaddr, sizeof(struct sockaddr_in)); _fix_stdinsockaddr(); x = sendto(_stdinsock, cbuf, strlen(cbuf), 0, (struct sockaddr*)&_stdinsockaddr, sizeof(struct sockaddr_in)); } SetConsoleCP(oldcp); CloseHandle(hconsolein); return 0; }
BOOL _ReadConsole(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, PCONSOLE_READCONSOLE_CONTROL pInputControl) { return ReadConsoleW(hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, pInputControl); }
char* win32_cgets (char* buffer, int len) { /* We use console ReadConsoleA / ReadConsoleW to be able to read unicode from the win32 console and fallback if seomething fails. */ HANDLE hIn=GetStdHandle (STD_INPUT_HANDLE); if(hIn && (hIn!=INVALID_HANDLE_VALUE) && p_WideCharToMultiByte && p_MultiByteToWideChar) { DWORD dwRead; wchar_t wszBuf[1024]; char szBuf[1024]; // NT and unicode conversion. if(ReadConsoleW(hIn, wszBuf, 1024, &dwRead, NULL)) { // Null terminate at end. if(wszBuf[dwRead-1]==L'\n') { wszBuf[dwRead-1]=L'\0'; dwRead--; } if(wszBuf[dwRead-1]==L'\r') { wszBuf[dwRead-1]=L'\0'; dwRead--; } wchar_2_UTF8(buffer, wszBuf, len); return buffer; } // Win 9x and unicode conversion. if(ReadConsoleA(hIn, szBuf, 1024, &dwRead, NULL)) { // Null terminate at end. if(szBuf[dwRead-1]==L'\n') { szBuf[dwRead-1]=L'\0'; dwRead--; } if(szBuf[dwRead-1]==L'\r') { szBuf[dwRead-1]=L'\0'; dwRead--; } // Convert from ansii to wchar_t. p_MultiByteToWideChar(GetConsoleCP(), 0, szBuf, -1, wszBuf, 1024); // Convert from wchar_t to UTF-8. if(wchar_2_UTF8(buffer, wszBuf, len)) return buffer; } } // Fallback. if(fgets(buffer, len, stdin)) return buffer; return NULL; }
static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl) { static int ps; int ok; char result[BUFSIZ]; int maxsize = BUFSIZ - 1; #if !defined(OPENSSL_SYS_WINCE) char *p = NULL; int echo_eol = !echo; intr_signal = 0; ok = 0; ps = 0; pushsig(); ps = 1; if (!echo && !noecho_console(ui)) goto error; ps = 2; result[0] = '\0'; # if defined(_WIN32) if (is_a_tty) { DWORD numread; # if defined(CP_UTF8) if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) { WCHAR wresult[BUFSIZ]; if (ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), wresult, maxsize, &numread, NULL)) { if (numread >= 2 && wresult[numread-2] == L'\r' && wresult[numread-1] == L'\n') { wresult[numread-2] = L'\n'; numread--; } wresult[numread] = '\0'; if (WideCharToMultiByte(CP_UTF8, 0, wresult, -1, result, sizeof(result), NULL, 0) > 0) p = result; OPENSSL_cleanse(wresult, sizeof(wresult)); } } else # endif if (ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE), result, maxsize, &numread, NULL)) { if (numread >= 2 && result[numread-2] == '\r' && result[numread-1] == '\n') { result[numread-2] = '\n'; numread--; } result[numread] = '\0'; p = result; } } else # elif defined(OPENSSL_SYS_MSDOS) if (!echo) { noecho_fgets(result, maxsize, tty_in); p = result; /* FIXME: noecho_fgets doesn't return errors */ } else # endif p = fgets(result, maxsize, tty_in); if (p == NULL) goto error; if (feof(tty_in)) goto error; if (ferror(tty_in)) goto error; if ((p = (char *)strchr(result, '\n')) != NULL) { if (strip_nl) *p = '\0'; } else if (!read_till_nl(tty_in)) goto error; if (UI_set_result(ui, uis, result) >= 0) ok = 1; error: if (intr_signal == SIGINT) ok = -1; if (echo_eol) fprintf(tty_out, "\n"); if (ps >= 2 && !echo && !echo_console(ui)) ok = 0; if (ps >= 1) popsig(); #else ok = 1; #endif OPENSSL_cleanse(result, BUFSIZ); return ok; }
errno_t __cdecl _cgetws_s ( wchar_t *string, size_t sizeInWords, size_t * pSizeRead ) { ULONG oldstate; ULONG num_read; errno_t err = 0; _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE((string != NULL), EINVAL); _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE((sizeInWords > 0), EINVAL); _RESET_STRING(string, sizeInWords); _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE((pSizeRead != NULL), EINVAL); _mlock(_CONIO_LOCK); /* lock the console */ __TRY /* * We need to decrement sizeInWords because ReadConsole reads as * many characters as the parameter passed, doesn't null terminate */ --sizeInWords; *pSizeRead = 0; /* * If the __console_whcar_buffer_used is set, then first fill the * buffered character and then proceed. */ if (__console_wchar_buffer_used != 0 && sizeInWords > 0) { *string++ = __console_wchar_buffer; __console_wchar_buffer = 0; --sizeInWords; (*pSizeRead)++; if (__console_wchar_buffer == L'\0') sizeInWords = 0; } /* if the user only asked for one character, we have now filled their request */ if (sizeInWords != 0) { /* * _coninpfh, the handle to the console input, is created the first * time that either _getch() or _cgets() or _kbhit() is called. */ if ( _coninpfh == -2 ) __initconin(); if ( _coninpfh != -1 ) { GetConsoleMode( (HANDLE)_coninpfh, &oldstate ); SetConsoleMode( (HANDLE)_coninpfh, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT ); // First try usual way just as _cgets if ( bUseW) { if ( !ReadConsoleW( (HANDLE)_coninpfh, (LPVOID)string, (DWORD)sizeInWords, &num_read, NULL ) ) { if ( bUseW == 2 ) { if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) bUseW = FALSE; else bUseW = TRUE; } } else { bUseW = TRUE; /* set length of string and null terminate it */ if (string[num_read - 2] == L'\r') { (*pSizeRead) += num_read - 2; string[num_read - 2] = L'\0'; } else if ( (num_read == sizeInWords) && (string[num_read - 1] == L'\r') ) { /* special case 1 - \r\n straddles the boundary */ (*pSizeRead) += num_read -1; string[num_read - 1] = L'\0'; } else if ( (num_read == 1) && (string[0] == L'\n') ) { /* special case 2 - read a single '\n'*/ string[0] = L'\0'; (*pSizeRead) += 0; } else { (*pSizeRead) += num_read; string[num_read] = L'\0'; } } } // If ReadConsoleW is not present, use ReadConsoleA and then convert // to Wide Char. if ( !bUseW) { static char AStr[BUF_MAX_LEN +1]; static int in_buff = 0, was_buff_full = 0; unsigned int Copy, Sz, consoleCP; unsigned int last_read = 0, i; consoleCP = GetConsoleCP(); do { if (!in_buff) { if ( ReadConsoleA( (HANDLE)_coninpfh, (LPVOID)AStr, BUF_MAX_LEN, &num_read, NULL) && num_read <= BUF_MAX_LEN ) { if (num_read >= 2 && AStr[num_read -2] == '\r') { AStr[num_read -2] = '\0'; } else if (num_read == BUF_MAX_LEN && AStr[num_read -1] == '\r') AStr[num_read -1] = '\0'; else if (num_read == 1 && AStr[0] == '\n') AStr[0] = '\0'; else AStr[num_read] = '\0'; } else { _dosmaperr(GetLastError()); err = errno; } } for ( i = 0; AStr[i] != '\0' && i < (BUF_MAX_LEN) && last_read < sizeInWords; i += Sz) { // Check if this character is lead byte. If yes, the size // of this character is 2. Else 1. if ( IsDBCSLeadByteEx( GetConsoleCP(), AStr[i])) Sz = 2; else Sz = 1; if ( (Copy = MultiByteToWideChar( consoleCP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, &AStr[i], Sz, &string[last_read], (int)sizeInWords - last_read))) { last_read += Copy; } } // Check if this conversion was from buffer. If yes, was // buffer fully filled when it was first read using // ReadConsoleA. If the buffer not fully filled, we don't need // to read more from buffer. This is necessary to make it // behave same as if we are reading using ReadConsoleW. if ( in_buff && i == strlen(AStr)) { in_buff = 0; if ( was_buff_full) { was_buff_full = 0; continue; } else { break; } } else if ( i < (BUF_MAX_LEN)) break; } while (last_read < sizeInWords); // We save the buffer to be used again. if ( i < strlen(AStr)) { in_buff = 1; if ( strlen(AStr) == (BUF_MAX_LEN)) was_buff_full = 1; memmove(AStr, &AStr[i], BUF_MAX_LEN +1 - i); } string[last_read] = '\0'; (*pSizeRead) += last_read; } SetConsoleMode( (HANDLE)_coninpfh, oldstate ); } else { _dosmaperr(GetLastError()); err = errno; } } __FINALLY _munlock(_CONIO_LOCK); /* unlock the console */ __END_TRY_FINALLY if (err != 0) { errno = err; } return err; }
static BOOL ReadString( IN UINT uIdResourcePrompt, IN OUT PWSTR Buffer, IN DWORD BufferLength, IN BOOL ShowString) { DWORD count, i; WCHAR charToDisplay[] = { 0, UNICODE_NULL }; if (!SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), 0)) return FALSE; if (!FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE))) return FALSE; if (!DisplayResourceText(uIdResourcePrompt, FALSE)) return FALSE; i = 0; for (;;) { WCHAR readChar; if (!ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), &readChar, 1, &count, NULL)) return FALSE; if (readChar == '\r' || readChar == '\n') { /* End of string */ charToDisplay[0] = L'\n'; WriteConsoleW( GetStdHandle(STD_OUTPUT_HANDLE), charToDisplay, wcslen(charToDisplay), &count, NULL); break; } if (ShowString) { /* Display the char */ charToDisplay[0] = readChar; WriteConsoleW( GetStdHandle(STD_OUTPUT_HANDLE), charToDisplay, wcslen(charToDisplay), &count, NULL); } Buffer[i++] = readChar; /* FIXME: buffer overflow if the user writes too many chars! */ UNREFERENCED_PARAMETER(BufferLength); /* FIXME: handle backspace */ } Buffer[i] = UNICODE_NULL; if (!ShowString) { /* Still display the \n */ static LPCWSTR newLine = L"\n"; DWORD result; WriteConsoleW( GetStdHandle(STD_OUTPUT_HANDLE), newLine, wcslen(newLine), &result, NULL); } return TRUE; }
arx_error arx_query(arx_utf8 const **string) { arx_error error = 0; #ifndef __WINDOWS__ int descriptor = -1; arx_handle codec = NULL; char terminal[L_ctermid + 1] = {0}; #else arx_handle utf16codec = NULL; arx_handle utf8codec = NULL; HANDLE descriptor = INVALID_HANDLE_VALUE; #endif static arx_utf8 storage[8192] = {0}; arx_utf8 *iter = storage; if (string == NULL) return arx_argerror(); #ifndef __WINDOWS__ if (ctermid(terminal) == NULL) { error = arx_unixerror(ENOTTY); goto cleanup; } if ((descriptor = open(terminal, O_RDWR, (S_IRWXU | S_IRWXG | S_IRWXO))) == -1) { error = arx_unixerror(errno); goto cleanup; } if ((error = arx_utf8codec('s', &codec))) { goto cleanup; } #else if ((descriptor = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { return arx_winerror(GetLastError()); } if ((error = arx_utf8codec('s', &utf8codec))) { goto cleanup; } if ((error = arx_utf16codec('s', arx_none, &utf16codec))) { goto cleanup; } #endif memset(storage, 0, sizeof(storage)); while (1) { #ifdef __WINDOWS__ DWORD wcount = 0; WCHAR wdata[ARX_QUERY_RUNES * sizeof(WCHAR)]; #endif arx_count total = 0; arx_count count = 0; arx_byte bytes[ARX_QUERY_BYTES]; arx_rune runes[ARX_QUERY_RUNES]; #ifndef __WINDOWS__ arx_count actual = 0; for (count = 1; count <= ARX_QUERY_BYTES; ++count) { actual = (arx_count)read(descriptor, &bytes[count - 1], 1); if (actual == (arx_count)-1) { error = arx_unixerror(errno); goto cleanup; } else if (actual == 0) { break; } if ((error = arx_decode(codec, bytes, count, runes, ARX_QUERY_RUNES, NULL))) { if (error != arx_ucerror(ARX_UCERROR_INCOMPLETE)) { goto cleanup; } } else { break; } } #else for (wcount = 1; wcount <= (sizeof(wdata) / sizeof(WCHAR)); ++wcount) { DWORD actual = 0; if (!ReadConsoleW(descriptor, &wdata[wcount - 1], wcount, &actual, NULL)) { error = arx_winerror(GetLastError()); goto cleanup; } memcpy(bytes, wdata, (count = (actual * sizeof(WCHAR)))); if ((error = arx_decode(utf16codec, bytes, count, runes, ARX_QUERY_RUNES, &count))) { if (error != arx_ucerror(ARX_UCERROR_INCOMPLETE)) { goto cleanup; } } else { break; } } if ((error = arx_encode(utf8codec, runes, count, bytes, ARX_QUERY_BYTES, &count))) { goto cleanup; } #endif if ((total + count) >= sizeof(storage)) { error = arx_memerror(); goto cleanup; } #ifndef __WINDOWS__ if ((count == 1) && (bytes[0] == '\n')) { break; } #else if ((count == 1) && (bytes[0] == '\n')) { *(--iter) = '\0'; break; } #endif memcpy(iter, bytes, count); total += count; iter += count; } cleanup: *iter = '\0'; *string = storage; #ifndef __WINDOWS__ if (descriptor != -1) { close(descriptor); } arx_close(codec); #else arx_close(utf16codec); arx_close(utf8codec); #endif return error; }
static bool get_console_input_win32 (const char *prompt, const bool echo, char *input, const int capacity) { HANDLE in = INVALID_HANDLE_VALUE; HANDLE err = INVALID_HANDLE_VALUE; DWORD len = 0; ASSERT (prompt); ASSERT (input); ASSERT (capacity > 0); input[0] = '\0'; in = GetStdHandle (STD_INPUT_HANDLE); err = get_orig_stderr (); if (in != INVALID_HANDLE_VALUE && err != INVALID_HANDLE_VALUE && !win32_service_interrupt (&win32_signal) && WriteFile (err, prompt, strlen (prompt), &len, NULL)) { bool is_console = (GetFileType (in) == FILE_TYPE_CHAR); DWORD flags_save = 0; int status = 0; WCHAR *winput; if (is_console) { if (GetConsoleMode (in, &flags_save)) { DWORD flags = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; if (echo) flags |= ENABLE_ECHO_INPUT; SetConsoleMode (in, flags); } else is_console = 0; } if (is_console) { winput = malloc (capacity * sizeof (WCHAR)); if (winput == NULL) return false; status = ReadConsoleW (in, winput, capacity, &len, NULL); WideCharToMultiByte (CP_UTF8, 0, winput, len, input, capacity, NULL, NULL); free (winput); } else status = ReadFile (in, input, capacity, &len, NULL); string_null_terminate (input, (int)len, capacity); chomp (input); if (!echo) WriteFile (err, "\r\n", 2, &len, NULL); if (is_console) SetConsoleMode (in, flags_save); if (status && !win32_service_interrupt (&win32_signal)) return true; } return false; }
/* putc() with code conversion */ int putc2(int c, FILE *fp) { static int num[NOFILE]; /* 0 : not in Kanji 1..4 : in JIS Kanji and num[] bytes are in store[][] -1 : in JIS Kanji and store[][] is empty */ static unsigned char store[NOFILE][4]; const int fd = fileno(fp); int ret = c, output_enc; #ifdef WIN32 if ((fp == stdout || fp == stderr) && (_isatty(fd) || !prior_file_enc)) { if (sjisterminal) { if (is_internalUPTEX()) output_enc = ENC_UTF8; else output_enc = ENC_SJIS; } else #else if ((fp == stdout || fp == stderr) && !prior_file_enc) { #endif output_enc = get_terminal_enc(); } else output_enc = get_file_enc(); if (num[fd] > 0) { /* multi-byte char */ if (is_internalUPTEX() && iskanji1(c)) { /* error */ ret = flush(store[fd], num[fd], fp); num[fd] = 0; } store[fd][num[fd]] = c; num[fd]++; if (multistrlen(store[fd], num[fd], 0) == num[fd]) { long i = fromBUFF(store[fd], num[fd], 0); ret = put_multibyte(toENC(i, output_enc), fp); num[fd] = -1; } else if ((is_internalUPTEX() && num[fd] == 4) || (!is_internalUPTEX() && num[fd] == 2)) { /* error */ ret = flush(store[fd], num[fd], fp); num[fd] = -1; } } else if (iskanji1(c)) { /* first multi-byte char */ if (num[fd] == 0 && output_enc == ENC_JIS) { ret = put_multibyte(KANJI_IN, fp); } store[fd][0] = c; num[fd] = 1; } else { /* ASCII */ if (num[fd] < 0 && output_enc == ENC_JIS) { put_multibyte(KANJI_OUT, fp); } ret = putc(c, fp); num[fd] = 0; } return ret; } /* fputs() with code conversion */ int fputs2(const char *s, FILE *fp) { while (*s != '\0') { int ret = putc2((unsigned char)*s, fp); if (ret == EOF) return EOF; s++; } return 1; } static struct unget_st { int size; int buff[4]; } ungetbuff[NOFILE]; static int getc4(FILE *fp) { struct unget_st *p = &ungetbuff[fileno(fp)]; if (p->size == 0) #ifdef WIN32 { const int fd = fileno(fp); HANDLE hStdin; DWORD ret; wchar_t wc[2]; long c; static wchar_t wcbuf = L'\0'; if (!(fd == fileno(stdin) && _isatty(fd) && is_internalUPTEX())) return getc(fp); hStdin = GetStdHandle(STD_INPUT_HANDLE); if (wcbuf) { wc[0] = wcbuf; wcbuf = L'\0'; } else if (ReadConsoleW(hStdin, wc, 1, &ret, NULL) == 0) return EOF; if (0xd800<=wc[0] && wc[0]<0xdc00) { if (ReadConsoleW(hStdin, wc+1, 1, &ret, NULL) == 0) return EOF; if (0xdc00<=wc[1] && wc[1]<0xe000) { c = UTF16StoUTF32(wc[0], wc[1]); } else { wcbuf = wc[1]; c = U_REPLACEMENT_CHARACTER; /* illegal upper surrogate pair */ } } else if (0xdc00<=wc[0] && wc[0]<0xe000) { c = U_REPLACEMENT_CHARACTER; /* illegal lower surrogate pair */ } else { c = wc[0]; } c = UCStoUTF8(c); /* always */ p->buff[p->size++]=BYTE4(c); if (BYTE3(c) != 0) p->buff[p->size++]=BYTE3(c); if (BYTE2(c) != 0) p->buff[p->size++]=BYTE2(c); if (BYTE1(c) != 0) p->buff[p->size++]=BYTE1(c); } #else return getc(fp); #endif return p->buff[--p->size]; } static int ungetc4(int c, FILE *fp) { struct unget_st *p = &ungetbuff[fileno(fp)]; if (p->size >= 4) return EOF; return p->buff[p->size++] = c; } static unsigned char *buffer; static long first, last; static boolean combin_voiced_sound(boolean semi) { int i, mblen; mblen = is_internalUPTEX() ? 3 : 2; if (last-mblen < first) return false; if (multistrlen(buffer,last,last-mblen) != mblen) return false; i = toUCS(fromBUFF(buffer,last,last-mblen)); i = get_voiced_sound(i, semi); if (i == 0) return false; i = toBUFF(fromUCS(i)); if (BYTE2(i) != 0) buffer[last-3] = BYTE2(i); /* always */ buffer[last-2] = BYTE3(i); /* always */ buffer[last-1] = BYTE4(i); return true; }
// reads at most maxlength chars without echoing to the terminal into buf bool read_from_keyboard(char* buf, int maxlength, bool echo) { #if !defined(WIN32) int ch, ch_count; ch = ch_count = 0; fflush(stdout); const char end_char = '\n'; if (!echo) echo_off(); while ( ch_count < maxlength-1 ) { ch = getchar(); if ( ch == end_char ) { break; } else if ( ch == '\b') { // backspace if ( ch_count > 0 ) { ch_count--; } continue; } else if ( ch == '\003' ) { // CTRL-C return FALSE; } buf[ch_count++] = (char) ch; } buf[ch_count] = '\0'; if (!echo) echo_on(); #else /* The Windows method for getting keyboard input is very different due to issues encountered by British users trying to use the pound character in their passwords. _getch did not accept any input from using the alt+#### method of inputting characters nor the pound symbol when using a British keyboard layout. The solution was to explicitly use ReadConsoleW, the unicode version of ReadConsole, to take in the password and down convert it into ascii. See Ticket #1639 */ HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); /* There is a difference between the code page the console is reporting and the code page that needs to be used for the ascii conversion. Below code acts to provide additional debug information should the need arise. */ //UINT cPage = GetConsoleCP(); //printf("Console CP: %d\n", cPage); //Preserve the previous console mode and switch back once input is complete. DWORD oldMode; GetConsoleMode(hStdin, &oldMode); //Default entry method is to not echo back what is entered. DWORD newMode = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; if(echo) { newMode |= ENABLE_ECHO_INPUT; } SetConsoleMode(hStdin, newMode); int cch; //maxlength is passed in even though it is a fairly constant value, so need to dynamically allocate. wchar_t *wbuffer = new wchar_t[maxlength]; if(!wbuffer) { return FALSE; } ReadConsoleW(hStdin, wbuffer, maxlength, (DWORD*)&cch, NULL); SetConsoleMode(hStdin, oldMode); //Zero terminate the input. cch = min(cch, maxlength-1); wbuffer[cch] = '\0'; --cch; //Strip out the newline and return that ReadConsoleW appends and zero terminate again. while (cch >= 0) { if(wbuffer[cch] == '\r' || wbuffer[cch] == '\n') wbuffer[cch] = '\0'; else break; --cch; } //Down convert the input into ASCII. int converted = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, wbuffer, -1, buf, maxlength, NULL, NULL); delete[] wbuffer; #endif return TRUE; }