mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-29 14:38:29 +00:00
os2: add port files for SDL2-2.0.4 from Andrey Vasilkin
only geniconv/iconv.h (was from LGPL libiconv) is replaced with a generic minimal iconv.h based on public knowledge.
This commit is contained in:
36
src/core/os2/SDL_os2.c
Normal file
36
src/core/os2/SDL_os2.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if defined(__OS2__)
|
||||
|
||||
#include "core/os2/geniconv/geniconv.h"
|
||||
|
||||
// SDL_OS2Quit() will be called from SDL_QuitSubSystem().
|
||||
|
||||
void SDL_OS2Quit()
|
||||
{
|
||||
// Unload DLL used for iconv. We can do it at any time and use iconv again -
|
||||
// dynamic library will be loaded on first call iconv_open() (see geniconv).
|
||||
libiconv_clean();
|
||||
}
|
||||
|
||||
#endif
|
31
src/core/os2/SDL_os2.h
Normal file
31
src/core/os2/SDL_os2.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef _SDL_os2_h
|
||||
#define _SDL_os2_h
|
||||
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include ".\src\core\os2\geniconv\geniconv.h"
|
||||
|
||||
#if OS2DEBUG==SDLOUTPUT
|
||||
|
||||
# define debug(s,...) SDL_LogDebug( SDL_LOG_CATEGORY_APPLICATION, \
|
||||
__func__"(): "##s, ##__VA_ARGS__ )
|
||||
|
||||
#elif defined(OS2DEBUG)
|
||||
|
||||
# define debug(s,...) printf( __func__"(): "##s"\n", ##__VA_ARGS__ )
|
||||
|
||||
#else
|
||||
|
||||
# define debug(s,...)
|
||||
|
||||
#endif // OS2DEBUG
|
||||
|
||||
|
||||
// StrUTF8New() - geniconv\sys2utf8.c.
|
||||
#define OS2_SysToUTF8(S) StrUTF8New( 1, S, SDL_strlen( S ) + 1 )
|
||||
#define OS2_UTF8ToSys(S) StrUTF8New( 0, (char *)(S), SDL_strlen( S ) + 1 )
|
||||
|
||||
// SDL_OS2Quit() will be called from SDL_QuitSubSystem().
|
||||
void SDL_OS2Quit();
|
||||
|
||||
#endif // _SDL_os2_h
|
143
src/core/os2/geniconv/geniconv.c
Normal file
143
src/core/os2/geniconv/geniconv.c
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Universal iconv implementation for OS/2.
|
||||
|
||||
Andrey Vasilkin, 2016.
|
||||
*/
|
||||
|
||||
#define INCL_DOSMODULEMGR /* Module Manager values */
|
||||
#define INCL_DOSERRORS /* Error values */
|
||||
#include <os2.h>
|
||||
#include <iconv.h>
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# include <stdio.h>
|
||||
# define debug(s,...) printf(__func__"(): "##s"\n" ,##__VA_ARGS__)
|
||||
#else
|
||||
# define debug(s,...)
|
||||
#endif
|
||||
|
||||
// Exports from os2iconv.c.
|
||||
extern iconv_t _System os2_iconv_open(const char* tocode, const char* fromcode);
|
||||
extern size_t _System os2_iconv(iconv_t cd, char* * inbuf,
|
||||
size_t *inbytesleft, char* * outbuf,
|
||||
size_t *outbytesleft);
|
||||
extern int _System os2_iconv_close(iconv_t cd);
|
||||
|
||||
// Functions pointers types.
|
||||
typedef iconv_t _System (*FNICONV_OPEN)(const char* tocode, const char* fromcode);
|
||||
typedef size_t _System (*FNICONV)(iconv_t cd, char* * inbuf,
|
||||
size_t *inbytesleft, char* * outbuf,
|
||||
size_t *outbytesleft);
|
||||
typedef int _System (*FNICONV_CLOSE)(iconv_t cd);
|
||||
|
||||
// Used DLL module handle.
|
||||
static HMODULE hmIconv = NULLHANDLE;
|
||||
// Functions pointers.
|
||||
static FNICONV_OPEN fn_iconv_open = NULL;
|
||||
static FNICONV fn_iconv = NULL;
|
||||
static FNICONV_CLOSE fn_iconv_close = NULL;
|
||||
|
||||
|
||||
static BOOL _loadDLL(PSZ pszName, PSZ pszIconvOpen, PSZ pszIconv,
|
||||
PSZ pszIconvClose)
|
||||
{
|
||||
ULONG ulRC;
|
||||
CHAR acError[256];
|
||||
|
||||
ulRC = DosLoadModule( &acError, sizeof(acError), pszName, &hmIconv );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DLL not loaded: %s", &acError );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ulRC = DosQueryProcAddr( hmIconv, 0, pszIconvOpen, (PFN *)&fn_iconv_open );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "Error: cannot find entry %s in %s", pszIconvOpen, pszName );
|
||||
break;
|
||||
}
|
||||
|
||||
ulRC = DosQueryProcAddr( hmIconv, 0, pszIconv, (PFN *)&fn_iconv );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "Error: cannot find entry %s in %s", pszIconv, pszName );
|
||||
break;
|
||||
}
|
||||
|
||||
ulRC = DosQueryProcAddr( hmIconv, 0, pszIconvClose, (PFN *)&fn_iconv_close );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "Error: cannot find entry %s in %s", pszIconvClose, pszName );
|
||||
break;
|
||||
}
|
||||
|
||||
debug( "DLL %s used", pszName );
|
||||
return TRUE;
|
||||
}
|
||||
while( FALSE );
|
||||
|
||||
DosFreeModule( hmIconv );
|
||||
hmIconv = NULLHANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void _init()
|
||||
{
|
||||
if ( fn_iconv_open != NULL )
|
||||
// Already was initialized.
|
||||
return;
|
||||
|
||||
// Try to load kiconv.dll, iconv2.dll or iconv.dll.
|
||||
if ( !_loadDLL( "KICONV", "_libiconv_open", "_libiconv", "_libiconv_close" )
|
||||
&& !_loadDLL( "ICONV2", "_libiconv_open", "_libiconv", "_libiconv_close" )
|
||||
&& !_loadDLL( "ICONV", "_iconv_open", "_iconv", "_iconv_close" ) )
|
||||
{
|
||||
// No one DLL was loaded - use OS/2 conversion objects API.
|
||||
|
||||
debug( "Uni*() API used" );
|
||||
fn_iconv_open = os2_iconv_open;
|
||||
fn_iconv = os2_iconv;
|
||||
fn_iconv_close = os2_iconv_close;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Public routines.
|
||||
// ----------------
|
||||
|
||||
// Non-standard function for iconv to unload the used dynamic library.
|
||||
void libiconv_clean()
|
||||
{
|
||||
if ( hmIconv != NULLHANDLE )
|
||||
{
|
||||
DosFreeModule( hmIconv );
|
||||
hmIconv = NULLHANDLE;
|
||||
|
||||
fn_iconv_open = NULL;
|
||||
fn_iconv = NULL;
|
||||
fn_iconv_close = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
iconv_t libiconv_open(const char* tocode, const char* fromcode)
|
||||
{
|
||||
_init();
|
||||
return fn_iconv_open( tocode, fromcode );
|
||||
}
|
||||
|
||||
size_t libiconv(iconv_t cd, char* * inbuf, size_t *inbytesleft,
|
||||
char* * outbuf, size_t *outbytesleft)
|
||||
{
|
||||
return fn_iconv( cd, inbuf, inbytesleft, outbuf, outbytesleft );
|
||||
}
|
||||
|
||||
int libiconv_close(iconv_t cd)
|
||||
{
|
||||
return fn_iconv_close( cd );
|
||||
}
|
59
src/core/os2/geniconv/geniconv.h
Normal file
59
src/core/os2/geniconv/geniconv.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Universal iconv implementation for OS/2.
|
||||
|
||||
Andrey Vasilkin, 2016.
|
||||
*/
|
||||
|
||||
#ifndef GENICONV_H
|
||||
#define GENICONV_H
|
||||
|
||||
#include <iconv.h>
|
||||
|
||||
#ifdef iconv_open
|
||||
#undef iconv_open
|
||||
#endif
|
||||
#define iconv_open libiconv_open
|
||||
|
||||
#ifdef iconv
|
||||
#undef iconv
|
||||
#endif
|
||||
#define iconv libiconv
|
||||
|
||||
#ifdef iconv_close
|
||||
#undef iconv_close
|
||||
#endif
|
||||
#define iconv_close libiconv_close
|
||||
|
||||
#define iconv_clean libiconv_clean
|
||||
|
||||
// Non-standard function for iconv to unload the used dynamic library.
|
||||
void libiconv_clean();
|
||||
|
||||
iconv_t libiconv_open(const char* tocode, const char* fromcode);
|
||||
size_t libiconv(iconv_t cd, char* * inbuf, size_t *inbytesleft,
|
||||
char* * outbuf, size_t *outbytesleft);
|
||||
int libiconv_close(iconv_t cd);
|
||||
|
||||
// System codepage <-> UTF-8.
|
||||
|
||||
// StrUTF8()
|
||||
// Coverts string from system cp. to UTF-8 (fToUTF8 is not 0) or from UTF-8 to
|
||||
// the system cp. (fToUTF8 is 0). Converted ASCIIZ string will be placed at the
|
||||
// buffer pcDst, up to cbDst - 1 (for sys->utf8) or 2 (for utf8->sys) bytes.
|
||||
// Returns the number of bytes written into pcDst, not counting the terminating
|
||||
// 0 byte(s) or -1 on error.
|
||||
int StrUTF8(int fToUTF8, char *pcDst, int cbDst, char *pcSrc, int cbSrc);
|
||||
|
||||
// StrUTF8New()
|
||||
// Coverts string from system cp. to UTF-8 (fToUTF8 is not 0) or from UTF-8 to
|
||||
// the system cp. (fToUTF8 is 0). Memory for the new string is obtained by
|
||||
// using libc malloc().
|
||||
// Returns converted string, terminating two bytes 0 is appended to the result.
|
||||
// Returns null on error.
|
||||
char *StrUTF8New(int fToUTF8, char *pcStr, int cbStr);
|
||||
|
||||
// StrUTF8Free()
|
||||
// Deallocates the memory block located by StrUTF8New() (just libc free()).
|
||||
void StrUTF8Free(char *pszStr);
|
||||
|
||||
#endif // GENICONV_H
|
21
src/core/os2/geniconv/iconv.h
Normal file
21
src/core/os2/geniconv/iconv.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef ICONV_H_ /* minimal iconv.h header based on public knowledge */
|
||||
#define ICONV_H_
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <errno.h>
|
||||
|
||||
typedef void *iconv_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern iconv_t iconv_open(const char *, const char *);
|
||||
extern size_t iconv(iconv_t, char **, size_t *, char **, size_t *);
|
||||
extern int iconv_close(iconv_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ICONV_H_ */
|
37
src/core/os2/geniconv/makefile
Normal file
37
src/core/os2/geniconv/makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# Universal iconv implementation for OS/2.
|
||||
#
|
||||
# OpenWatcom makefile to build a library that uses kiconv.dll / iconv2.dll /
|
||||
# iconv.dll or OS/2 Uni*() API.
|
||||
#
|
||||
# Andrey Vasilkin, 2016.
|
||||
#
|
||||
|
||||
LIBFILE = geniconv.lib
|
||||
|
||||
all: $(LIBFILE) test.exe .symbolic
|
||||
|
||||
CFLAGS = -I$(%WATCOM)/h/os2 -I$(%WATCOM)/h -I. -bt=os2 -q -d0 -w2
|
||||
|
||||
SRCS = geniconv.c os2cp.c os2iconv.c
|
||||
SRCS+= sys2utf8.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
LIBS = libuls.lib libconv.lib $(LIBFILE)
|
||||
|
||||
test.exe: $(LIBFILE) test.obj
|
||||
wlink op quiet system os2v2 file test.obj lib {$(LIBS)} name $*
|
||||
|
||||
$(LIBFILE): $(OBJS)
|
||||
@if exist $@ rm $@
|
||||
@for %f in ($(OBJS)) do wlib -q -b $* +%f
|
||||
|
||||
.c.obj:
|
||||
wcc386 $(CFLAGS) -fo=$^@ $<
|
||||
|
||||
clean: .SYMBOLIC
|
||||
@if exist *.obj rm *.obj
|
||||
@if exist *.err rm *.err
|
||||
@if exist $(LIBFILE) rm $(LIBFILE)
|
||||
@if exist test.exe rm test.exe
|
383
src/core/os2/geniconv/os2cp.c
Normal file
383
src/core/os2/geniconv/os2cp.c
Normal file
@@ -0,0 +1,383 @@
|
||||
#include "os2cp.h"
|
||||
#define INCL_DOSNLS
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef struct _CP2NAME {
|
||||
ULONG ulCode;
|
||||
PSZ pszName;
|
||||
} CP2NAME;
|
||||
|
||||
typedef struct _NAME2CP {
|
||||
PSZ pszName;
|
||||
ULONG ulCode;
|
||||
} NAME2CP;
|
||||
|
||||
static CP2NAME aCP2Name[] =
|
||||
{
|
||||
{367, "ANSI_X3.4-1968"},
|
||||
{813, "ECMA-118"},
|
||||
{819, "CP819"},
|
||||
{850, "850"},
|
||||
{862, "862"},
|
||||
{866, "866"},
|
||||
{874, "ISO-IR-166"},
|
||||
{878, "KOI8-R"},
|
||||
{896, "JISX0201-1976"},
|
||||
{901, "ISO-8859-13"},
|
||||
{912, "ISO-8859-2"},
|
||||
{913, "ISO-8859-3"},
|
||||
{914, "ISO-8859-4"},
|
||||
{915, "CYRILLIC"},
|
||||
{920, "ISO-8859-9"},
|
||||
{923, "ISO-8859-15"},
|
||||
{943, "MS_KANJI"},
|
||||
{954, "EUC-JP"},
|
||||
{964, "EUC-TW"},
|
||||
{970, "EUC-KR"},
|
||||
{1051, "HP-ROMAN8"},
|
||||
{1089, "ARABIC"},
|
||||
{1129, "VISCII"},
|
||||
{1168, "KOI8-U"},
|
||||
{1200, "ISO-10646-UCS-2"},
|
||||
{1202, "UTF-16LE"},
|
||||
{1204, "UCS-2BE"},
|
||||
{1208, "UTF-8"},
|
||||
{1232, "UTF-32BE"},
|
||||
{1234, "UTF-32LE"},
|
||||
{1236, "ISO-10646-UCS-4"},
|
||||
{1250, "CP1250"},
|
||||
{1251, "CP1251"},
|
||||
{1252, "CP1252"},
|
||||
{1253, "CP1253"},
|
||||
{1254, "CP1254"},
|
||||
{1255, "CP1255"},
|
||||
{1256, "CP1256"},
|
||||
{1257, "CP1257"},
|
||||
{1275, "MAC"},
|
||||
{1383, "CN-GB"},
|
||||
{1386, "GBK"},
|
||||
{1392, "GB18030"},
|
||||
{62210, "HEBREW"}
|
||||
};
|
||||
|
||||
static NAME2CP aName2CP[] =
|
||||
{
|
||||
{"850", 850},
|
||||
{"862", 862},
|
||||
{"866", 866},
|
||||
{"ANSI_X3.4-1968", 367},
|
||||
{"ANSI_X3.4-1986", 367},
|
||||
{"ARABIC", 1089},
|
||||
{"ASCII", 367},
|
||||
{"ASMO-708", 1089},
|
||||
{"CN-GB", 1383},
|
||||
{"CP1250", 1250},
|
||||
{"CP1251", 1251},
|
||||
{"CP1252", 1252},
|
||||
{"CP1253", 1253},
|
||||
{"CP1254", 1254},
|
||||
{"CP1255", 1255},
|
||||
{"CP1256", 1256},
|
||||
{"CP1257", 1257},
|
||||
{"CP367", 367},
|
||||
{"CP819", 819},
|
||||
{"CP850", 850},
|
||||
{"CP862", 862},
|
||||
{"CP866", 866},
|
||||
{"CP936", 1386},
|
||||
{"CSASCII", 367},
|
||||
{"CSEUCKR", 970},
|
||||
{"CSEUCPKDFMTJAPANESE", 954},
|
||||
{"CSEUCTW", 964},
|
||||
{"CSGB2312", 1383},
|
||||
{"CSHALFWIDTHKATAKANA", 896},
|
||||
{"CSHPROMAN8", 1051},
|
||||
{"CSIBM866", 866},
|
||||
{"CSISOLATIN1", 819},
|
||||
{"CSISOLATIN2", 912},
|
||||
{"CSISOLATIN3", 913},
|
||||
{"CSISOLATIN4", 914},
|
||||
{"CSISOLATIN5", 920},
|
||||
{"CSISOLATINARABIC", 1089},
|
||||
{"CSISOLATINCYRILLIC", 915},
|
||||
{"CSISOLATINGREEK", 813},
|
||||
{"CSISOLATINHEBREW", 62210},
|
||||
{"CSKOI8R", 878},
|
||||
{"CSKSC56011987", 970},
|
||||
{"CSMACINTOSH", 1275},
|
||||
{"CSPC850MULTILINGUAL", 850},
|
||||
{"CSPC862LATINHEBREW", 862},
|
||||
{"CSSHIFTJIS", 943},
|
||||
{"CSUCS4", 1236},
|
||||
{"CSUNICODE", 1200},
|
||||
{"CSUNICODE11", 1204},
|
||||
{"CSVISCII", 1129},
|
||||
{"CYRILLIC", 915},
|
||||
{"ECMA-114", 1089},
|
||||
{"ECMA-118", 813},
|
||||
{"ELOT_928", 813},
|
||||
{"EUC-CN", 1383},
|
||||
{"EUC-JP", 954},
|
||||
{"EUC-KR", 970},
|
||||
{"EUC-TW", 964},
|
||||
{"EUCCN", 1383},
|
||||
{"EUCJP", 954},
|
||||
{"EUCKR", 970},
|
||||
{"EUCTW", 964},
|
||||
{"EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE", 954},
|
||||
{"GB18030", 1392},
|
||||
{"GB2312", 1383},
|
||||
{"GBK", 1386},
|
||||
{"GREEK", 813},
|
||||
{"GREEK8", 813},
|
||||
{"HEBREW", 62210},
|
||||
{"HP-ROMAN8", 1051},
|
||||
{"IBM367", 367},
|
||||
{"IBM819", 819},
|
||||
{"IBM850", 850},
|
||||
{"IBM862", 862},
|
||||
{"IBM866", 866},
|
||||
{"ISO-10646-UCS-2", 1200},
|
||||
{"ISO-10646-UCS-4", 1236},
|
||||
{"ISO-8859-1", 819},
|
||||
{"ISO-8859-13", 901},
|
||||
{"ISO-8859-15", 923},
|
||||
{"ISO-8859-2", 912},
|
||||
{"ISO-8859-3", 913},
|
||||
{"ISO-8859-4", 914},
|
||||
{"ISO-8859-5", 915},
|
||||
{"ISO-8859-6", 1089},
|
||||
{"ISO-8859-7", 813},
|
||||
{"ISO-8859-8", 62210},
|
||||
{"ISO-8859-9", 920},
|
||||
{"ISO-IR-100", 819},
|
||||
{"ISO-IR-101", 912},
|
||||
{"ISO-IR-109", 913},
|
||||
{"ISO-IR-110", 914},
|
||||
{"ISO-IR-126", 813},
|
||||
{"ISO-IR-127", 1089},
|
||||
{"ISO-IR-138", 62210},
|
||||
{"ISO-IR-144", 915},
|
||||
{"ISO-IR-148", 920},
|
||||
{"ISO-IR-149", 970},
|
||||
{"ISO-IR-166", 874},
|
||||
{"ISO-IR-179", 901},
|
||||
{"ISO-IR-203", 923},
|
||||
{"ISO-IR-6", 367},
|
||||
{"ISO646-US", 367},
|
||||
{"ISO8859-1", 819},
|
||||
{"ISO8859-13", 901},
|
||||
{"ISO8859-15", 923},
|
||||
{"ISO8859-2", 912},
|
||||
{"ISO8859-3", 913},
|
||||
{"ISO8859-4", 914},
|
||||
{"ISO8859-5", 915},
|
||||
{"ISO8859-6", 1089},
|
||||
{"ISO8859-7", 813},
|
||||
{"ISO8859-8", 62210},
|
||||
{"ISO8859-9", 920},
|
||||
{"ISO_646.IRV:1991", 367},
|
||||
{"ISO_8859-1", 819},
|
||||
{"ISO_8859-13", 901},
|
||||
{"ISO_8859-15", 923},
|
||||
{"ISO_8859-15:1998", 923},
|
||||
{"ISO_8859-1:1987", 819},
|
||||
{"ISO_8859-2", 912},
|
||||
{"ISO_8859-2:1987", 912},
|
||||
{"ISO_8859-3", 913},
|
||||
{"ISO_8859-3:1988", 913},
|
||||
{"ISO_8859-4", 914},
|
||||
{"ISO_8859-4:1988", 914},
|
||||
{"ISO_8859-5", 915},
|
||||
{"ISO_8859-5:1988", 915},
|
||||
{"ISO_8859-6", 1089},
|
||||
{"ISO_8859-6:1987", 1089},
|
||||
{"ISO_8859-7", 813},
|
||||
{"ISO_8859-7:1987", 813},
|
||||
{"ISO_8859-7:2003", 813},
|
||||
{"ISO_8859-8", 62210},
|
||||
{"ISO_8859-8:1988", 62210},
|
||||
{"ISO_8859-9", 920},
|
||||
{"ISO_8859-9:1989", 920},
|
||||
{"JISX0201-1976", 896},
|
||||
{"JIS_X0201", 896},
|
||||
{"KOI8-R", 878},
|
||||
{"KOI8-U", 1168},
|
||||
{"KOREAN", 970},
|
||||
{"KSC_5601", 970},
|
||||
{"KS_C_5601-1987", 970},
|
||||
{"KS_C_5601-1989", 970},
|
||||
{"L1", 819},
|
||||
{"L2", 912},
|
||||
{"L3", 913},
|
||||
{"L4", 914},
|
||||
{"L5", 920},
|
||||
{"L7", 901},
|
||||
{"LATIN-9", 923},
|
||||
{"LATIN1", 819},
|
||||
{"LATIN2", 912},
|
||||
{"LATIN3", 913},
|
||||
{"LATIN4", 914},
|
||||
{"LATIN5", 920},
|
||||
{"LATIN7", 901},
|
||||
{"MAC", 1275},
|
||||
{"MACINTOSH", 1275},
|
||||
{"MACROMAN", 1275},
|
||||
{"MS-ANSI", 1252},
|
||||
{"MS-ARAB", 1256},
|
||||
{"MS-CYRL", 1251},
|
||||
{"MS-EE", 1250},
|
||||
{"MS-GREEK", 1253},
|
||||
{"MS-HEBR", 1255},
|
||||
{"MS-TURK", 1254},
|
||||
{"MS936", 1386},
|
||||
{"MS_KANJI", 943},
|
||||
{"R8", 1051},
|
||||
{"ROMAN8", 1051},
|
||||
{"SHIFT-JIS", 943},
|
||||
{"SHIFT_JIS", 943},
|
||||
{"SJIS", 943},
|
||||
{"TIS-620", 874},
|
||||
{"TIS620", 874},
|
||||
{"TIS620-0", 874},
|
||||
{"TIS620.2529-1", 874},
|
||||
{"TIS620.2533-0", 874},
|
||||
{"TIS620.2533-1", 874},
|
||||
{"UCS-2", 1200},
|
||||
{"UCS-2BE", 1204},
|
||||
{"UCS-4", 1236},
|
||||
{"UNICODE-1-1", 1204},
|
||||
{"UNICODEBIG", 1204},
|
||||
{"US", 367},
|
||||
{"US-ASCII", 367},
|
||||
{"UTF-16", 1204},
|
||||
{"UTF-16BE", 1200},
|
||||
{"UTF-16LE", 1202},
|
||||
{"UTF-32", 1236},
|
||||
{"UTF-32BE", 1232},
|
||||
{"UTF-32LE", 1234},
|
||||
{"UTF-8", 1208},
|
||||
{"VISCII", 1129},
|
||||
{"VISCII1.1-1", 1129},
|
||||
{"WINBALTRIM", 1257},
|
||||
{"WINDOWS-1250", 1250},
|
||||
{"WINDOWS-1251", 1251},
|
||||
{"WINDOWS-1252", 1252},
|
||||
{"WINDOWS-1253", 1253},
|
||||
{"WINDOWS-1254", 1254},
|
||||
{"WINDOWS-1255", 1255},
|
||||
{"WINDOWS-1256", 1256},
|
||||
{"WINDOWS-1257", 1257},
|
||||
{"WINDOWS-936", 1386},
|
||||
{"X0201", 896}
|
||||
};
|
||||
|
||||
char * os2cpToName(unsigned long cp)
|
||||
{
|
||||
ULONG ulLo = 0;
|
||||
ULONG ulHi = ( sizeof(aCP2Name) / sizeof(struct _CP2NAME) ) - 1;
|
||||
ULONG ulNext;
|
||||
LONG lFound = -1;
|
||||
|
||||
if ( cp == SYSTEM_CP )
|
||||
{
|
||||
ULONG aulCP[3];
|
||||
ULONG cCP;
|
||||
|
||||
if ( DosQueryCp( sizeof(aulCP), &aulCP, &cCP ) != NO_ERROR )
|
||||
return NULL;
|
||||
|
||||
cp = aulCP[0];
|
||||
}
|
||||
|
||||
if ( ( aCP2Name[0].ulCode > cp ) || ( aCP2Name[ulHi].ulCode < cp ) )
|
||||
return NULL;
|
||||
|
||||
if ( aCP2Name[0].ulCode == cp )
|
||||
return aCP2Name[0].pszName;
|
||||
|
||||
if ( aCP2Name[ulHi].ulCode == cp )
|
||||
return aCP2Name[ulHi].pszName;
|
||||
|
||||
while( ( ulHi - ulLo ) > 1 )
|
||||
{
|
||||
ulNext = ( ulLo + ulHi ) / 2;
|
||||
|
||||
if ( aCP2Name[ulNext].ulCode < cp )
|
||||
ulLo = ulNext;
|
||||
else if ( aCP2Name[ulNext].ulCode > cp )
|
||||
ulHi = ulNext;
|
||||
else
|
||||
{
|
||||
lFound = ulNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lFound == -1 ? NULL : aCP2Name[lFound].pszName;
|
||||
}
|
||||
|
||||
unsigned long os2cpFromName(char *cp)
|
||||
{
|
||||
ULONG ulLo = 0;
|
||||
ULONG ulHi = ( sizeof(aName2CP) / sizeof(struct _NAME2CP) ) - 1;
|
||||
ULONG ulNext;
|
||||
LONG lFound = -1;
|
||||
LONG lCmp;
|
||||
PCHAR pcEnd;
|
||||
CHAR acBuf[64];
|
||||
|
||||
if ( cp == NULL )
|
||||
{
|
||||
ULONG aulCP[3];
|
||||
ULONG cCP;
|
||||
|
||||
return DosQueryCp( sizeof(aulCP), &aulCP, &cCP ) != NO_ERROR ? 0 : aulCP[0];
|
||||
}
|
||||
|
||||
while( isspace( *cp ) ) cp++;
|
||||
pcEnd = strchr( cp, ' ' );
|
||||
if ( pcEnd == NULL )
|
||||
pcEnd = strchr( cp, '\0' );
|
||||
|
||||
ulNext = pcEnd - cp;
|
||||
if ( ulNext >= sizeof(acBuf) )
|
||||
return 0;
|
||||
|
||||
memcpy( &acBuf, cp, ulNext );
|
||||
acBuf[ulNext] = '\0';
|
||||
strupr( &acBuf );
|
||||
|
||||
lCmp = strcmp( aName2CP[0].pszName, &acBuf );
|
||||
if ( lCmp > 0 )
|
||||
return 0;
|
||||
else if ( lCmp == 0 )
|
||||
return aName2CP[0].ulCode;
|
||||
|
||||
lCmp = strcmp( aName2CP[ulHi].pszName, &acBuf );
|
||||
if ( lCmp < 0 )
|
||||
return 0;
|
||||
else if ( lCmp == 0 )
|
||||
return aName2CP[ulHi].ulCode;
|
||||
|
||||
while( ( ulHi - ulLo ) > 1 )
|
||||
{
|
||||
ulNext = ( ulLo + ulHi ) / 2;
|
||||
|
||||
lCmp = strcmp( aName2CP[ulNext].pszName, &acBuf );
|
||||
if ( lCmp < 0 )
|
||||
ulLo = ulNext;
|
||||
else if ( lCmp > 0 )
|
||||
ulHi = ulNext;
|
||||
else
|
||||
{
|
||||
lFound = ulNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lFound == -1 ? 0 : aName2CP[lFound].ulCode;
|
||||
}
|
9
src/core/os2/geniconv/os2cp.h
Normal file
9
src/core/os2/geniconv/os2cp.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef OS2CP_H
|
||||
#define OS2CP_H 1
|
||||
|
||||
#define SYSTEM_CP 0
|
||||
|
||||
char * os2cpToName(unsigned long cp);
|
||||
unsigned long os2cpFromName(char *cp);
|
||||
|
||||
#endif // OS2CP_H
|
264
src/core/os2/geniconv/os2iconv.c
Normal file
264
src/core/os2/geniconv/os2iconv.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
Implementation iconv via OS/2 conversion objects API.
|
||||
|
||||
Andrey Vasilkin.
|
||||
*/
|
||||
|
||||
#define ICONV_THREAD_SAFE 1
|
||||
//#undef ICONV_THREAD_SAFE
|
||||
|
||||
#include "iconv.h"
|
||||
#include <uconv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
#endif
|
||||
#include "os2cp.h"
|
||||
|
||||
#define MAX_CP_NAME_LEN 64
|
||||
|
||||
typedef struct iuconv_obj {
|
||||
UconvObject uo_tocode;
|
||||
UconvObject uo_fromcode;
|
||||
int buf_len;
|
||||
UniChar *buf;
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
HMTX hMtx;
|
||||
#endif
|
||||
} iuconv_obj;
|
||||
|
||||
|
||||
static int _createUconvObj(const char *code, UconvObject *uobj)
|
||||
{
|
||||
UniChar uc_code[MAX_CP_NAME_LEN];
|
||||
int i;
|
||||
const char *ch = code;
|
||||
|
||||
if ( code == NULL )
|
||||
uc_code[0] = 0;
|
||||
else
|
||||
{
|
||||
for( i = 0; i < MAX_CP_NAME_LEN; i++ )
|
||||
{
|
||||
uc_code[i] = (unsigned short)*ch;
|
||||
if ( !(*ch) ) break;
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
return UniCreateUconvObject( &uc_code, uobj );
|
||||
}
|
||||
|
||||
static int uconv_open(const char *code, UconvObject *uobj)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ( !stricmp( code, "UTF-16" ) )
|
||||
{
|
||||
*uobj = NULL;
|
||||
return ULS_SUCCESS;
|
||||
}
|
||||
|
||||
rc = _createUconvObj( code, uobj );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
unsigned long cp = os2cpFromName( (char *)code );
|
||||
char cp_name[16];
|
||||
|
||||
if ( cp != 0 && _snprintf( &cp_name, sizeof(cp_name), "IBM-%u", cp ) > 0 )
|
||||
rc = _createUconvObj( &cp_name, uobj );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
extern iconv_t _System os2_iconv_open(const char* tocode, const char* fromcode)
|
||||
{
|
||||
UconvObject uo_tocode;
|
||||
UconvObject uo_fromcode;
|
||||
int rc;
|
||||
iuconv_obj *iuobj;
|
||||
|
||||
if ( tocode == NULL )
|
||||
tocode = "";
|
||||
|
||||
if ( fromcode == NULL )
|
||||
fromcode = "";
|
||||
|
||||
if ( stricmp(tocode, fromcode) != 0 )
|
||||
{
|
||||
rc = uconv_open( fromcode, &uo_fromcode );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
errno = EINVAL;
|
||||
return (iconv_t)(-1);
|
||||
}
|
||||
|
||||
rc = uconv_open( tocode, &uo_tocode );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
UniFreeUconvObject( uo_fromcode );
|
||||
errno = EINVAL;
|
||||
return (iconv_t)(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uo_tocode = NULL;
|
||||
uo_fromcode = NULL;
|
||||
}
|
||||
|
||||
iuobj = malloc( sizeof(iuconv_obj) );
|
||||
iuobj->uo_tocode = uo_tocode;
|
||||
iuobj->uo_fromcode = uo_fromcode;
|
||||
iuobj->buf_len = 0;
|
||||
iuobj->buf = NULL;
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosCreateMutexSem( NULL, &iuobj->hMtx, 0, FALSE );
|
||||
#endif
|
||||
|
||||
return iuobj;
|
||||
}
|
||||
|
||||
extern size_t _System os2_iconv(iconv_t cd, char* * inbuf,
|
||||
size_t *inbytesleft,
|
||||
char* * outbuf, size_t *outbytesleft)
|
||||
{
|
||||
UconvObject uo_tocode = ((iuconv_obj *)(cd))->uo_tocode;
|
||||
UconvObject uo_fromcode = ((iuconv_obj *)(cd))->uo_fromcode;
|
||||
size_t nonIdenticalConv = 0;
|
||||
UniChar *uc_buf;
|
||||
size_t uc_buf_len;
|
||||
UniChar **uc_str;
|
||||
size_t *uc_str_len;
|
||||
int rc;
|
||||
size_t ret = (size_t)(-1);
|
||||
|
||||
if ( uo_tocode == NULL && uo_fromcode == NULL )
|
||||
{
|
||||
uc_buf_len = min( *inbytesleft, *outbytesleft );
|
||||
memcpy( *outbuf, *inbuf, uc_buf_len );
|
||||
*inbytesleft -= uc_buf_len;
|
||||
*outbytesleft -= uc_buf_len;
|
||||
outbuf += uc_buf_len;
|
||||
inbuf += uc_buf_len;
|
||||
return uc_buf_len;
|
||||
}
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosRequestMutexSem( ((iuconv_obj *)(cd))->hMtx, SEM_INDEFINITE_WAIT );
|
||||
#endif
|
||||
|
||||
if ( uo_tocode && uo_fromcode &&
|
||||
(( ((iuconv_obj *)(cd))->buf_len >> 1 ) < (*inbytesleft)) )
|
||||
{
|
||||
if ( ( ((iuconv_obj *)(cd))->buf ) != NULL )
|
||||
free( ((iuconv_obj *)(cd))->buf );
|
||||
((iuconv_obj *)(cd))->buf_len = *inbytesleft << 1;
|
||||
((iuconv_obj *)(cd))->buf = (UniChar *)malloc( ((iuconv_obj *)(cd))->buf_len );
|
||||
}
|
||||
|
||||
if ( uo_fromcode )
|
||||
{
|
||||
if ( uo_tocode )
|
||||
{
|
||||
uc_buf = ((iuconv_obj *)(cd))->buf;
|
||||
uc_buf_len = ((iuconv_obj *)(cd))->buf_len;
|
||||
uc_str = &uc_buf;
|
||||
}
|
||||
else {
|
||||
uc_str = (UniChar **)outbuf;
|
||||
uc_buf_len = *outbytesleft;
|
||||
}
|
||||
uc_buf_len = uc_buf_len >> 1;
|
||||
uc_str_len = &uc_buf_len;
|
||||
rc = UniUconvToUcs( uo_fromcode, (void **)inbuf, inbytesleft,
|
||||
uc_str, uc_str_len, &nonIdenticalConv );
|
||||
uc_buf_len = uc_buf_len << 1;
|
||||
if ( !uo_tocode )
|
||||
*outbytesleft = uc_buf_len;
|
||||
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
errno = EILSEQ;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
if ( *inbytesleft && !*uc_str_len )
|
||||
{
|
||||
errno = E2BIG;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( !uo_tocode )
|
||||
return nonIdenticalConv;
|
||||
|
||||
uc_buf = ((iuconv_obj *)(cd))->buf;
|
||||
uc_buf_len = ((iuconv_obj *)(cd))->buf_len - uc_buf_len;
|
||||
uc_str = &uc_buf;
|
||||
uc_str_len = &uc_buf_len;
|
||||
}
|
||||
else {
|
||||
uc_str = (UniChar **)inbuf;
|
||||
uc_str_len = inbytesleft;
|
||||
}
|
||||
|
||||
*uc_str_len = *uc_str_len>>1;
|
||||
rc = UniUconvFromUcs( uo_tocode, uc_str, uc_str_len, (void **)outbuf,
|
||||
outbytesleft, &nonIdenticalConv );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
switch ( rc )
|
||||
{
|
||||
case ULS_BUFFERFULL:
|
||||
errno = E2BIG;
|
||||
break;
|
||||
case ULS_ILLEGALSEQUENCE:
|
||||
errno = EILSEQ;
|
||||
break;
|
||||
case ULS_INVALID:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
if ( *uc_str_len && !*outbytesleft )
|
||||
{
|
||||
errno = E2BIG;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = nonIdenticalConv;
|
||||
|
||||
done:
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosReleaseMutexSem( ((iuconv_obj *)(cd))->hMtx );
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern int _System os2_iconv_close(iconv_t cd)
|
||||
{
|
||||
if ( !cd )
|
||||
return 0;
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosCloseMutexSem( ((iuconv_obj *)(cd))->hMtx );
|
||||
#endif
|
||||
if ( ((iuconv_obj *)(cd))->uo_tocode != NULL )
|
||||
UniFreeUconvObject( ((iuconv_obj *)(cd))->uo_tocode );
|
||||
if ( ((iuconv_obj *)(cd))->uo_fromcode != NULL )
|
||||
UniFreeUconvObject( ((iuconv_obj *)(cd))->uo_fromcode );
|
||||
|
||||
if ( ( ((iuconv_obj *)(cd))->buf ) != NULL )
|
||||
free( ((iuconv_obj *)(cd))->buf );
|
||||
|
||||
free(cd);
|
||||
|
||||
return 0;
|
||||
}
|
97
src/core/os2/geniconv/sys2utf8.c
Normal file
97
src/core/os2/geniconv/sys2utf8.c
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <iconv.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int StrUTF8(int fToUTF8, char *pcDst, int cbDst, char *pcSrc, int cbSrc)
|
||||
{
|
||||
size_t rc;
|
||||
char *pcDstStart = pcDst;
|
||||
iconv_t cd;
|
||||
char *pszToCP, *pszFromCP;
|
||||
int fError = 0;
|
||||
|
||||
if ( cbDst < 4 )
|
||||
return -1;
|
||||
|
||||
if ( fToUTF8 )
|
||||
{
|
||||
pszToCP = "UTF-8";
|
||||
pszFromCP = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
pszToCP = "";
|
||||
pszFromCP = "UTF-8";
|
||||
}
|
||||
|
||||
cd = iconv_open( pszToCP, pszFromCP );
|
||||
if ( cd == (iconv_t)-1 )
|
||||
return -1;
|
||||
|
||||
while( cbSrc > 0 )
|
||||
{
|
||||
rc = iconv( cd, &pcSrc, (size_t *)&cbSrc, &pcDst, (size_t *)&cbDst );
|
||||
if ( rc == (size_t)-1 )
|
||||
{
|
||||
if ( errno == EILSEQ )
|
||||
{
|
||||
// Try to skip invalid character.
|
||||
pcSrc++;
|
||||
cbSrc--;
|
||||
continue;
|
||||
}
|
||||
|
||||
fError = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iconv_close( cd );
|
||||
|
||||
// Write trailing ZERO (1 byte for UTF-8, 2 bytes for the system cp.).
|
||||
|
||||
if ( fToUTF8 )
|
||||
{
|
||||
if ( cbDst < 1 )
|
||||
{
|
||||
pcDst--;
|
||||
fError = 1; // The destination buffer overflow.
|
||||
}
|
||||
*pcDst = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( cbDst < 2 )
|
||||
{
|
||||
pcDst -= ( cbDst == 0 ) ? 2 : 1;
|
||||
fError = 1; // The destination buffer overflow.
|
||||
}
|
||||
*((short *)pcDst) = '\0';
|
||||
}
|
||||
|
||||
return fError ? -1 : ( pcDst - pcDstStart );
|
||||
}
|
||||
|
||||
char *StrUTF8New(int fToUTF8, char *pcStr, int cbStr)
|
||||
{
|
||||
int cbNewStr = ( ( cbStr > 4 ? cbStr : 4 ) + 1 ) * 2;
|
||||
char *pszNewStr = malloc( cbNewStr );
|
||||
|
||||
if ( pszNewStr == NULL )
|
||||
return NULL;
|
||||
|
||||
cbNewStr = StrUTF8( fToUTF8, pszNewStr, cbNewStr, pcStr, cbStr );
|
||||
if ( cbNewStr != -1 )
|
||||
{
|
||||
pcStr = realloc( pszNewStr, cbNewStr + ( fToUTF8 ? 1 : sizeof(short) ) );
|
||||
if ( pcStr != NULL )
|
||||
return pcStr;
|
||||
}
|
||||
|
||||
free( pszNewStr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void StrUTF8Free(char *pszStr)
|
||||
{
|
||||
free( pszStr );
|
||||
}
|
45
src/core/os2/geniconv/test.c
Normal file
45
src/core/os2/geniconv/test.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <geniconv.h>
|
||||
|
||||
void main()
|
||||
{
|
||||
char acBuf[128];
|
||||
char *inbuf = "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"; // KOI8-R string.
|
||||
size_t inbytesleft = strlen( inbuf );
|
||||
char *outbuf = &acBuf;
|
||||
size_t outbytesleft = sizeof( acBuf );
|
||||
iconv_t ic;
|
||||
|
||||
// KOI8 -> system cp.
|
||||
|
||||
ic = iconv_open( "", "KOI8-R" );
|
||||
if ( ic == (iconv_t)(-1) )
|
||||
{
|
||||
puts( "iconv_open() fail" );
|
||||
return;
|
||||
}
|
||||
|
||||
iconv( ic, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
|
||||
printf( "KOI8-R to system cp.: %s\n", &acBuf );
|
||||
|
||||
iconv_close( ic );
|
||||
|
||||
// System cp. -> UTF-8 -> system cp.
|
||||
|
||||
// System cp. -> UTF-8 by StrUTF8New().
|
||||
inbuf = StrUTF8New( 1, &acBuf, strlen( &acBuf ) );
|
||||
|
||||
// UTF-8 -> system cp. by StrUTF8().
|
||||
if ( StrUTF8( 0, &acBuf, sizeof(acBuf), inbuf, strlen( inbuf ) ) == -1 )
|
||||
puts( "StrUTF8() failed" );
|
||||
else
|
||||
printf( "system cp. -> UTF-8 -> system cp.: %s\n", &acBuf );
|
||||
|
||||
free( inbuf );
|
||||
|
||||
// Unload used DLL.
|
||||
iconv_clean();
|
||||
|
||||
puts( "Done." );
|
||||
}
|
Reference in New Issue
Block a user