📄 nls.c
字号:
/****************************************************************/
/* */
/* nls.c */
/* FreeDOS */
/* */
/* National Languge Support functions and data structures */
/* */
/* Copyright (c) 2000 */
/* Steffen Kaiser */
/* All Rights Reserved */
/* */
/* This file is part of FreeDOS. */
/* */
/* DOS-C 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, or (at your option) any later version. */
/* */
/* DOS-C 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 DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
/*
* Note 1: Some code assume certains prerequisites to be matched,
* e.g. character tables exactly 128 bytes long; I try to keep\
* track of these conditions within comments marked with:
* ==ska*/
#include "portab.h"
#include "globals.h"
#include "pcb.h"
#include <nls.h>
#ifdef VERSION_STRINGS
static BYTE *RcsId =
"$Id: nls.c,v 1.19 2004/03/19 22:33:48 bartoldeman Exp $";
#endif
#ifdef NLS_DEBUG
#define log(a) printf a
#define log1(a) printf a
#else
#define log(a)
#ifdef NDEBUG
#define log1(a)
#else
#define log1(a) printf a
#endif
#endif
struct nlsInfoBlock nlsInfo = {
(char FAR *)0 /* filename to COUNTRY.SYS */
, 437 /* system code page */
/* Implementation flags */
, 0
#ifdef NLS_MODIFYABLE_DATA
| NLS_CODE_MODIFYABLE_DATA
#endif
#ifdef NLS_REORDER_POINTERS
| NLS_CODE_REORDER_POINTERS
#endif
, &nlsPackageHardcoded /* hardcoded first package */
, &nlsPackageHardcoded /* first item in chain */
};
/* getTableX return the pointer to the X'th table; X==subfct */
/* subfct 2: normal upcase table; 4: filename upcase table */
#ifdef NLS_REORDER_POINTERS
#define getTable2(nls) ((nls)->nlsPointers[0].pointer)
#define getTable4(nls) ((nls)->nlsPointers[1].pointer)
#else
#define getTable2(nls) getTable(2, (nls))
#define getTable4(nls) getTable(4, (nls))
#define NEED_GET_TABLE
#endif
/*== both chartables must be 128 bytes long and lower range is
identical to 7bit-US-ASCII ==ska*/
#define getCharTbl2(nls) \
(((struct nlsCharTbl FAR*)getTable2(nls))->tbl - 0x80)
#define getCharTbl4(nls) \
(((struct nlsCharTbl FAR*)getTable4(nls))->tbl - 0x80)
/********************************************************************
***** MUX calling functions ****************************************
********************************************************************/
extern int ASMCFUNC call_nls(UWORD, struct nlsInfoBlock *, UWORD, UWORD, UWORD,
UWORD, void FAR *, UWORD *);
/*== DS:SI _always_ points to global NLS info structure <-> no
* subfct can use these registers for anything different. ==ska*/
STATIC COUNT muxGo(int subfct, UWORD bp, UWORD cp, UWORD cntry, UWORD bufsize,
void FAR *buf, UWORD *id)
{
int ret;
log(("NLS: muxGo(): subfct=%x, cntry=%u, cp=%u, ES:DI=%p\n",
subfct, cntry, cp, buf));
ret = call_nls(subfct, &nlsInfo, bp, cp, cntry, bufsize, buf, id);
log(("NLS: muxGo(): return value = %d\n", ret));
return ret;
}
/*
* Call NLSFUNC to load the NLS package
*/
COUNT muxLoadPkg(UWORD cp, UWORD cntry)
{
UWORD id; /* on stack, call_nls in int2f.asm takes care of this
* if DS != SS */
/* 0x1400 == not installed, ok to install */
/* 0x1401 == not installed, not ok to install */
/* 0x14FF == installed */
#if NLS_FREEDOS_NLSFUNC_VERSION == NLS_FREEDOS_NLSFUNC_ID
/* make sure the NLSFUNC ID is updated */
#error "NLS_FREEDOS_NLSFUNC_VERSION == NLS_FREEDOS_NLSFUNC_ID"
#endif
if (muxGo(0, 0, NLS_FREEDOS_NLSFUNC_VERSION, 0, NLS_FREEDOS_NLSFUNC_ID, 0,
(UWORD *)&id) != 0x14ff)
return DE_FILENOTFND; /* No NLSFUNC --> no load */
if (id != NLS_FREEDOS_NLSFUNC_ID) /* FreeDOS NLSFUNC will return */
return DE_INVLDACC; /* This magic number */
/* OK, the correct NLSFUNC is available --> load pkg */
/* If cp == -1 on entry, NLSFUNC updates cp to the codepage loaded
into memory. The system must then change to this one later */
return muxGo(NLSFUNC_LOAD_PKG, 0, cp, cntry, 0, 0, 0);
}
STATIC int muxBufGo(int subfct, int bp, UWORD cp, UWORD cntry,
UWORD bufsize, VOID FAR * buf)
{
log(("NLS: muxBufGo(): subfct=%x, BP=%u, cp=%u, cntry=%u, len=%u, buf=%p\n",
subfct, bp, cp, cntry, bufsize, buf));
return muxGo(subfct, bp, cp, cntry, bufsize, buf, 0);
}
#define mux65(s,cp,cc,bs,b) muxBufGo(2, (s), (cp), (cc), (bs), (b))
#define mux38(cp,cc,bs,b) muxBufGo(4, 0, (cp), (cc), (bs), (b))
#define muxYesNo(ch) muxBufGo(NLSFUNC_YESNO,0, NLS_DEFAULT, NLS_DEFAULT, (ch), 0)
#define muxUpMem(s,b,bs) muxBufGo((s),0, NLS_DEFAULT,NLS_DEFAULT, (bs), (b))
/********************************************************************
***** Helper functions**********************************************
********************************************************************/
/*
* Search for the NLS package within the chain
* Also resolves the default values (-1) into the currently
* active codepage/country code.
*/
STATIC struct nlsPackage FAR *searchPackage(UWORD cp, UWORD cntry)
{
struct nlsPackage FAR *nls;
if (cp == NLS_DEFAULT)
cp = nlsInfo.actPkg->cp;
if (cntry == NLS_DEFAULT)
cntry = nlsInfo.actPkg->cntry;
nls = nlsInfo.chain;
while ((nls->cp != cp || nls->cntry != cntry)
&& (nls = nls->nxt) != NULL) ;
return nls;
}
/* For various robustnesses reasons and to simplify the implementation
at other places, locateSubfct() returns NULL (== "not found"),
if nls == NULL on entry. */
STATIC VOID FAR *locateSubfct(struct nlsPackage FAR * nls, int subfct)
{
int cnt;
struct nlsPointer FAR *p;
if (nls)
for (cnt = nls->numSubfct, p = &nls->nlsPointers[0]; cnt--; ++p)
if (p->subfct == (UBYTE) subfct)
return p;
return NULL;
}
#ifdef NEED_GET_TABLE
/* search the table (from a subfct) from the active package */
/* Note: Because this table returns the pointers for stuff of
*internal* purpose, it seems to be more comfortable that this
function is guaranteed to return valid pointers, rather than
to let the user (some kernel function) deal with non-existing
tables -- 2000/02/26 ska*/
STATIC VOID FAR *getTable(UBYTE subfct, struct nlsPackage FAR * nls)
{
struct nlsPointer FAR *poi;
if ((poi = locateSubfct(nls, subfct)) != NULL)
return poi;
/* Failed --> return the hardcoded table */
switch (subfct)
{
case 2:
return &nlsUpHardcodedTable;
case 4:
return &nlsFnameUpHardcodedTable;
/* case 5: return &nlsFnameTermHardcodedTable; */
/* case 6: return &nlsCollHardcodedTable; */
}
}
#endif
/*
* Copy a buffer and test the size of the buffer
* Returns SUCCESS on success; DE_INVLDFUNC on failure
*
* Efficiency note: This function is used as:
* return cpyBuf(buf, bufsize, ...)
* three times. If the code optimizer is some good, it can re-use
* the code to push bufsize, buf, call cpyBuf() and return its result.
* The parameter were ordered to allow this code optimization.
*/
STATIC COUNT cpyBuf(VOID FAR * dst, UWORD dstlen, VOID FAR * src,
UWORD srclen)
{
if (srclen <= dstlen)
{
fmemcpy(dst, src, srclen);
return SUCCESS;
}
return DE_INVLDFUNC; /* buffer too small */
}
/*
* This function assumes that 'map' is adjusted such that
* map[0x80] is the uppercase of character 0x80.
*== 128 byte chartables, lower range conform to 7bit-US-ASCII ==ska*/
STATIC VOID upMMem(UBYTE FAR * map, UBYTE FAR * str, unsigned len)
{
REG unsigned c;
#ifdef NLS_DEBUG
UBYTE FAR *oldStr;
unsigned oldLen;
oldStr = str;
oldLen = len;
log(("NLS: upMMem(): len=%u, %04x:%04x=\"", len, FP_SEG(str),
FP_OFF(str)));
for (c = 0; c < len; ++c)
printf("%c", str[c] > 32 ? str[c] : '.');
printf("\"\n");
#endif
if (len)
do
{
if ((c = *str) >= 'a' && c <= 'z')
*str += 'A' - 'a';
else if (c > 0x7f)
*str = map[c];
++str;
}
while (--len);
#ifdef NLS_DEBUG
printf("NLS: upMMem(): result=\"");
for (c = 0; c < oldLen; ++c)
printf("%c", oldStr[c] > 32 ? oldStr[c] : '.');
printf("\"\n");
#endif
}
/********************************************************************
***** Lowlevel interface *******************************************
********************************************************************/
/* GetData function used by both the MUX-callback function and
the direct-access interface.
subfct == NLS_DOS_38 is a value > 0xff in order to not clash
with subfunctions valid to be passed as DOS-65-XX. */
STATIC int nlsGetData(struct nlsPackage FAR * nls, int subfct,
UBYTE FAR * buf, unsigned bufsize)
{
VOID FAR *poi;
log(("NLS: nlsGetData(): subfct=%x, bufsize=%u, cp=%u, cntry=%u\n",
subfct, bufsize, nls->cp, nls->cntry));
/* Theoretically tables 1 and, if NLS_REORDER_POINTERS is enabled,
2 and 4 could be hard-coded, because their
data is located at predictable (calculatable) locations.
However, 1 and subfct NLS_DOS_38 are to handle the same
data and the "locateSubfct()" call has to be implemented anyway,
in order to handle all subfunctions.
Also, NLS is often NOT used in any case, so this code is more
size than speed optimized. */
if ((poi = locateSubfct(nls, subfct)) != NULL)
{
log(("NLS: nlsGetData(): subfunction found\n"));
switch (subfct)
{
case 1: /* Extended Country Information */
return cpyBuf(buf, bufsize, poi,
((struct nlsExtCntryInfo FAR *)poi)->size + 3);
case NLS_DOS_38: /* Normal Country Information */
return cpyBuf(buf, bufsize, &(((struct nlsExtCntryInfo FAR *)poi)->dateFmt), 24); /* standard cinfo has no more 34 _used_ bytes */
/* don't copy 34, copy only 0x18 instead,
see comment at DosGetCountryInformation TE */
default:
/* All other subfunctions just return the found nlsPoinerInf
structure */
return cpyBuf(buf, bufsize, poi, sizeof(struct nlsPointer));
}
}
/* The requested subfunction could not been located within the
NLS pkg --> error. Because the data corresponds to the subfunction
number passed to the API, the failure is the same as that a wrong
API function has been called. */
log(("NLS: nlsGetData(): Subfunction not found\n"));
return DE_INVLDFUNC;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -