| /* liblouis Braille Translation and Back-Translation Library |
| |
| Based on the Linux screenreader BRLTTY, copyright (C) 1999-2006 by The |
| BRLTTY Team |
| |
| Copyright (C) 2004, 2005, 2006 ViewPlus Technologies, Inc. www.viewplus.com |
| Copyright (C) 2004, 2005, 2006 JJB Software, Inc. www.jjb-software.com |
| Copyright (C) 2016 Mike Gray, American Printing House for the Blind |
| Copyright (C) 2016 Davy Kager, Dedicon |
| |
| This file is part of liblouis. |
| |
| liblouis is free software: you can redistribute it and/or modify it |
| under the terms of the GNU Lesser General Public License as published |
| by the Free Software Foundation, either version 2.1 of the License, or |
| (at your option) any later version. |
| |
| liblouis is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with liblouis. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| /** |
| * @file |
| * @brief Common utility functions |
| */ |
| |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <stdarg.h> |
| #include <string.h> |
| #include <ctype.h> |
| #include <sys/stat.h> |
| |
| #include "internal.h" |
| #include "config.h" |
| |
| /* Contributed by Michel Such <michel.such@free.fr> */ |
| #ifdef _WIN32 |
| |
| /* Adapted from BRLTTY code (see sys_progs_wihdows.h) */ |
| |
| #include <shlobj.h> |
| |
| static void * |
| reallocWrapper(void *address, size_t size) { |
| if (!(address = realloc(address, size)) && size) _lou_outOfMemory(); |
| return address; |
| } |
| |
| static char * |
| strdupWrapper(const char *string) { |
| char *address = strdup(string); |
| if (!address) _lou_outOfMemory(); |
| return address; |
| } |
| |
| char *EXPORT_CALL |
| lou_getProgramPath(void) { |
| char *path = NULL; |
| HMODULE handle; |
| |
| if ((handle = GetModuleHandle(NULL))) { |
| DWORD size = 0X80; |
| char *buffer = NULL; |
| |
| while (1) { |
| buffer = reallocWrapper(buffer, size <<= 1); |
| |
| { |
| // As the "UNICODE" Windows define may have been set at compilation, |
| // This call must be specifically GetModuleFilenameA as further code |
| // expects it to be single byte chars. |
| DWORD length = GetModuleFileNameA(handle, buffer, size); |
| |
| if (!length) { |
| printf("GetModuleFileName\n"); |
| exit(3); |
| } |
| |
| if (length < size) { |
| buffer[length] = 0; |
| path = strdupWrapper(buffer); |
| |
| while (length > 0) |
| if (path[--length] == '\\') break; |
| |
| strncpy(path, path, length + 1); |
| path[length + 1] = '\0'; |
| break; |
| } |
| } |
| } |
| |
| free(buffer); |
| } else { |
| printf("GetModuleHandle\n"); |
| exit(3); |
| } |
| |
| return path; |
| } |
| #endif |
| /* End of MS contribution */ |
| |
| int EXPORT_CALL |
| _lou_stringHash(const widechar *c) { |
| /* hash function for strings */ |
| unsigned long int makeHash = |
| (((unsigned long int)c[0] << 8) + (unsigned long int)c[1]) % HASHNUM; |
| return (int)makeHash; |
| } |
| |
| int EXPORT_CALL |
| _lou_charHash(widechar c) { |
| unsigned long int makeHash = (unsigned long int)c % HASHNUM; |
| return (int)makeHash; |
| } |
| |
| char *EXPORT_CALL |
| _lou_showString(widechar const *chars, int length) { |
| /* Translate a string of characters to the encoding used in character |
| * operands */ |
| int charPos; |
| int bufPos = 0; |
| static char scratchBuf[MAXSTRING]; |
| scratchBuf[bufPos++] = '\''; |
| for (charPos = 0; charPos < length && bufPos < (MAXSTRING - 2); charPos++) { |
| if (chars[charPos] >= 32 && chars[charPos] < 127) |
| scratchBuf[bufPos++] = (char)chars[charPos]; |
| else { |
| char hexbuf[20]; |
| int hexLength; |
| char escapeLetter; |
| |
| int leadingZeros; |
| int hexPos; |
| hexLength = sprintf(hexbuf, "%x", chars[charPos]); |
| switch (hexLength) { |
| case 1: |
| case 2: |
| case 3: |
| case 4: |
| escapeLetter = 'x'; |
| leadingZeros = 4 - hexLength; |
| break; |
| case 5: |
| escapeLetter = 'y'; |
| leadingZeros = 0; |
| break; |
| case 6: |
| case 7: |
| case 8: |
| escapeLetter = 'z'; |
| leadingZeros = 8 - hexLength; |
| break; |
| default: |
| escapeLetter = '?'; |
| leadingZeros = 0; |
| break; |
| } |
| if ((bufPos + leadingZeros + hexLength + 4) >= (MAXSTRING - 2)) break; |
| scratchBuf[bufPos++] = '\\'; |
| scratchBuf[bufPos++] = escapeLetter; |
| for (hexPos = 0; hexPos < leadingZeros; hexPos++) scratchBuf[bufPos++] = '0'; |
| for (hexPos = 0; hexPos < hexLength; hexPos++) |
| scratchBuf[bufPos++] = hexbuf[hexPos]; |
| } |
| } |
| scratchBuf[bufPos++] = '\''; |
| scratchBuf[bufPos] = 0; |
| return scratchBuf; |
| } |
| |
| /** |
| * Translate a sequence of dots to the encoding used in dots operands. |
| */ |
| char *EXPORT_CALL |
| _lou_showDots(widechar const *dots, int length) { |
| int bufPos = 0; |
| static char scratchBuf[MAXSTRING]; |
| for (int dotsPos = 0; dotsPos < length && bufPos < (MAXSTRING - 1); dotsPos++) { |
| for (int mappingPos = 0; dotMapping[mappingPos].key; mappingPos++) { |
| if ((dots[dotsPos] & dotMapping[mappingPos].key) && |
| (bufPos < (MAXSTRING - 1))) |
| scratchBuf[bufPos++] = dotMapping[mappingPos].value; |
| } |
| if ((dots[dotsPos] == B16) && (bufPos < (MAXSTRING - 1))) |
| scratchBuf[bufPos++] = '0'; |
| if ((dotsPos != length - 1) && (bufPos < (MAXSTRING - 1))) |
| scratchBuf[bufPos++] = '-'; |
| } |
| scratchBuf[bufPos] = 0; |
| return scratchBuf; |
| } |
| |
| /** |
| * Mapping between character attribute and textual representation |
| */ |
| const static intCharTupple attributeMapping[] = { |
| { CTC_Space, 's' }, { CTC_Letter, 'l' }, { CTC_Digit, 'd' }, { CTC_Punctuation, 'p' }, |
| { CTC_UpperCase, 'U' }, { CTC_LowerCase, 'u' }, { CTC_Math, 'm' }, { CTC_Sign, 'S' }, |
| { CTC_LitDigit, 'D' }, { CTC_Class1, 'w' }, { CTC_Class2, 'x' }, { CTC_Class3, 'y' }, |
| { CTC_Class4, 'z' }, 0, |
| }; |
| |
| /** |
| * Show attributes using the letters used after the $ in multipass |
| * opcodes. |
| */ |
| char *EXPORT_CALL |
| _lou_showAttributes(TranslationTableCharacterAttributes a) { |
| int bufPos = 0; |
| static char scratchBuf[MAXSTRING]; |
| for (int mappingPos = 0; attributeMapping[mappingPos].key; mappingPos++) { |
| if ((a & attributeMapping[mappingPos].key) && bufPos < (MAXSTRING - 1)) |
| scratchBuf[bufPos++] = attributeMapping[mappingPos].value; |
| } |
| scratchBuf[bufPos] = 0; |
| return scratchBuf; |
| } |
| |
| void EXPORT_CALL |
| _lou_outOfMemory(void) { |
| _lou_logMessage(LOG_FATAL, "liblouis: Insufficient memory\n"); |
| exit(3); |
| } |
| |
| #ifdef DEBUG |
| void EXPORT_CALL |
| _lou_debugHook(void) { |
| char *hook = "debug hook"; |
| printf("%s\n", hook); |
| } |
| #endif |