windows-nt/Source/XPSP1/NT/enduser/stuff/itircl/common/chartab.c
2020-09-26 16:20:57 +08:00

897 lines
30 KiB
C

/*************************************************************************
* *
* CHARTAB.C *
* *
* Copyright (C) Microsoft Corporation 1990-1994 *
* All Rights reserved. *
* *
**************************************************************************
* *
* Module Intent *
* Character table indexing and retrieval. The reasons this module is *
* not put together with ansiusa are: *
* - Like stop words, this involves indexing and retrieval *
* - It is word breaker independent *
* *
**************************************************************************
* *
* Current Owner: Binh Nguyen *
* *
*************************************************************************/
#include <mvopsys.h>
#include <mem.h>
#include <memory.h>
#include <iterror.h>
#include <_mvutil.h>
#include <mvsearch.h>
#include "common.h"
#ifdef _DEBUG
static BYTE NEAR *s_aszModule = __FILE__; // Used by error return functions.
#endif
#define SLASH '/'
#define RETURN '\r'
#define NEWLINE '\n'
#define INBUF_SIZE 256 // Maximum buffer size to store a line
#define BYTE_MAX 256 // Maximum number of characters
#define LIGATURE_BYTES 3 // Number of bytes/ligature
/* External variables */
extern BYTE LigatureTable[];
extern CHARMAP DefaultCMap[];
/*************************************************************************
*
* API FUNCTIONS
* Those functions should be exported in a .DEF file
*************************************************************************/
PUBLIC LPV EXPORT_API FAR PASCAL MVCharTableLoad (HFPB, LSZ, PHRESULT);
PUBLIC LPV EXPORT_API FAR PASCAL MVCharTableGetDefault (PHRESULT);
PUBLIC VOID EXPORT_API FAR PASCAL MVCharTableDispose (LPVOID);
PUBLIC HRESULT EXPORT_API PASCAL FAR MVCharTableFileBuild (HFPB, LPVOID, LSZ);
PUBLIC LPV EXPORT_API FAR PASCAL MVCharTableIndexLoad(HFPB, LSZ, PHRESULT);
/*************************************************************************
*
* INTERNAL PRIVATE FUNCTIONS
* All of them should be declared near
*************************************************************************/
PRIVATE LPB NEAR PASCAL GetNumber (HFPB, LPB, LPB, int FAR *, WORD FAR *);
PRIVATE LPCHARTAB PASCAL NEAR CharTableCreate (int);
PRIVATE VOID PASCAL NEAR StripCRLF (LPB, WORD);
PRIVATE VOID PASCAL NEAR GetWord (LSZ FAR *, LST);
PUBLIC VOID PASCAL FAR FreeHandle2 (HANDLE hd)
{
if (hd) {
_GLOBALUNLOCK(hd);
_GLOBALFREE(hd);
}
}
/*************************************************************************
* @doc EXTERNAL API INDEX
*
* @func LPCHARTAB FAR PASCAL | MVCharTableLoad |
* Open an ASCII file and read in the description of the character
* tables. It then converts them into binary format ready to be used
* The format of the file is:
* Size // How many entries
* char class, normalized value, sorted value, mac display value
* ........
* char class, normalized value, sorted value, mac display value
* Comments are preceded by // and ignored until EOL
* A description of the ligature table, if any, is to followed the
* charmap table
*
* @parm HFPB | hfpbIn |
* Handle to system file or subfile; NULL if file is external.
*
* @parm LSZ | lszFilename |
* DOS filen containing the description of the tables
*
* @parm PHRESULT | phr |
* Error buffer
*
* @rdesc
* The function returns a pointer to the memory block containing
* tables, or NULL if failed. The error buffer will contain
* description for the cause of the failure
*
* @comm About ligature table, there are some assumptions:
* If there is no wcLigature, then the default table is used
* if (wcLigature == 0) no ligature should be used
* if wcLigature != 0, the author provides a ligature table.
*************************************************************************/
PUBLIC LPVOID EXPORT_API FAR PASCAL MVCharTableLoad (HFPB hfpbIn,
LSZ lszFilename, PHRESULT phr)
{
register WORD j; // Scratch index variable
register WORD i; // Scratch index variable
register LPB lpbBuf; // Pointer to input buffer
WORD cbRead; // How many bytes have read (left)
int wcTabEntries; // Number of table entries
int wTmp; // Scratch variable
HFPB hfpb; // Handle of char table file
BOOL fOpenedFile; // TRUE if we have to close the file
BYTE Buffer [INBUF_SIZE]; // Input buffer
LPCMAP lpCMap; // Pointer to character table entries
LPCHARTAB lpCharTab = NULL; // Pointer to general char table struct
int wcLigature;
LPB lpbChar; // Scratch pointer
/* Open subfile if necessary, (and system file if necessary) */
if ((fOpenedFile = FsTypeFromHfpb(hfpb = hfpbIn) != FS_SUBFILE) &&
(hfpb = (HANDLE)FileOpen
(hfpbIn, lszFilename, hfpbIn ? FS_SUBFILE : REGULAR_FILE,
READ, phr)) == 0)
{
SetErrCode (phr, E_FILENOTFOUND);
return NULL;
}
*phr = E_BADFORMAT;
/* Fill in the buffer */
if ((cbRead =
(WORD) FileRead(hfpb, lpbBuf = Buffer, INBUF_SIZE, phr)) == 0 ||
FAILED(*phr))
{
goto ErrorExit;
}
/* Get the table size */
lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wcTabEntries, &cbRead);
if (wcTabEntries == 0 || wcTabEntries > BYTE_MAX) {
goto ErrorExit;
}
/* Allocate memory for the character table */
if ((lpCharTab = CharTableCreate (wcTabEntries)) == NULL)
{
SetErrCode (phr, E_OUTOFMEMORY);
if (fOpenedFile)
FileClose (hfpb);
return NULL;
}
lpCMap = (LPCMAP)lpCharTab->lpCMapTab;
lpCharTab->wcTabEntries = (WORD) wcTabEntries;
/* Now read in invidual char table entry */
for (i = (WORD) wcTabEntries; i > 0; i--, lpCMap++) {
if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
&cbRead)) == NULL) {
/* Missing item */
goto ErrorExit;
}
lpCMap->Class = (WORD) wTmp;
if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
&cbRead)) == NULL) {
/* Missing item */
goto ErrorExit;
}
lpCMap->SortOrder = (WORD) wTmp;
if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
&cbRead)) == NULL) {
/* Missing item */
goto ErrorExit;
}
lpCMap->Norm = (BYTE)wTmp;
if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
&cbRead)) == NULL) {
/* Missing item */
goto ErrorExit;
}
lpCMap->WinCaseSensitiveNorm = (BYTE)wTmp;
if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
&cbRead)) == NULL) {
/* Missing item */
goto ErrorExit;
}
lpCMap->MacDisplay = (BYTE)wTmp;
if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
&cbRead)) == NULL) {
/* Missing item */
goto ErrorExit;
}
lpCMap->MacCaseSensitiveNorm = (BYTE)wTmp;
}
/*
* Check for valid table, ie. all reserved characters should not
* be modified
*/
/* Check for valid reserved type */
lpCMap = &(((LPCMAP)lpCharTab->lpCMapTab)[1]);
if (lpCMap->Class != CLASS_TYPE)
goto ErrorExit;
/* Check for ligatures */
if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf,
&wcLigature, &cbRead)) == NULL) {
/* No ligature table present, use default */
lpCharTab->wcLigature = DEF_LIGATURE_COUNT;
lpCharTab->fFlag = USE_DEF_LIGATURE;
lpCharTab->lpLigature = LigatureTable;
}
else {
if ((lpCharTab->wcLigature = (WORD) wcLigature) != 0) {
/* Ligature table present */
/* Allocate memory block. Notice that we allocate 3 extra bytes
* They will serve as sentinels for the end of the ligature
* table, thus eliminating the need of having to know beforehand
* what is the size of the table
*/
if ((lpCharTab->hLigature = _GLOBALALLOC (DLLGMEM_ZEROINIT,
LIGATURE_BYTES * (wcLigature + 1))) == 0) {
SetErrCode (phr, E_OUTOFMEMORY);
goto ErrorExit;
}
lpbChar = lpCharTab->lpLigature =
(LPB)_GLOBALLOCK(lpCharTab->hLigature);
/* Read in the entries */
for (i = (WORD) wcLigature; i > 0; i--) {
for (j = LIGATURE_BYTES; j > 0; j--) {
if (lpbBuf = GetNumber (hfpb, Buffer, lpbBuf,
&wTmp, &cbRead)) {
/* Update entry */
*lpbChar ++ = (BYTE)wTmp;
}
else {
/* Missing item */
goto ErrorExit;
}
}
}
lpCharTab->fFlag = LIGATURE_PROVIDED;
}
else
lpCharTab->fFlag = NO_LIGATURE;
}
if (fOpenedFile)
FileClose (hfpb);
return ((LPV)lpCharTab);
ErrorExit:
if (fOpenedFile)
FileClose (hfpb);
MVCharTableDispose (lpCharTab);
return NULL;
}
/*************************************************************************
* @doc API INDEX
*
* @func HRESULT PASCAL FAR | MVCharTableFileBuild |
* Incorporate the character table into the system file
*
* @parm HFPB | hfpbSysFile |
* Handle to system file. It is non-zero, then the system file is
* already open, else the function will open the system file
*
* @parm LPCHARTAB | lpCharTab |
* Pointer to character table information structure
*
* @parm LSZ | lszFilename |
* File name. If hpfbSysFile is 0, the format is:
* dos filename[!charfilename], else it is the name of the character
* file itself
*
* @rdesc ERR_SUCCESS if succeeded, other errors if failed.
*
* @comm About ligature table, there are some assumptions:
* If hLigature == 0 {
* if (wcLigature == 0)
* There is no ligature table
* else
* We use the default ligature table. There is no need
* to write out the table data
* }
* else
* The author provides a ligature table.
*************************************************************************/
PUBLIC HRESULT EXPORT_API PASCAL FAR MVCharTableFileBuild (HFPB hfpbSysFile,
LPCHARTAB lpCharTab, LSZ lszFilename)
{
HFPB hfpbCharTab; // Pointer to final index file info.
BOOL fCreatedFile;
CHARTAB_HDR CharTab_hdr; // Character table header
BYTE Dummy[CHARTAB_HDR_SIZE]; // Dummy buffer to write 0
FILEOFFSET foOffset; // File's offset
FILEOFFSET foStart;
WORD CharTabSize;
WORD CharLigatureSize;
// char szFullFilename[MAX_PATH];
HRESULT hr = S_OK;
if (lpCharTab == NULL || lpCharTab->wcTabEntries == 0)
{
/* Nothing to build */
return E_INVALIDARG;
}
/* If hfpbSysFile != 0, allocate a temp HFPB to use for the system file */
//if (!(fCloseSysFile = (char)(hfpbSysFile == 0))) {
// if ((hfpb = ALLOCTEMPFPB (hfpbSysFile, phr)) == NULL)
// return ERR_FAILED;
//}
if ((fCreatedFile =
FsTypeFromHfpb(hfpbCharTab = hfpbSysFile) != FS_SUBFILE) &&
0 == (hfpbCharTab = FileCreate
(hfpbSysFile, lszFilename,
hfpbSysFile ? FS_SUBFILE : REGULAR_FILE, &hr)))
{
return hr;
}
// If we didn't open the file, we need to find out where the file seek
// pointer is initially so that we only seek relative to that starting
// position (i.e. the caller owns the part of the file that comes before).
foStart = (fCreatedFile ? MakeFo(0,0) :
FileSeek (hfpbCharTab, MakeFo (0, 0), wFSSeekCur, &hr));
if (FAILED(hr))
goto exit01;
/* Write out the CharTab file header */
CharTab_hdr.FileStamp = CHRTAB_STAMP;
CharTab_hdr.version = CHARTABVER;
CharTabSize = lpCharTab->wcTabEntries * sizeof(CHARMAP);
/* the ligature table size:
* - is 0 if we are going to use the default table
* - Is non-0 if the author provides a ligature table
*/
switch (lpCharTab->fFlag)
{
case NO_LIGATURE:
case USE_DEF_LIGATURE:
CharLigatureSize = 0;
break;
default:
CharLigatureSize = lpCharTab->wcLigature * LIGATURE_BYTES;
}
CharTab_hdr.dwTabSize = CharTabSize + CharLigatureSize;
CharTab_hdr.wcTabEntries = lpCharTab->wcTabEntries;
CharTab_hdr.wcLigature = lpCharTab->wcLigature;
CharTab_hdr.fFlag = lpCharTab->fFlag;
MEMSET(Dummy, (BYTE)0, CHARTAB_HDR_SIZE);
/* Write all zero to the header */
if (FileSeekWrite(hfpbCharTab, Dummy, FoAddFo(foStart, foNil),
CHARTAB_HDR_SIZE, &hr) != CHARTAB_HDR_SIZE)
{
goto exit01;
}
if (FileSeekWrite(hfpbCharTab, &CharTab_hdr, FoAddFo(foStart, foNil),
sizeof(CHARTAB_HDR), &hr) != sizeof(CHARTAB_HDR))
{
goto exit01;
}
foOffset = FoAddFo(foStart, MakeFo(CHARTAB_HDR_SIZE,0L));
/* Write out the character table buffer */
if (FileSeekWrite(hfpbCharTab, lpCharTab->lpCMapTab, foOffset,
CharTabSize, &hr) != CharTabSize)
{
goto exit01;
}
if (CharLigatureSize)
{
foOffset = FoAddDw(foOffset,CharTabSize);
/* Write out the ligature table */
if (FileSeekWrite(hfpbCharTab, lpCharTab->lpLigature, foOffset,
CharLigatureSize, &hr) != CharLigatureSize)
{
goto exit01;
}
}
hr = S_OK;
exit01:
// Close file if we created it.
if (fCreatedFile)
FileClose(hfpbCharTab); // Removed fRet= here.
return hr;
}
/*************************************************************************
* @doc INTERNAL
*
* @func VOID PASCAL NEAR | GetWord |
* This function will scan and get a word from the input buffer
*
* @parm LSZ FAR | *lplszBuf |
* Pointer to input buffer. The content will be updated on exit
*
* @parm LST | lstWord |
* Buffer to received parsed word
*************************************************************************/
PRIVATE VOID PASCAL NEAR GetWord (LSZ FAR *lplszBuf, LST lstWord)
{
LST lstWordStart;
LSZ lszBuf = *lplszBuf;
/* Remember the beginning of the word */
lstWordStart = lstWord++;
/* Skip all beginning blanks */
while (*lszBuf == ' ')
lszBuf++;
/* Now keep accumulating the word's characters */
for (;;) {
switch (*lszBuf) {
case 0:
case ' ':
goto exit0;
case '/':
if (*(lszBuf + 1) == '/') {
/* Skip the inline comment */
while (*lszBuf)
lszBuf++;
goto exit0;
}
default:
*lstWord++ = *lszBuf++;
}
}
exit0:
*lplszBuf = lszBuf;
*lstWordStart = (BYTE)(lstWord - lstWordStart - 1);
}
/*************************************************************************
* @doc INTERNAL
*
* @func VOID PASCAL NEAR | StripCRLF |
* This function will change all CR, LF in the input buffer into
* 0, all tabs into blank
*
* @parm LPB | lpbBuf |
* Input buffer
*
* @parm WORD | BufSize |
* Length of the buffer
*************************************************************************/
PRIVATE VOID PASCAL NEAR StripCRLF (LPB lpbBuf, WORD BufSize)
{
for (; BufSize > 0; BufSize --)
{
switch (*lpbBuf)
{
case RETURN:
case NEWLINE:
*lpbBuf = 0;
break;
case '\t':
*lpbBuf = ' ';
break;
}
lpbBuf++;
}
}
/*************************************************************************
* @doc API RETRIEVAL
*
* @func LPCHARTAB FAR PASCAL | MVCharTableIndexLoad |
* This function will load a character table from a
* system file.
*
* @parm HANDLE | hfpbSysFile |
* If non-zero, this is the handle of an already opened system file
*
* @parm LSZ | lszFilename |
* If hpfbSysFile is non-zero, this is the name of the CharTab's subfile
* else this is the combined filename with the format
* "dos_filename[CharTab_filename]"
* If the subfile's name is not specified, the default CharTab's file
* name will be used
*
* @parm PHRESULT | phr |
* Pointer to error buffer
*
* @rdesc If succeeded, the function will return a pointer the loaded
* CharTab, else NULL. The error buffer will contain information
* about the cause of the failure
*
* @comm About ligature table, there are some assumptions:
* If hLigature == 0 {
* if (wcLigature == 0)
* There is no ligature table
* else
* We use the default ligature table. There is no need
* to write out the table data
* }
* else
* The author provides a ligature table.
*************************************************************************/
PUBLIC LPVOID EXPORT_API FAR PASCAL MVCharTableIndexLoad(HFPB hfpbSysFile,
LSZ lszFilename, PHRESULT phr)
{
HANDLE hfpbCharTabFile;
BOOL fOpenedFile;
LPCHARTAB lpCharTab = NULL;
CHARTAB_HDR FAR *lpCharTabHdr;
CHARTAB_HDR CharTabHdr;
FILEOFFSET foStart;
#if _MAC
int MacClipMap[256], i;
LPCMAP lpCMapEntry;
#endif
*phr = S_OK;
lpCharTabHdr = &CharTabHdr;
/* Open subfile, (and system file if necessary) */
if ((fOpenedFile =
FsTypeFromHfpb(hfpbCharTabFile = hfpbSysFile) != FS_SUBFILE) &&
(hfpbCharTabFile = (HANDLE)FileOpen
(hfpbSysFile, lszFilename, hfpbSysFile ? FS_SUBFILE : REGULAR_FILE,
READ, phr)) == 0)
{
exit0:
return (LPV)lpCharTab;
}
// If we didn't open the file, we need to find out where the file seek
// pointer is initially so that we only seek relative to that starting
// position (i.e. the caller owns the part of the file that comes before).
foStart = (fOpenedFile ? MakeFo(0,0) :
FileSeek (hfpbCharTabFile, MakeFo (0, 0), wFSSeekCur, phr));
/* Read in the header file, and make sure that is a CharTab file */
if (FAILED(*phr) ||
FileSeekRead(hfpbCharTabFile, (LPV)lpCharTabHdr, FoAddFo(foStart, foNil),
sizeof(CHARTAB_HDR), phr) != sizeof(CHARTAB_HDR)) {
exit1:
/* Close the subfile if we opened it */
if (fOpenedFile)
FileClose(hfpbCharTabFile);
/* Close the system file if we open it, the handle will be
* released in the process */
goto exit0;
}
/* MAC code. They will be optimized out */
lpCharTabHdr->FileStamp = SWAPWORD(lpCharTabHdr->FileStamp);
lpCharTabHdr->version = SWAPWORD(lpCharTabHdr->version);
lpCharTabHdr->wcTabEntries = SWAPWORD(lpCharTabHdr->wcTabEntries);
lpCharTabHdr->wcLigature = SWAPWORD(lpCharTabHdr->wcLigature);
lpCharTabHdr->fFlag = SWAPWORD(lpCharTabHdr->fFlag);
lpCharTabHdr->dwTabSize = SWAPLONG(lpCharTabHdr->dwTabSize);
/* Check to see if the data read in is valid */
if (lpCharTabHdr->FileStamp != CHRTAB_STAMP)
{ // File stamp
SetErrCode(phr, E_BADVERSION);
goto exit1;
}
/* Allocate memory for the character table. Note that there may be
* some inefficiency im memory usage, since there are 3-bytes per
* ligature entry, and several more for each charmap entry.
*/
if ((lpCharTab = CharTableCreate ((lpCharTabHdr->wcTabEntries +
lpCharTabHdr->wcLigature))) == NULL) {
SetErrCode(phr, E_OUTOFMEMORY);
goto exit1;
}
lpCharTab->wcTabEntries = lpCharTabHdr->wcTabEntries;
lpCharTab->fFlag = lpCharTabHdr->fFlag;
lpCharTab->hLigature = 0;
/* Read in the CharTab bitmap data */
if (FileSeekRead(hfpbCharTabFile,
(LPV)lpCharTab->lpCMapTab, FoAddFo(foStart, MakeFo(CHARTAB_HDR_SIZE,0)),
(WORD)lpCharTabHdr->dwTabSize, phr) !=
(WORD)lpCharTabHdr->dwTabSize)
{
MVCharTableDispose(lpCharTab);
lpCharTab = NULL;
goto exit1;
}
#if _MAC
/* Create the mapping from Mac to Windows. This is to deal with the
* situation people entering data on a Mac and look for that string
*/
lpCMapEntry = (LPCMAP)lpCharTab->lpCMapTab;
for (i = lpCharTab->wcTabEntries; i > 0; i--)
{
// erinfox: swap class
lpCMapEntry[i].Class = SWAPWORD(lpCMapEntry[i].Class);
lpCMapEntry[i].SortOrder = SWAPWORD(lpCMapEntry[i].SortOrder);
if (lpCMapEntry[i].MacDisplay != 0)
{
lpCMapEntry[lpCMapEntry[i].MacDisplay].MacToWin = i;
}
}
/* Change the Mac clipboard mapping. I am using the 256 value.
* The character table hasthe mapping based on the Windows indices
* but since the WinToMap mapping will change all the character
* values to their corresponding Mac, the new values have to be
* used as indices, ie. there is a need to remap the
* MacCaseSensitiveNorm column based on the new Mac indices
*/
MEMSET (MacClipMap, 0, 256);
for ( i = 0; i < lpCharTab->wcTabEntries; i++)
{
MacClipMap[lpCMapEntry[i].MacDisplay] =
lpCMapEntry[i].MacCaseSensitiveNorm;
}
/* Reset the mapping. */
/* Change all 0's to 32 (space) to avoid truncation */
for ( i = 0; i < lpCharTab->wcTabEntries; i++)
{
if ((lpCMapEntry[i].MacCaseSensitiveNorm = MacClipMap[i]) == 0)
lpCMapEntry[i].MacCaseSensitiveNorm = 32;
}
#endif /* _MAC */
/* Look for ligature */
switch (lpCharTab->fFlag) {
case NO_LIGATURE:
break;
case USE_DEF_LIGATURE:
lpCharTab->wcLigature = DEF_LIGATURE_COUNT;
lpCharTab->fFlag = USE_DEF_LIGATURE;
lpCharTab->hLigature = 0;
lpCharTab->lpLigature = LigatureTable;
break;
default:
lpCharTab->lpLigature = (LPB)lpCharTab->lpCMapTab +
lpCharTabHdr->wcTabEntries * sizeof(CHARMAP);
lpCharTab->wcLigature = lpCharTabHdr->wcLigature;
}
goto exit1;
}
/*************************************************************************
* @doc API RETRIEVAL
* @func LPCTAB FAR PASCAL | MVCharTableGetDefault |
* Retrieve the default character mapping table used by MV
* @parm PHRESULT | phr |
* Pointer to error buffer
* @rdesc
* Pointer to character mapping table if successful, NULL otherwise.
* In case of error, phr will contain the error code
*************************************************************************/
PUBLIC LPV EXPORT_API FAR PASCAL MVCharTableGetDefault (PHRESULT phr)
{
LPCHARTAB lpCharTab = NULL;
#if _MAC
int i;
LPCMAP lpCMapEntry;
#endif /* _MAC */
/* Allocate memory for the character table. Note that there may be
* some inefficiency im memory usage, since there are 3-bytes per
* ligature entry, and several more for each charmap entry.
*/
if ((lpCharTab = CharTableCreate (MAX_CHAR_COUNT +
DEF_LIGATURE_COUNT)) == NULL) {
SetErrCode(phr, E_OUTOFMEMORY);
return NULL;
}
lpCharTab->wcTabEntries = MAX_CHAR_COUNT;
lpCharTab->wcLigature = DEF_LIGATURE_COUNT;
lpCharTab->fFlag = USE_DEF_LIGATURE;
lpCharTab->hLigature = 0;
lpCharTab->lpLigature = LigatureTable;
lpCharTab->lpCMapTab = DefaultCMap;
#if _MAC
/* Create the mapping from Mac to Windows. This is to deal with the
* situation people entering data on a Mac and look for that string
*/
lpCMapEntry = (LPCMAP)lpCharTab->lpCMapTab;
for (i = lpCharTab->wcTabEntries; i > 0; i--) {
if (lpCMapEntry[i].MacDisplay != 0) {
lpCMapEntry[lpCMapEntry[i].MacDisplay].MacToWin = i;
}
}
/* Create the clipboard case sensitive column */
#endif /* _MAC */
return(lpCharTab);
}
/*************************************************************************
* @doc API INDEX RETRIEVAL
*
* @func VOID FAR PASCAL | MVCharTableDispose |
* Free all memory associated with the character table
*
* @parm LPCHARTAB | lpCharTab |
* Pointer to character table structure
*************************************************************************/
PUBLIC VOID EXPORT_API FAR PASCAL MVCharTableDispose (LPCHARTAB lpCharTab)
{
HANDLE hBuf;
if (lpCharTab == NULL)
return;
if (hBuf = lpCharTab->hLigature) {
FreeHandle2(hBuf);
lpCharTab->hLigature = NULL;
}
FreeHandle2(lpCharTab->hStruct);
}
/*************************************************************************
* @doc API INDEX RETRIEVAL
*
* @func VOID FAR PASCAL | MVCharTableSetWildcards |
* Change the property of '*' and '?' to CLASS_WILDCARD.
*
* @parm LPCHARTAB | lpCharTab |
* Pointer to character table structure
*************************************************************************/
PUBLIC VOID EXPORT_API FAR PASCAL MVCharTableSetWildcards (LPCHARTAB lpCharTab)
{
if (lpCharTab == NULL)
return;
(lpCharTab->lpCMapTab)['*'].Class = CLASS_WILDCARD;
(lpCharTab->lpCMapTab)['?'].Class = CLASS_WILDCARD;
}
/*************************************************************************
* @doc INTERNAL
*
* @func LPB NEAR PASCAL | GetNumber |
* This function will try to get to a number in an ASCII and then
* retrieve it. It will fill up the input buffer if necessary
*
* @parm HFPB | hfpb |
* Handle of opened file
*
* @parm LPB | Buffer |
* Buffer to store the input data
*
* @parm LPB | lpbBuf |
* Current location pointer into the input buffer
*
* @parm int far * | lpNum |
* Place to store the retrieved number
*
* @parm WORD FAR * | lpcbRead |
* How many bytes are left in the input buffer
*
* @rdesc If succeeded, the function will return the last location
* of the input buffer, else NULL if failed. If succeeded, the
* number is stored in *lpNum, the number of bytes left in the input
* buffer is updated
*************************************************************************/
PRIVATE LPB NEAR PASCAL GetNumber (HFPB hfpb, LPB Buffer, LPB lpbBuf,
int far *lpNum, WORD FAR *lpcbRead)
{
register WORD fSkipComment = 0;
register WORD cbRead = *lpcbRead;
WORD number = 0;
BYTE fGetNum = FALSE;
HRESULT hr;
for (;;) {
/* Check for empty buffer, and read in new data if necessary */
if (cbRead == 0) {
cbRead = (WORD) FileRead(hfpb, lpbBuf = Buffer, INBUF_SIZE, &hr);
if (cbRead == 0 || FAILED(hr)) {
if (fGetNum == FALSE)
lpbBuf = NULL; // Return error
break;
}
}
if (*lpbBuf == RETURN || *lpbBuf == NEWLINE) {
/* EOL, reset variables, exit if we already got a number */
fSkipComment = 0;
if (fGetNum)
break;
}
else if (fSkipComment != 2) {
/* We are not inside a comment, so look for a number */
if (*lpbBuf >= '0' && *lpbBuf <= '9') {
/* Get the number */
number = number * 10 + *lpbBuf - '0';
fGetNum = TRUE;
}
else if (*lpbBuf == SLASH) {
if (fGetNum)
break;
fSkipComment++; // Increment slash count
}
else {
if (fGetNum)
break;
fSkipComment = 0;
}
}
cbRead--;
lpbBuf++;
}
/* Update the variables */
*lpcbRead = cbRead;
*lpNum = number;
return lpbBuf;
}
/*************************************************************************
* @doc INTERNAL
*
* @func LPCHARTAB PASCAL NEAR | CharTableCreate |
* Allocate memory necessary for the character table. The amount
* needed is based on the number of entries
*
* @parm WORD | wcTabEntries |
* Number of entries in the character table
*
*************************************************************************/
PRIVATE LPCHARTAB PASCAL NEAR CharTableCreate (int wcTabEntries)
{
HANDLE hMem;
LPCHARTAB lpCharTab;
/* Allocate memory for the character table */
if ((hMem = _GLOBALALLOC (DLLGMEM_ZEROINIT,
sizeof(CHARTAB) + wcTabEntries * sizeof(CHARMAP))) == NULL) {
return NULL;
}
lpCharTab = (LPCHARTAB)_GLOBALLOCK(hMem);
lpCharTab->lpCMapTab = (LPCMAP)(lpCharTab + 1);
lpCharTab->hStruct = hMem;
return lpCharTab;
}