// Small module for correct Russian localization of programs written in C/C++ under Windows #pragma once #include #include #include #include #include #define WT _T // WT = widechar text - Macro for declaring constant widechar strings #define W_SET wmemset // Memset for wchar // Internal functions of the module, not intended for use in user code int set_unicode_mode(void); // Enable unicode mode int set_default_mode(void); // Enable default mode // void wwrite(TCHAR* dst, size_t dst_size); // Input wide char characters from console into array void wprint(wchar_t* format, ...); // Formatted output of wide char array to console void bwprint(wchar_t* arr, size_t size); // Output wide char array in binary form to console void bcprint(char* arr, size_t size); // Output char array in binary form to console TCHAR* ctow(char* arr1, TCHAR* arr2); // Converts char array to wide char array char* wtoc(TCHAR* arr1, char* arr2); // Converts wide char array to char array enum COD3K_ERRORS { SETMODE_ERROR_STDIN = -228, SETMODE_ERROR_STDOUT, SETMODE_ERROR_STDERR }; // Enable Unicode mode int set_unicode_mode(void) { int err_inp, err_out, err_err; if ((err_inp = _setmode(_fileno(stdin), _O_WTEXT)) == -1) { // Unicode mode for input stream return SETMODE_ERROR_STDIN; } if ((err_inp = _setmode(_fileno(stdout), _O_WTEXT)) == -1) { // Unicode mode for output stream return SETMODE_ERROR_STDOUT; } if ((err_err = _setmode(_fileno(stderr), _O_WTEXT)) == -1) { // Unicode mode for error stream return SETMODE_ERROR_STDERR; } } // Disable Unicode mode int set_default_mode(void) { int err_inp, err_out, err_err; if ((err_inp = _setmode(_fileno(stdin), _O_TEXT)) == -1) { // Restore mode for input stream return SETMODE_ERROR_STDIN; } if ((err_out = _setmode(_fileno(stdout), _O_TEXT)) == -1) { // Restore mode for output stream return SETMODE_ERROR_STDOUT; } if ((err_err = _setmode(_fileno(stderr), _O_TEXT)) == -1) { // Restore mode for error stream return SETMODE_ERROR_STDERR; } return 0; } // Formatted output of wide char array to console void wprint(const wchar_t* format, ...) { set_unicode_mode(); va_list args; va_start(args, format); vfwprintf(stdout, format, args); va_end(args); set_default_mode(); } // Function to print the first 'size' characters of wchar_t array in binary form void bwprint(wchar_t* arr, size_t size) { for (size_t i = 0; i < size; i++) { for (int j = sizeof(wchar_t) * 8 - 1; j >= 0; j--) { putchar((arr[i] & (1 << j)) ? '1' : '0'); } putchar(' '); } putchar('\n'); } // Function to print the first 'size' characters of char array in binary form void bcprint(char* arr, size_t size) { for (size_t i = 0; i < size; i++) { for (int j = sizeof(char) * 8 - 1; j >= 0; j--) { putchar((arr[i] & (1 << j)) ? '1' : '0'); } putchar(' '); } putchar('\n'); } // dst - TCHAR a.k.a wchar_t array, into which characters from console will be written, size - size of this array // removes newline character void wwrite(TCHAR* dst, size_t dst_size) { set_unicode_mode(); fgetws(dst, dst_size, stdin); dst[wcslen(dst) - 1] = 0; set_default_mode(); } // char to wide char conversion TCHAR* ctow(char* arr1, TCHAR* arr2) { int i = 0; for (char* p_byte = arr1; *p_byte != 0; ++p_byte) { char byte = *p_byte; if (byte & 0x80) { // bit at position 8 is set => Russian text // clear bit at position 8 + // set bit at position 11 (this is necessary for correct wide char if the text is not ASCII) arr2[i] = byte & 0x7F | 0x400; } else { // English text arr2[i] = byte; } ++i; } return arr2; } // widechar to char char* wtoc(TCHAR* arr1, char* arr2) { int i = 0; for (TCHAR* p_wbyte = arr1; *p_wbyte != 0; ++p_wbyte) { TCHAR wbyte = *p_wbyte; arr2[i] = (char)(wbyte & 0xFF); // lower 8 bits if (wbyte & 0x400) { // if the 11th bit is set, the text is Russian arr2[i] |= 0x80; // marker for Russian text in char - set the 8th bit } ++i; } return arr2; }