Added Uq-Ruan Masters game - it compiles but does not work (renders too slowly? Another problem?)
This commit is contained in:
1
project/jni/application/sc2/src/libs/strings/Makeinfo
Normal file
1
project/jni/application/sc2/src/libs/strings/Makeinfo
Normal file
@@ -0,0 +1 @@
|
||||
uqm_CFILES="getstr.c sfileins.c sresins.c strings.c unicode.c"
|
||||
483
project/jni/application/sc2/src/libs/strings/getstr.c
Normal file
483
project/jni/application/sc2/src/libs/strings/getstr.c
Normal file
@@ -0,0 +1,483 @@
|
||||
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "options.h"
|
||||
#include "strintrn.h"
|
||||
#include "libs/graphics/gfx_common.h"
|
||||
#include "libs/reslib.h"
|
||||
#include "libs/log.h"
|
||||
#include "libs/memlib.h"
|
||||
|
||||
|
||||
#define MAX_STRINGS 2048
|
||||
#define POOL_SIZE 4096
|
||||
|
||||
static void
|
||||
dword_convert (DWORD *dword_array, COUNT num_dwords)
|
||||
{
|
||||
BYTE *p = (BYTE*)dword_array;
|
||||
|
||||
do
|
||||
{
|
||||
*dword_array++ = MAKE_DWORD (
|
||||
MAKE_WORD (p[3], p[2]),
|
||||
MAKE_WORD (p[1], p[0])
|
||||
);
|
||||
p += 4;
|
||||
} while (--num_dwords);
|
||||
}
|
||||
|
||||
static void
|
||||
set_strtab_entry (STRING_TABLE_DESC *strtab, int index, const char *value, int len)
|
||||
{
|
||||
STRING str = &strtab->strings[index];
|
||||
|
||||
if (str->data)
|
||||
{
|
||||
HFree (str->data);
|
||||
str->data = NULL;
|
||||
str->length = 0;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
str->data = HMalloc (len);
|
||||
str->length = len;
|
||||
memcpy (str->data, value, len);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_GetConversationData (const char *path, RESOURCE_DATA *resdata)
|
||||
{
|
||||
uio_Stream *fp;
|
||||
long dataLen;
|
||||
void *result;
|
||||
int n, path_len, num_data_sets;
|
||||
DWORD opos,
|
||||
slen[MAX_STRINGS], StringOffs, tot_string_size,
|
||||
clen[MAX_STRINGS], ClipOffs, tot_clip_size,
|
||||
tslen[MAX_STRINGS], TSOffs;
|
||||
DWORD tot_ts_size = 0;
|
||||
char CurrentLine[1024], paths[1024], *clip_path, *ts_path,
|
||||
*strdata, *clipdata, *ts_data;
|
||||
uio_Stream *timestamp_fp = NULL;
|
||||
|
||||
/* Parse out the conversation components. */
|
||||
strncpy (paths, path, 1023);
|
||||
paths[1023] = '\0';
|
||||
clip_path = strchr (paths, ':');
|
||||
if (clip_path == NULL)
|
||||
{
|
||||
ts_path = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*clip_path = '\0';
|
||||
clip_path++;
|
||||
|
||||
ts_path = strchr (clip_path, ':');
|
||||
if (ts_path != NULL)
|
||||
{
|
||||
*ts_path = '\0';
|
||||
ts_path++;
|
||||
}
|
||||
}
|
||||
|
||||
fp = res_OpenResFile (contentDir, paths, "rb");
|
||||
if (fp == NULL)
|
||||
{
|
||||
log_add (log_Warning, "Warning: Can't open '%s'", paths);
|
||||
resdata->ptr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
dataLen = LengthResFile (fp);
|
||||
log_add (log_Info, "\t'%s' -- conversation phrases -- %lu bytes", paths, dataLen);
|
||||
if (clip_path)
|
||||
log_add (log_Info, "\t'%s' -- voice clip directory", clip_path);
|
||||
else
|
||||
log_add (log_Info, "\tNo associated voice clips");
|
||||
if (ts_path)
|
||||
log_add (log_Info, "\t'%s' -- timestamps", ts_path);
|
||||
else
|
||||
log_add (log_Info, "\tNo associated timestamp file");
|
||||
|
||||
|
||||
if (dataLen == 0)
|
||||
{
|
||||
log_add (log_Warning, "Warning: Trying to load empty file '%s'.", path);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((strdata = HMalloc (tot_string_size = POOL_SIZE)) == 0)
|
||||
goto err;
|
||||
|
||||
if ((clipdata = HMalloc (tot_clip_size = POOL_SIZE)) == 0)
|
||||
{
|
||||
HFree (strdata);
|
||||
goto err;
|
||||
}
|
||||
ts_data = NULL;
|
||||
|
||||
path_len = clip_path ? strlen (clip_path) : 0;
|
||||
|
||||
if (ts_path && (timestamp_fp = uio_fopen (contentDir, ts_path,
|
||||
"rb")))
|
||||
{
|
||||
if ((ts_data = HMalloc (tot_ts_size = POOL_SIZE)) == 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
opos = uio_ftell (fp);
|
||||
n = -1;
|
||||
StringOffs = ClipOffs = TSOffs = 0;
|
||||
while (uio_fgets (CurrentLine, sizeof (CurrentLine), fp) && n < MAX_STRINGS - 1)
|
||||
{
|
||||
int l;
|
||||
|
||||
if (CurrentLine[0] == '#')
|
||||
{
|
||||
char CopyLine[1024];
|
||||
char *s;
|
||||
|
||||
strcpy (CopyLine, CurrentLine);
|
||||
s = strtok (&CopyLine[1], "()");
|
||||
if (s)
|
||||
{
|
||||
if (n >= 0)
|
||||
{
|
||||
while (slen[n] > 1 &&
|
||||
(strdata[StringOffs - 2] == '\n' ||
|
||||
strdata[StringOffs - 2] == '\r'))
|
||||
{
|
||||
--slen[n];
|
||||
--StringOffs;
|
||||
strdata[StringOffs - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
slen[++n] = 0;
|
||||
// now lets check for timestamp data
|
||||
if (timestamp_fp)
|
||||
{
|
||||
char TimeStampLine[1024], *tsptr;
|
||||
BOOLEAN ts_ok = FALSE;
|
||||
uio_fgets (TimeStampLine, sizeof (TimeStampLine), timestamp_fp);
|
||||
if (TimeStampLine[0] == '#')
|
||||
{
|
||||
tslen[n] = 0;
|
||||
if ((tsptr = strstr (TimeStampLine,s))
|
||||
&& (tsptr += strlen(s))
|
||||
&& (++tsptr))
|
||||
{
|
||||
ts_ok = TRUE;
|
||||
while (! strcspn(tsptr," \t\r\n") && *tsptr)
|
||||
tsptr++;
|
||||
if (*tsptr)
|
||||
{
|
||||
l = strlen (tsptr) + 1;
|
||||
if (TSOffs + l > tot_ts_size
|
||||
&& (ts_data = HRealloc (ts_data,
|
||||
tot_ts_size += POOL_SIZE)) == 0)
|
||||
{
|
||||
HFree (strdata);
|
||||
goto err;
|
||||
}
|
||||
strcpy (&ts_data[TSOffs], tsptr);
|
||||
TSOffs += l;
|
||||
tslen[n] = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ts_ok)
|
||||
{
|
||||
// timestamp data is invalid, remove all of it
|
||||
log_add (log_Warning, "Invalid timestamp data "
|
||||
"for '%s'. Disabling timestamps", s);
|
||||
HFree (ts_data);
|
||||
ts_data = NULL;
|
||||
uio_fclose (timestamp_fp);
|
||||
timestamp_fp = NULL;
|
||||
TSOffs = 0;
|
||||
}
|
||||
}
|
||||
clen[n] = 0;
|
||||
s = strtok (NULL, " \t\r\n)");
|
||||
if (s)
|
||||
{
|
||||
l = path_len + strlen (s) + 1;
|
||||
if (ClipOffs + l > tot_clip_size
|
||||
&& (clipdata = HRealloc (clipdata,
|
||||
tot_clip_size += POOL_SIZE)) == 0)
|
||||
{
|
||||
HFree (strdata);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (clip_path)
|
||||
strcpy (&clipdata[ClipOffs], clip_path);
|
||||
strcpy (&clipdata[ClipOffs + path_len], s);
|
||||
ClipOffs += l;
|
||||
clen[n] = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (n >= 0)
|
||||
{
|
||||
char *s;
|
||||
l = strlen (CurrentLine) + 1;
|
||||
if (StringOffs + l > tot_string_size
|
||||
&& (strdata = HRealloc (strdata,
|
||||
tot_string_size += POOL_SIZE)) == 0)
|
||||
{
|
||||
HFree (clipdata);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (slen[n])
|
||||
{
|
||||
--slen[n];
|
||||
--StringOffs;
|
||||
}
|
||||
s = &strdata[StringOffs];
|
||||
slen[n] += l;
|
||||
StringOffs += l;
|
||||
|
||||
strcpy (s, CurrentLine);
|
||||
}
|
||||
|
||||
if ((int)uio_ftell (fp) - (int)opos >= (int)dataLen)
|
||||
break;
|
||||
}
|
||||
if (n >= 0)
|
||||
{
|
||||
while (slen[n] > 1 && (strdata[StringOffs - 2] == '\n'
|
||||
|| strdata[StringOffs - 2] == '\r'))
|
||||
{
|
||||
--slen[n];
|
||||
--StringOffs;
|
||||
strdata[StringOffs - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (timestamp_fp)
|
||||
uio_fclose (timestamp_fp);
|
||||
|
||||
result = NULL;
|
||||
num_data_sets = (ClipOffs ? 1 : 0) + (TSOffs ? 1 : 0) + 1;
|
||||
if (++n)
|
||||
{
|
||||
int flags = 0;
|
||||
if (ClipOffs)
|
||||
flags |= HAS_SOUND_CLIPS;
|
||||
if (TSOffs)
|
||||
flags |= HAS_TIMESTAMP;
|
||||
result = AllocStringTable (n, flags);
|
||||
if (result)
|
||||
{
|
||||
int StringIndex, ClipIndex, TSIndex;
|
||||
STRING_TABLE_DESC *lpST;
|
||||
|
||||
lpST = (STRING_TABLE) result;
|
||||
|
||||
StringIndex = 0;
|
||||
ClipIndex = n;
|
||||
TSIndex = n * ((flags & HAS_SOUND_CLIPS) ? 2 : 1);
|
||||
|
||||
StringOffs = ClipOffs = TSOffs = 0;
|
||||
|
||||
for (n = 0; n < (int)lpST->size;
|
||||
++n, ++StringIndex, ++ClipIndex, ++TSIndex)
|
||||
{
|
||||
set_strtab_entry(lpST, StringIndex, strdata + StringOffs, slen[n]);
|
||||
StringOffs += slen[n];
|
||||
if (lpST->flags & HAS_SOUND_CLIPS)
|
||||
{
|
||||
set_strtab_entry(lpST, ClipIndex, clipdata + ClipOffs, clen[n]);
|
||||
ClipOffs += clen[n];
|
||||
}
|
||||
if (lpST->flags & HAS_TIMESTAMP)
|
||||
{
|
||||
set_strtab_entry(lpST, TSIndex, ts_data + TSOffs, tslen[n]);
|
||||
TSOffs += tslen[n];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HFree (strdata);
|
||||
HFree (clipdata);
|
||||
if (ts_data)
|
||||
HFree (ts_data);
|
||||
|
||||
resdata->ptr = result;
|
||||
return;
|
||||
|
||||
err:
|
||||
res_CloseResFile (fp);
|
||||
resdata->ptr = NULL;
|
||||
|
||||
}
|
||||
|
||||
void *
|
||||
_GetStringData (uio_Stream *fp, DWORD length)
|
||||
{
|
||||
void *result;
|
||||
|
||||
int n;
|
||||
DWORD opos, slen[MAX_STRINGS], StringOffs, tot_string_size;
|
||||
char CurrentLine[1024], *strdata;
|
||||
|
||||
if ((strdata = HMalloc (tot_string_size = POOL_SIZE)) == 0)
|
||||
return (0);
|
||||
|
||||
opos = uio_ftell (fp);
|
||||
n = -1;
|
||||
StringOffs = 0;
|
||||
while (uio_fgets (CurrentLine, sizeof (CurrentLine), fp) && n < MAX_STRINGS - 1)
|
||||
{
|
||||
int l;
|
||||
|
||||
if (CurrentLine[0] == '#')
|
||||
{
|
||||
char CopyLine[1024];
|
||||
char *s;
|
||||
|
||||
strcpy (CopyLine, CurrentLine);
|
||||
s = strtok (&CopyLine[1], "()");
|
||||
if (s)
|
||||
{
|
||||
if (n >= 0)
|
||||
{
|
||||
while (slen[n] > 1 &&
|
||||
(strdata[StringOffs - 2] == '\n' ||
|
||||
strdata[StringOffs - 2] == '\r'))
|
||||
{
|
||||
--slen[n];
|
||||
--StringOffs;
|
||||
strdata[StringOffs - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
slen[++n] = 0;
|
||||
}
|
||||
}
|
||||
else if (n >= 0)
|
||||
{
|
||||
char *s;
|
||||
l = strlen (CurrentLine) + 1;
|
||||
if (StringOffs + l > tot_string_size
|
||||
&& (strdata = HRealloc (strdata,
|
||||
tot_string_size += POOL_SIZE)) == 0)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (slen[n])
|
||||
{
|
||||
--slen[n];
|
||||
--StringOffs;
|
||||
}
|
||||
s = &strdata[StringOffs];
|
||||
slen[n] += l;
|
||||
StringOffs += l;
|
||||
|
||||
strcpy (s, CurrentLine);
|
||||
}
|
||||
|
||||
if ((int)uio_ftell (fp) - (int)opos >= (int)length)
|
||||
break;
|
||||
}
|
||||
if (n >= 0)
|
||||
{
|
||||
while (slen[n] > 1 && (strdata[StringOffs - 2] == '\n'
|
||||
|| strdata[StringOffs - 2] == '\r'))
|
||||
{
|
||||
--slen[n];
|
||||
--StringOffs;
|
||||
strdata[StringOffs - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
result = NULL;
|
||||
if (++n)
|
||||
{
|
||||
int flags = 0;
|
||||
result = AllocStringTable (n, flags);
|
||||
if (result)
|
||||
{
|
||||
int StringIndex;
|
||||
STRING_TABLE_DESC *lpST;
|
||||
|
||||
lpST = (STRING_TABLE) result;
|
||||
|
||||
StringIndex = 0;
|
||||
|
||||
StringOffs = 0;
|
||||
|
||||
for (n = 0; n < (int)lpST->size;
|
||||
++n, ++StringIndex)
|
||||
{
|
||||
set_strtab_entry(lpST, StringIndex, strdata + StringOffs, slen[n]);
|
||||
StringOffs += slen[n];
|
||||
}
|
||||
}
|
||||
}
|
||||
HFree (strdata);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
_GetBinaryTableData (uio_Stream *fp, DWORD length)
|
||||
{
|
||||
void *result;
|
||||
result = GetResourceData (fp, length);
|
||||
|
||||
if (result)
|
||||
{
|
||||
DWORD *fileData;
|
||||
STRING_TABLE lpST;
|
||||
|
||||
fileData = (DWORD *)result;
|
||||
|
||||
dword_convert (fileData, 1); /* Length */
|
||||
|
||||
lpST = AllocStringTable (fileData[0], 0);
|
||||
if (lpST)
|
||||
{
|
||||
int i, size;
|
||||
BYTE *stringptr;
|
||||
|
||||
size = lpST->size;
|
||||
|
||||
dword_convert (fileData+1, size + 1);
|
||||
stringptr = (BYTE *)(fileData + 2 + size + fileData[1]);
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
set_strtab_entry (lpST, i, (char *)stringptr, fileData[2+i]);
|
||||
stringptr += fileData[2+i];
|
||||
}
|
||||
}
|
||||
HFree (result);
|
||||
result = lpST;
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
50
project/jni/application/sc2/src/libs/strings/sfileins.c
Normal file
50
project/jni/application/sc2/src/libs/strings/sfileins.c
Normal file
@@ -0,0 +1,50 @@
|
||||
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "port.h"
|
||||
#include "strintrn.h"
|
||||
#include "libs/uio.h"
|
||||
#include "libs/reslib.h"
|
||||
|
||||
|
||||
STRING_TABLE
|
||||
LoadStringTableFile (uio_DirHandle *dir, const char *fileName)
|
||||
{
|
||||
uio_Stream *fp;
|
||||
|
||||
// FIXME: this theoretically needs a mechanism to prevent races
|
||||
if (_cur_resfile_name)
|
||||
// something else is loading resources atm
|
||||
return 0;
|
||||
|
||||
fp = res_OpenResFile (dir, fileName, "rb");
|
||||
if (fp)
|
||||
{
|
||||
STRING_TABLE data;
|
||||
|
||||
_cur_resfile_name = fileName;
|
||||
data = (STRING_TABLE) _GetStringData (fp, LengthResFile (fp));
|
||||
_cur_resfile_name = 0;
|
||||
res_CloseResFile (fp);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
55
project/jni/application/sc2/src/libs/strings/sresins.c
Normal file
55
project/jni/application/sc2/src/libs/strings/sresins.c
Normal file
@@ -0,0 +1,55 @@
|
||||
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "strintrn.h"
|
||||
|
||||
static void
|
||||
GetStringTableFileData (const char *pathname, RESOURCE_DATA *resdata)
|
||||
{
|
||||
resdata->ptr = LoadResourceFromPath (pathname, _GetStringData);
|
||||
}
|
||||
|
||||
static void
|
||||
GetBinaryTableFileData (const char *pathname, RESOURCE_DATA *resdata)
|
||||
{
|
||||
resdata->ptr = LoadResourceFromPath (pathname, _GetBinaryTableData);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
InstallStringTableResType (void)
|
||||
{
|
||||
InstallResTypeVectors ("STRTAB", GetStringTableFileData, FreeResourceData, NULL);
|
||||
InstallResTypeVectors ("BINTAB", GetBinaryTableFileData, FreeResourceData, NULL);
|
||||
InstallResTypeVectors ("CONVERSATION", _GetConversationData, FreeResourceData, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STRING_TABLE
|
||||
LoadStringTableInstance (RESOURCE res)
|
||||
{
|
||||
void *data;
|
||||
|
||||
data = res_GetResource (res);
|
||||
if (data)
|
||||
{
|
||||
res_DetachResource (res);
|
||||
}
|
||||
|
||||
return (STRING_TABLE)data;
|
||||
}
|
||||
|
||||
287
project/jni/application/sc2/src/libs/strings/strings.c
Normal file
287
project/jni/application/sc2/src/libs/strings/strings.c
Normal file
@@ -0,0 +1,287 @@
|
||||
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "strintrn.h"
|
||||
#include "libs/memlib.h"
|
||||
|
||||
STRING_TABLE
|
||||
AllocStringTable (int num_entries, int flags)
|
||||
{
|
||||
STRING_TABLE strtab = HMalloc (sizeof (STRING_TABLE_DESC));
|
||||
int i, multiplier = 1;
|
||||
|
||||
if (flags & HAS_SOUND_CLIPS)
|
||||
{
|
||||
multiplier++;
|
||||
}
|
||||
if (flags & HAS_TIMESTAMP)
|
||||
{
|
||||
multiplier++;
|
||||
}
|
||||
strtab->flags = flags;
|
||||
strtab->size = num_entries;
|
||||
num_entries *= multiplier;
|
||||
strtab->strings = HMalloc (sizeof (STRING_TABLE_ENTRY_DESC) * num_entries);
|
||||
for (i = 0; i < num_entries; i++)
|
||||
{
|
||||
strtab->strings[i].data = NULL;
|
||||
strtab->strings[i].length = 0;
|
||||
strtab->strings[i].parent = strtab;
|
||||
strtab->strings[i].index = i;
|
||||
}
|
||||
return strtab;
|
||||
}
|
||||
|
||||
void
|
||||
FreeStringTable (STRING_TABLE strtab)
|
||||
{
|
||||
int i, multiplier = 1;
|
||||
|
||||
if (strtab == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (strtab->flags & HAS_SOUND_CLIPS)
|
||||
{
|
||||
multiplier++;
|
||||
}
|
||||
if (strtab->flags & HAS_TIMESTAMP)
|
||||
{
|
||||
multiplier++;
|
||||
}
|
||||
|
||||
for (i = 0; i < strtab->size * multiplier; i++)
|
||||
{
|
||||
if (strtab->strings[i].data != NULL)
|
||||
{
|
||||
HFree (strtab->strings[i].data);
|
||||
}
|
||||
}
|
||||
|
||||
HFree (strtab->strings);
|
||||
HFree (strtab);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
DestroyStringTable (STRING_TABLE StringTable)
|
||||
{
|
||||
FreeStringTable (StringTable);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STRING
|
||||
CaptureStringTable (STRING_TABLE StringTable)
|
||||
{
|
||||
if ((StringTable != 0) && (StringTable->size > 0))
|
||||
{
|
||||
return StringTable->strings;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STRING_TABLE
|
||||
ReleaseStringTable (STRING String)
|
||||
{
|
||||
STRING_TABLE StringTable;
|
||||
|
||||
StringTable = GetStringTable (String);
|
||||
|
||||
return (StringTable);
|
||||
}
|
||||
|
||||
STRING_TABLE
|
||||
GetStringTable (STRING String)
|
||||
{
|
||||
if (String && String->parent)
|
||||
{
|
||||
return String->parent;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
COUNT
|
||||
GetStringTableCount (STRING String)
|
||||
{
|
||||
if (String && String->parent)
|
||||
{
|
||||
return String->parent->size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
COUNT
|
||||
GetStringTableIndex (STRING String)
|
||||
{
|
||||
if (String)
|
||||
{
|
||||
return String->index;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STRING
|
||||
SetAbsStringTableIndex (STRING String, COUNT StringTableIndex)
|
||||
{
|
||||
STRING_TABLE StringTablePtr;
|
||||
|
||||
if (!String)
|
||||
return NULL;
|
||||
|
||||
StringTablePtr = String->parent;
|
||||
|
||||
if (StringTablePtr == NULL)
|
||||
{
|
||||
String = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
StringTableIndex = StringTableIndex % StringTablePtr->size;
|
||||
String = &StringTablePtr->strings[StringTableIndex];
|
||||
}
|
||||
|
||||
return (String);
|
||||
}
|
||||
|
||||
STRING
|
||||
SetRelStringTableIndex (STRING String, SIZE StringTableOffs)
|
||||
{
|
||||
STRING_TABLE StringTablePtr;
|
||||
|
||||
if (!String)
|
||||
return NULL;
|
||||
|
||||
StringTablePtr = String->parent;
|
||||
|
||||
if (StringTablePtr == NULL)
|
||||
{
|
||||
String = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
COUNT StringTableIndex;
|
||||
|
||||
while (StringTableOffs < 0)
|
||||
StringTableOffs += StringTablePtr->size;
|
||||
StringTableIndex = (String->index + StringTableOffs)
|
||||
% StringTablePtr->size;
|
||||
|
||||
String = &StringTablePtr->strings[StringTableIndex];
|
||||
}
|
||||
|
||||
return (String);
|
||||
}
|
||||
|
||||
COUNT
|
||||
GetStringLength (STRING String)
|
||||
{
|
||||
if (String == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return utf8StringCountN(String->data, String->data + String->length);
|
||||
}
|
||||
|
||||
COUNT
|
||||
GetStringLengthBin (STRING String)
|
||||
{
|
||||
if (String == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return String->length;
|
||||
}
|
||||
|
||||
STRINGPTR
|
||||
GetStringSoundClip (STRING String)
|
||||
{
|
||||
STRING_TABLE StringTablePtr;
|
||||
COUNT StringIndex;
|
||||
|
||||
if (String == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StringTablePtr = String->parent;
|
||||
if (StringTablePtr == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StringIndex = String->index;
|
||||
if (!(StringTablePtr->flags & HAS_SOUND_CLIPS))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StringIndex += StringTablePtr->size;
|
||||
String = &StringTablePtr->strings[StringIndex];
|
||||
if (String->length == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return String->data;
|
||||
}
|
||||
|
||||
STRINGPTR
|
||||
GetStringTimeStamp (STRING String)
|
||||
{
|
||||
STRING_TABLE StringTablePtr;
|
||||
COUNT StringIndex;
|
||||
int offset;
|
||||
|
||||
if (String == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StringTablePtr = String->parent;
|
||||
if (StringTablePtr == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StringIndex = String->index;
|
||||
if (!(StringTablePtr->flags & HAS_TIMESTAMP))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
offset = (StringTablePtr->flags & HAS_SOUND_CLIPS) ? 1 : 0;
|
||||
StringIndex += StringTablePtr->size << offset;
|
||||
String = &StringTablePtr->strings[StringIndex];
|
||||
if (String->length == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return String->data;
|
||||
}
|
||||
|
||||
STRINGPTR
|
||||
GetStringAddress (STRING String)
|
||||
{
|
||||
if (String == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return String->data;
|
||||
}
|
||||
53
project/jni/application/sc2/src/libs/strings/strintrn.h
Normal file
53
project/jni/application/sc2/src/libs/strings/strintrn.h
Normal file
@@ -0,0 +1,53 @@
|
||||
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _STRINTRN_H
|
||||
#define _STRINTRN_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "libs/strlib.h"
|
||||
#include "libs/reslib.h"
|
||||
|
||||
struct string_table_entry
|
||||
{
|
||||
STRINGPTR data;
|
||||
int length; /* Internal NULs are allowed */
|
||||
int index;
|
||||
struct string_table *parent;
|
||||
};
|
||||
|
||||
struct string_table
|
||||
{
|
||||
unsigned short flags;
|
||||
int size;
|
||||
STRING_TABLE_ENTRY_DESC *strings;
|
||||
};
|
||||
|
||||
#define HAS_SOUND_CLIPS (1 << 0)
|
||||
#define HAS_TIMESTAMP (1 << 1)
|
||||
|
||||
STRING_TABLE AllocStringTable (int num_entries, int flags);
|
||||
void FreeStringTable (STRING_TABLE strtab);
|
||||
|
||||
void *_GetStringData (uio_Stream *fp, DWORD length);
|
||||
void *_GetBinaryTableData (uio_Stream *fp, DWORD length);
|
||||
void _GetConversationData (const char *path, RESOURCE_DATA *resdata);
|
||||
|
||||
#endif /* _STRINTRN_H */
|
||||
|
||||
541
project/jni/application/sc2/src/libs/strings/unicode.c
Normal file
541
project/jni/application/sc2/src/libs/strings/unicode.c
Normal file
@@ -0,0 +1,541 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "port.h"
|
||||
|
||||
#define UNICODE_INTERNAL
|
||||
#include "libs/unicode.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "libs/log.h"
|
||||
#include "libs/misc.h"
|
||||
|
||||
|
||||
// Resynchronise (skip everything starting with 0x10xxxxxx):
|
||||
static inline void
|
||||
resyncUTF8(const unsigned char **ptr) {
|
||||
while ((**ptr & 0xc0) == 0x80)
|
||||
(*ptr)++;
|
||||
}
|
||||
|
||||
// Get one character from a UTF-8 encoded string.
|
||||
// *ptr will point to the start of the next character.
|
||||
// Returns 0 if the encoding is bad. This can be distinguished from the
|
||||
// '\0' character by checking whether **ptr == '\0' before calling this
|
||||
// function.
|
||||
UniChar
|
||||
getCharFromString(const unsigned char **ptr) {
|
||||
UniChar result;
|
||||
|
||||
if (**ptr < 0x80) {
|
||||
// 0xxxxxxx, regular ASCII
|
||||
result = **ptr;
|
||||
(*ptr)++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((**ptr & 0xe0) == 0xc0) {
|
||||
// 110xxxxx; 10xxxxxx must follow
|
||||
// Value between 0x00000080 and 0x000007ff (inclusive)
|
||||
result = **ptr & 0x1f;
|
||||
(*ptr)++;
|
||||
|
||||
if ((**ptr & 0xc0) != 0x80)
|
||||
goto err;
|
||||
result = (result << 6) | ((**ptr) & 0x3f);
|
||||
(*ptr)++;
|
||||
|
||||
if (result < 0x00000080) {
|
||||
// invalid encoding - must reject
|
||||
goto err;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((**ptr & 0xf0) == 0xe0) {
|
||||
// 1110xxxx; 10xxxxxx 10xxxxxx must follow
|
||||
// Value between 0x00000800 and 0x0000ffff (inclusive)
|
||||
result = **ptr & 0x0f;
|
||||
(*ptr)++;
|
||||
|
||||
if ((**ptr & 0xc0) != 0x80)
|
||||
goto err;
|
||||
result = (result << 6) | ((**ptr) & 0x3f);
|
||||
(*ptr)++;
|
||||
|
||||
if ((**ptr & 0xc0) != 0x80)
|
||||
goto err;
|
||||
result = (result << 6) | ((**ptr) & 0x3f);
|
||||
(*ptr)++;
|
||||
|
||||
if (result < 0x00000800) {
|
||||
// invalid encoding - must reject
|
||||
goto err;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((**ptr & 0xf8) == 0xf0) {
|
||||
// 11110xxx; 10xxxxxx 10xxxxxx 10xxxxxx must follow
|
||||
// Value between 0x00010000 and 0x0010ffff (inclusive)
|
||||
result = **ptr & 0x07;
|
||||
(*ptr)++;
|
||||
|
||||
if ((**ptr & 0xc0) != 0x80)
|
||||
goto err;
|
||||
result = (result << 6) | ((**ptr) & 0x3f);
|
||||
(*ptr)++;
|
||||
|
||||
if ((**ptr & 0xc0) != 0x80)
|
||||
goto err;
|
||||
result = (result << 6) | ((**ptr) & 0x3f);
|
||||
(*ptr)++;
|
||||
|
||||
if ((**ptr & 0xc0) != 0x80)
|
||||
goto err;
|
||||
result = (result << 6) | ((**ptr) & 0x3f);
|
||||
(*ptr)++;
|
||||
|
||||
if (result < 0x00010000) {
|
||||
// invalid encoding - must reject
|
||||
goto err;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
err:
|
||||
log_add(log_Warning, "Warning: Invalid UTF8 sequence.");
|
||||
|
||||
// Resynchronise (skip everything starting with 0x10xxxxxx):
|
||||
resyncUTF8(ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UniChar
|
||||
getCharFromStringN(const unsigned char **ptr, const unsigned char *end) {
|
||||
size_t numBytes;
|
||||
|
||||
if (*ptr == end)
|
||||
goto err;
|
||||
|
||||
if (**ptr < 0x80) {
|
||||
numBytes = 1;
|
||||
} else if ((**ptr & 0xe0) == 0xc0) {
|
||||
numBytes = 2;
|
||||
} else if ((**ptr & 0xf0) == 0xe0) {
|
||||
numBytes = 3;
|
||||
} else if ((**ptr & 0xf8) == 0xf0) {
|
||||
numBytes = 4;
|
||||
} else
|
||||
goto err;
|
||||
|
||||
if (*ptr + numBytes > end)
|
||||
goto err;
|
||||
|
||||
return getCharFromString(ptr);
|
||||
|
||||
err:
|
||||
*ptr = end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get one line from a string.
|
||||
// A line is terminated with either CRLF (DOS/Windows),
|
||||
// LF (Unix, MacOS X), or CR (old MacOS).
|
||||
// The end of the string is reached when **startNext == '\0'.
|
||||
// NULL is returned if the string is not valid UTF8. In this case
|
||||
// *end points to the first invalid character (or the character before if
|
||||
// it was a LF), and *startNext to the start of the next (possibly invalid
|
||||
// too) character.
|
||||
unsigned char *
|
||||
getLineFromString(const unsigned char *start, const unsigned char **end,
|
||||
const unsigned char **startNext) {
|
||||
const unsigned char *ptr = start;
|
||||
const unsigned char *lastPtr;
|
||||
UniChar ch;
|
||||
|
||||
// Search for the first newline.
|
||||
for (;;) {
|
||||
if (*ptr == '\0') {
|
||||
*end = ptr;
|
||||
*startNext = ptr;
|
||||
return (unsigned char *) unconst(start);
|
||||
}
|
||||
lastPtr = ptr;
|
||||
ch = getCharFromString(&ptr);
|
||||
if (ch == '\0') {
|
||||
// Bad string
|
||||
*end = lastPtr;
|
||||
*startNext = ptr;
|
||||
return NULL;
|
||||
}
|
||||
if (ch == '\n') {
|
||||
*end = lastPtr;
|
||||
if (*ptr == '\0'){
|
||||
// LF at the end of the string.
|
||||
*startNext = ptr;
|
||||
return (unsigned char *) unconst(start);
|
||||
}
|
||||
ch = getCharFromString(&ptr);
|
||||
if (ch == '\0') {
|
||||
// Bad string
|
||||
return NULL;
|
||||
}
|
||||
if (ch == '\r') {
|
||||
// LFCR
|
||||
*startNext = ptr;
|
||||
} else {
|
||||
// LF
|
||||
*startNext = *end;
|
||||
}
|
||||
return (unsigned char *) unconst(start);
|
||||
} else if (ch == '\r') {
|
||||
*end = lastPtr;
|
||||
*startNext = ptr;
|
||||
return (unsigned char *) unconst(start);
|
||||
} // else: a normal character
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
utf8StringCount(const unsigned char *start) {
|
||||
size_t count = 0;
|
||||
UniChar ch;
|
||||
|
||||
for (;;) {
|
||||
ch = getCharFromString(&start);
|
||||
if (ch == '\0')
|
||||
return count;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
utf8StringCountN(const unsigned char *start, const unsigned char *end) {
|
||||
size_t count = 0;
|
||||
UniChar ch;
|
||||
|
||||
for (;;) {
|
||||
ch = getCharFromStringN(&start, end);
|
||||
if (ch == '\0')
|
||||
return count;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Locates a unicode character (ch) in a UTF-8 string (pStr)
|
||||
// returns the char positions when found
|
||||
// -1 when not found
|
||||
int
|
||||
utf8StringPos (const unsigned char *pStr, UniChar ch)
|
||||
{
|
||||
int pos;
|
||||
|
||||
for (pos = 0; *pStr != '\0'; ++pos)
|
||||
{
|
||||
if (getCharFromString (&pStr) == ch)
|
||||
return pos;
|
||||
}
|
||||
|
||||
if (ch == '\0' && *pStr == '\0')
|
||||
return pos;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Safe version of strcpy(), somewhat analogous to strncpy()
|
||||
// except it guarantees a 0-term when size > 0
|
||||
// when size == 0, returns NULL
|
||||
// BUG: this may result in the last character being only partially in the
|
||||
// buffer
|
||||
unsigned char *
|
||||
utf8StringCopy (unsigned char *dst, size_t size, const unsigned char *src)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
strncpy ((char *) dst, (const char *) src, size);
|
||||
dst[size - 1] = '\0';
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
// TODO: this is not implemented with respect to collating order
|
||||
int
|
||||
utf8StringCompare (const unsigned char *str1, const unsigned char *str2)
|
||||
{
|
||||
#if 0
|
||||
// UniChar comparing version
|
||||
UniChar ch1;
|
||||
UniChar ch2;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
ch1 = getCharFromString(&str1);
|
||||
ch2 = getCharFromString(&str2);
|
||||
if (ch1 == '\0' || ch2 == '\0')
|
||||
break;
|
||||
|
||||
cmp = utf8CompareChar (ch1, ch2);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
}
|
||||
|
||||
if (ch1 != '\0')
|
||||
{
|
||||
// ch2 == '\0'
|
||||
// str2 ends, str1 continues
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ch2 != '\0')
|
||||
{
|
||||
// ch1 == '\0'
|
||||
// str1 ends, str2 continues
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ch1 == '\0' && ch2 == '\0'.
|
||||
// Strings match completely.
|
||||
return 0;
|
||||
#else
|
||||
// this will do for now
|
||||
return strcmp ((const char *) str1, (const char *) str2);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
skipUTF8Chars(const unsigned char *ptr, size_t num) {
|
||||
UniChar ch;
|
||||
const unsigned char *oldPtr;
|
||||
|
||||
while (num--) {
|
||||
oldPtr = ptr;
|
||||
ch = getCharFromString(&ptr);
|
||||
if (ch == '\0')
|
||||
return (unsigned char *) unconst(oldPtr);
|
||||
}
|
||||
return (unsigned char *) unconst(ptr);
|
||||
}
|
||||
|
||||
// Decodes a UTF-8 string (start) into a unicode character string (wstr)
|
||||
// returns number of chars decoded and stored, not counting 0-term
|
||||
// any chars that do not fit are truncated
|
||||
// wide string term 0 is always appended, unless the destination
|
||||
// buffer is 0 chars long
|
||||
size_t
|
||||
getUniCharFromStringN(UniChar *wstr, size_t maxcount,
|
||||
const unsigned char *start, const unsigned char *end)
|
||||
{
|
||||
UniChar *next;
|
||||
|
||||
if (maxcount == 0)
|
||||
return 0;
|
||||
|
||||
// always leave room for 0-term
|
||||
--maxcount;
|
||||
|
||||
for (next = wstr; maxcount > 0; ++next, --maxcount)
|
||||
{
|
||||
*next = getCharFromStringN(&start, end);
|
||||
if (*next == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
*next = 0; // term
|
||||
|
||||
return next - wstr;
|
||||
}
|
||||
|
||||
// See getStringFromWideN() for functionality
|
||||
// the only difference is that the source string (start) length is
|
||||
// calculated by searching for 0-term
|
||||
size_t
|
||||
getUniCharFromString(UniChar *wstr, size_t maxcount,
|
||||
const unsigned char *start)
|
||||
{
|
||||
UniChar *next;
|
||||
|
||||
if (maxcount == 0)
|
||||
return 0;
|
||||
|
||||
// always leave room for 0-term
|
||||
--maxcount;
|
||||
|
||||
for (next = wstr; maxcount > 0; ++next, --maxcount)
|
||||
{
|
||||
*next = getCharFromString(&start);
|
||||
if (*next == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
*next = 0; // term
|
||||
|
||||
return next - wstr;
|
||||
}
|
||||
|
||||
// Encode one wide character into UTF-8
|
||||
// returns number of bytes used in the buffer,
|
||||
// 0 : invalid or unsupported char
|
||||
// <0 : negative of bytes needed if buffer too small
|
||||
// string term '\0' is *not* appended or counted
|
||||
int
|
||||
getStringFromChar(unsigned char *ptr, size_t size, UniChar ch)
|
||||
{
|
||||
int i;
|
||||
static const struct range_def
|
||||
{
|
||||
UniChar lim;
|
||||
int marker;
|
||||
int mask;
|
||||
}
|
||||
ranges[] =
|
||||
{
|
||||
{0x0000007f, 0x00, 0x7f},
|
||||
{0x000007ff, 0xc0, 0x1f},
|
||||
{0x0000ffff, 0xe0, 0x0f},
|
||||
{0x001fffff, 0xf0, 0x07},
|
||||
{0x03ffffff, 0xf8, 0x03},
|
||||
{0x7fffffff, 0xfc, 0x01},
|
||||
{0x00000000, 0x00, 0x00} // term
|
||||
};
|
||||
const struct range_def *def;
|
||||
|
||||
// lookup the range
|
||||
for (i = 0, def = ranges; ch > def->lim && def->mask != 0; ++i, ++def)
|
||||
;
|
||||
if (def->mask == 0)
|
||||
{ // invalid or unsupported char
|
||||
log_add(log_Warning, "Warning: Invalid or unsupported unicode "
|
||||
"char (%lu)", (unsigned long) ch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t)i + 1 > size)
|
||||
return -(i + 1);
|
||||
|
||||
// unrolled for speed
|
||||
switch (i)
|
||||
{
|
||||
case 5: ptr[5] = (ch & 0x3f) | 0x80;
|
||||
ch >>= 6;
|
||||
case 4: ptr[4] = (ch & 0x3f) | 0x80;
|
||||
ch >>= 6;
|
||||
case 3: ptr[3] = (ch & 0x3f) | 0x80;
|
||||
ch >>= 6;
|
||||
case 2: ptr[2] = (ch & 0x3f) | 0x80;
|
||||
ch >>= 6;
|
||||
case 1: ptr[1] = (ch & 0x3f) | 0x80;
|
||||
ch >>= 6;
|
||||
case 0: ptr[0] = (ch & def->mask) | def->marker;
|
||||
}
|
||||
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
// Encode a wide char string (wstr) into a UTF-8 string (ptr)
|
||||
// returns number of bytes used in the buffer (includes 0-term)
|
||||
// any chars that do not fit are truncated
|
||||
// string term '\0' is always appended, unless the destination
|
||||
// buffer is 0 bytes long
|
||||
size_t
|
||||
getStringFromWideN(unsigned char *ptr, size_t size,
|
||||
const UniChar *wstr, size_t count)
|
||||
{
|
||||
unsigned char *next;
|
||||
int used;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
// always leave room for 0-term
|
||||
--size;
|
||||
|
||||
for (next = ptr; size > 0 && count > 0;
|
||||
size -= used, next += used, --count, ++wstr)
|
||||
{
|
||||
used = getStringFromChar(next, size, *wstr);
|
||||
if (used < 0)
|
||||
break; // not enough room
|
||||
if (used == 0)
|
||||
{ // bad char?
|
||||
*next = '?';
|
||||
used = 1;
|
||||
}
|
||||
}
|
||||
|
||||
*next = '\0'; // term
|
||||
|
||||
return next - ptr + 1;
|
||||
}
|
||||
|
||||
// See getStringFromWideN() for functionality
|
||||
// the only difference is that the source string (wstr) length is
|
||||
// calculated by searching for 0-term
|
||||
size_t
|
||||
getStringFromWide(unsigned char *ptr, size_t size, const UniChar *wstr)
|
||||
{
|
||||
const UniChar *end;
|
||||
|
||||
for (end = wstr; *end != 0; ++end)
|
||||
;
|
||||
|
||||
return getStringFromWideN(ptr, size, wstr, (end - wstr));
|
||||
}
|
||||
|
||||
int
|
||||
UniChar_isGraph(UniChar ch)
|
||||
{ // this is not technically sufficient, but close enough for us
|
||||
// we'll consider all non-control (CO and C1) chars in 'graph' class
|
||||
// except for the "Private Use Area" (0xE000 - 0xF8FF)
|
||||
|
||||
// TODO: The private use area is really only glommed by OS X,
|
||||
// and even there, not all of it. (Delete and Backspace both
|
||||
// end up producing characters there -- see bug #942 for the
|
||||
// gory details.)
|
||||
return (ch > 0xa0 && (ch < 0xE000 || ch > 0xF8FF)) ||
|
||||
(ch > 0x20 && ch < 0x7f);
|
||||
}
|
||||
|
||||
int
|
||||
UniChar_isPrint(UniChar ch)
|
||||
{ // this is not technically sufficient, but close enough for us
|
||||
// chars in 'print' class are 'graph' + 'space' classes
|
||||
// the only space we currently have defined is 0x20
|
||||
return (ch == 0x20) || UniChar_isGraph(ch);
|
||||
}
|
||||
|
||||
UniChar
|
||||
UniChar_toUpper(UniChar ch)
|
||||
{ // this is a very basic Latin-1 implementation
|
||||
// just to get things going
|
||||
return (ch < 0x100) ? (UniChar) toupper((int) ch) : ch;
|
||||
}
|
||||
|
||||
UniChar
|
||||
UniChar_toLower(UniChar ch)
|
||||
{ // this is a very basic Latin-1 implementation
|
||||
// just to get things going
|
||||
return (ch < 0x100) ? (UniChar) tolower((int) ch) : ch;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user