NLS.C
上传用户:dcs7469208
上传日期:2010-01-02
资源大小:443k
文件大小:19k
源码类别:

操作系统开发

开发平台:

DOS

  1. /****************************************************************/
  2. /*                                                              */
  3. /*                            nls.c                             */
  4. /*                            DOS-C                             */
  5. /*                                                              */
  6. /*    National Languge Support functions and data structures    */
  7. /*                                                              */
  8. /*                   Copyright (c) 1995, 1996                   */
  9. /*                      Pasquale J. Villani                     */
  10. /*                      All Rights Reserved                     */
  11. /*                                                              */
  12. /*                   Copyright (c) 1995, 1996                   */
  13. /*                         Steffen Kaiser                       */
  14. /*                      All Rights Reserved                     */
  15. /*                                                              */
  16. /* This file is part of DOS-C.                                  */
  17. /*                                                              */
  18. /* DOS-C is free software; you can redistribute it and/or       */
  19. /* modify it under the terms of the GNU General Public License  */
  20. /* as published by the Free Software Foundation; either version */
  21. /* 2, or (at your option) any later version.                    */
  22. /*                                                              */
  23. /* DOS-C is distributed in the hope that it will be useful, but */
  24. /* WITHOUT ANY WARRANTY; without even the implied warranty of   */
  25. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See    */
  26. /* the GNU General Public License for more details.             */
  27. /*                                                              */
  28. /* You should have received a copy of the GNU General Public    */
  29. /* License along with DOS-C; see the file COPYING.  If not,     */
  30. /* write to the Free Software Foundation, 675 Mass Ave,         */
  31. /* Cambridge, MA 02139, USA.                                    */
  32. /****************************************************************/
  33. /* $Logfile:   C:/dos-c/src/kernel/nls.c_v  $ */
  34. #ifdef VERSION_STRINGS
  35. static BYTE *RcsId = "$Header:   C:/dos-c/src/kernel/nls.c_v   1.4   04 Jan 1998 23:15:16   patv  $";
  36. #endif
  37. /* $Log:   C:/dos-c/src/kernel/nls.c_v  $
  38.  * 
  39.  *    Rev 1.4   04 Jan 1998 23:15:16   patv
  40.  * Changed Log for strip utility
  41.  * 
  42.  *    Rev 1.3   16 Jan 1997 12:46:54   patv
  43.  * pre-Release 0.92 feature additions
  44.  * 
  45.  *    Rev 1.2   29 May 1996 21:03:46   patv
  46.  * bug fixes for v0.91a
  47.  * 
  48.  *    Rev 1.1   19 Feb 1996  4:34:46   patv
  49.  * Corrected typo
  50.  * 
  51.  *    Rev 1.0   19 Feb 1996  3:21:46   patv
  52.  * Added NLS, int2f and config.sys processing
  53.  */
  54. /* $EndLog$ */
  55. #include "../../hdr/portab.h"
  56. #include "globals.h"
  57. extern UWORD internalUpcase(UWORD c);
  58. #ifndef lint
  59. static char const rcsid[] = 
  60.         "$Id$";
  61. #endif
  62. /* one byte alignment */
  63. #if defined(_MSC_VER) 
  64.     #define asm __asm
  65.     #pragma pack(1)
  66. #elif defined(_QC) || defined(__WATCOM__)
  67.     #pragma pack(1)
  68. #elif defined(__ZTC__)
  69.     #pragma ZTC align 1
  70. #elif defined(__TURBOC__) && (__TURBOC__ > 0x202)
  71.     #pragma option -a-
  72. #endif
  73. struct ctryInfo {       /* Country Information DOS-38 */
  74.         WORD dateFmt;                   /* 0: USA, 1: Europe, 2: Japan */
  75.         char curr[5];                   /* ASCIZ of currency string */
  76.         char thSep[2];                  /* ASCIZ of thousand's separator */
  77.         char point[2];                  /* ASCIZ of decimal point */
  78.         char dateSep[2];                /* ASCIZ of date separator */
  79.         char timeSep[2];                /* ASCIZ of time separator */
  80.         BYTE currFmt;                   /* format of currency:
  81.                                                 bit 0: currency string is placed 0: before, 1: behind number
  82.                                                 bit 1: currency string and number are separated by a space; 0: No, 1: Yes
  83.                                         */
  84.         BYTE prescision;                /* */
  85.         BYTE timeFmt;                   /* time format: 0: 12 hours; 1: 24 houres */
  86.         VOID (FAR *upCaseFct)(VOID);    /* far call to a function mapping character in register AL */
  87.         char dataSep[2];                /* ASCIZ of separator in data records */
  88. };
  89. struct _VectorTable
  90. {
  91.         VOID FAR *Table;
  92.         BYTE FnCode;
  93. }; 
  94. struct _NlsInfo
  95. {
  96.         struct extCtryInfo
  97.         {
  98.                 BYTE reserved[8];
  99.                 BYTE countryFname[64];
  100.                 WORD sysCodePage;
  101.                 WORD nFnEntries;
  102.                 struct _VectorTable VectorTable[6];
  103.                 
  104.                 /* Extended Country Information DOS-65-01 */
  105.                 WORD countryCode;               /* current COUNTRY= code */
  106.                 WORD codePage;                  /* current code page (CP) */
  107.                 struct ctryInfo nlsCtryInfo;
  108.         } nlsExtCtryInfo;
  109. /* characters of Yes/No prompt for DOS-65-23 */
  110.         char yesCharacter;
  111.         char noCharacter;
  112. /* upcased characters for ECS-ASCII > 0x7f for DOS-65-02 */
  113.         WORD upNCsize;                  /* number of entries in the following array */
  114.         char upNormCh[128];
  115. /* upcased characters for ECS-ASCII > 0x7f for file names for DOS-65-04 */
  116.         WORD upFCsize;                  /* number of entries in the following array */
  117.         char upFileCh[128];
  118. /* collating sequence for ECS-ASCII 0..0xff for DOS-65-06 */
  119.         WORD collSize;                  /* number of entries in the following array */
  120.         char collSeq[256];
  121. /* DBC support for DOS-65-07 */
  122.         WORD dbcSize;                   /* number of entries in the following array */
  123.         /* char dbcTable[1024]; no DBC support */
  124.         WORD dbcEndMarker;              /* contains always 0 */
  125. /* in file names permittable characters for DOS-65-05 */
  126.         struct chFileNames {
  127.                 WORD fnSize;                    /* size of this structure */
  128.                 BYTE dummy1;
  129.                 char firstCh, lastCh;   /* first, last permittable character */
  130.                 BYTE dummy2;
  131.                 char firstExcl, lastExcl;       /* first, last excluded character */
  132.                 BYTE dummy3;
  133.                 BYTE numSep;            /* number of file name separators */
  134.                 char fnSeparators[14];
  135.         } nlsFn;
  136. } nlsInfo
  137. #ifdef INIT_NLS_049
  138. =               /* let's initialize it with values for Germany */
  139. #include "049-437.nls"
  140. #else
  141. =               /* let's initialize it with default values (USA) */
  142. #include "001-437.nls"
  143. #endif
  144. ;
  145. #define normalCh nlsInfo.upNormCh
  146. #define fileCh nlsInfo.upFileCh
  147. #define yesChar nlsInfo.yesCharacter
  148. #define noChar nlsInfo.noCharacter
  149. #define PathSep(c) ((c)=='/'||(c)=='\')
  150. #define DriveChar(c) (((c)>='A'&&(c)<='Z')||((c)>='a'&&(c)<='z'))
  151. /*  COUNTRY.SYS structures */
  152. struct  CpiHeader
  153. {
  154.         BYTE    name[8];                /* signature */
  155.         BYTE    reserved[8];
  156.         WORD    nPointers;              /* size of following array */
  157.         
  158.         struct  
  159.         {
  160.                 BYTE    pointerType;    /* always 1 */
  161.                 DWORD   offset;         /* offset to data */
  162.         }       pointer[1];
  163. };
  164. struct  CountryRecord
  165. {
  166.         WORD    length;                 /* size of record */
  167.         WORD    country;                /* country code */
  168.         WORD    codePage;               /* code page */
  169.         WORD    reserved[2];
  170.         DWORD   subCountryOffset;       /* offset to data record */
  171. };
  172. struct  CountryTableDescr
  173. {
  174.         WORD    length;         /* size of structure */
  175.         WORD    id;             /* table type id */
  176.         DWORD   offset;         /* offset to table data */
  177. };
  178. /* standard alignment */
  179. #if defined (_MSC_VER) || defined(_QC) || defined(__WATCOMC__)
  180.  #pragma pack()
  181. #elif defined (__ZTC__)
  182.  #pragma ZTC align
  183. #elif defined(__TURBOC__) && (__TURBOC__ > 0x202)
  184.  #pragma option -a.
  185. #endif
  186.  
  187. COUNT NlsFuncInst(VOID)
  188. {
  189.         BYTE cNlsRet;
  190.         asm {
  191.                 xor     bx,bx
  192.                 mov     ax,1400h
  193.                 int     2Fh
  194.                 mov     cNlsRet,al
  195.         }
  196.         /* Return the al register as sign extended:                     */
  197.         /*               0 == not installed, ok to install              */
  198.         /*               1 == not installed, not ok to install          */
  199.         /*              -1 == installed                                 */
  200.         return cNlsRet;
  201. }
  202. BOOL
  203. GetGlblCodePage(UWORD FAR *ActvCodePage, UWORD FAR *SysCodePage)
  204. {
  205.         *ActvCodePage = nlsInfo.nlsExtCtryInfo.codePage;
  206.         *SysCodePage = nlsInfo.nlsExtCtryInfo.sysCodePage;
  207.         return TRUE;
  208. }
  209. BOOL
  210. SetGlblCodePage(UWORD FAR *ActvCodePage, UWORD FAR *SysCodePage)
  211. {
  212.         nlsInfo.nlsExtCtryInfo.codePage = *ActvCodePage;
  213.         nlsInfo.nlsExtCtryInfo.sysCodePage = *SysCodePage;
  214.         return TRUE;
  215. }
  216. UWORD SetCtryInfo(UBYTE FAR *lpShrtCode, UWORD FAR *lpLongCode,
  217.         BYTE FAR *lpTable, UBYTE *nRetCode)
  218. {
  219.         UWORD CntryCode;
  220.         UBYTE nNlsEntry;
  221.         UWORD uSegTable, uOffTable;
  222.         UBYTE nLclRet;
  223.         /* Get the Country Code according to the DOS silly rules.       */
  224.         if(0xff != *lpShrtCode)
  225.                 CntryCode = *lpShrtCode;
  226.         else
  227.                 CntryCode = *lpLongCode;
  228.         /* If it's the same country code as what's installed, just      */
  229.         /* return because there's nothing to do.                        */
  230.         if(CntryCode == nlsInfo.nlsExtCtryInfo.countryCode)
  231.         {
  232.                 *nRetCode = 0;
  233.                 return CntryCode;
  234.         }
  235.         /* Check if nlsfunc is installed                                */
  236.         if(NlsFuncInst() >= 0)
  237.         {
  238.                 *nRetCode = 0xff;
  239.                 return 0xffff;
  240.         }
  241.         /* Get the country information from nlsfunc                     */
  242.         uSegTable = FP_SEG(lpTable);
  243.         uOffTable = FP_OFF(lpTable);
  244.         asm {
  245.                 push    ds
  246.                 mov     bx,CntryCode
  247.                 mov     ax,uSegTable
  248.                 mov     dx,uOffTable
  249.                 mov     ds,ax
  250.                 mov     ax,1404h
  251.                 int     2Fh
  252.                 pop     ds
  253.                 mov     CntryCode,bx
  254.                 mov     nLclRet,al
  255.         }
  256.         *nRetCode = nLclRet;
  257.         return CntryCode;
  258. UWORD GetCtryInfo(UBYTE FAR *lpShrtCode, UWORD FAR *lpLongCode,
  259.         BYTE FAR *lpTable)
  260. {
  261.         UWORD CntryCode;
  262.         if(0xff != *lpShrtCode)
  263.                 CntryCode = *lpShrtCode;
  264.         else
  265.                 CntryCode = *lpLongCode;
  266.         fbcopy((BYTE FAR *)&nlsInfo.nlsExtCtryInfo.nlsCtryInfo,
  267.           lpTable, sizeof(struct ctryInfo));
  268.         return nlsInfo.nlsExtCtryInfo.countryCode;
  269. BOOL
  270. ExtCtryInfo(UBYTE nOpCode, UWORD CodePageID, UWORD InfoSize, VOID FAR *Information)
  271. {
  272.         VOID FAR *lpSource;
  273.         COUNT nIdx;
  274.         if(0xffff != CodePageID)
  275.         {
  276.                 UBYTE nNlsEntry;
  277.                 if(NlsFuncInst() >= 0)
  278.                         return FALSE;
  279.                 asm {
  280.                         mov     bp,word ptr nOpCode
  281.                         mov     bx,CodePageID
  282.                         mov     si,word ptr Information+2
  283.                         mov     ds,si
  284.                         mov     si,word ptr Information
  285.                         mov     ax,1402h
  286.                         int     2Fh
  287.                         cmp     al,0
  288.                         mov     nNlsEntry,al
  289.                 }
  290.                 if(0 != nNlsEntry)
  291.                         return FALSE;
  292.                 return  TRUE;
  293.         }
  294.         CodePageID = nlsInfo.nlsExtCtryInfo.codePage;
  295.         for(nIdx = 0; nIdx < nlsInfo.nlsExtCtryInfo.nFnEntries; nIdx++)
  296.         {
  297.                 if(nlsInfo.nlsExtCtryInfo.VectorTable[nIdx].FnCode == nOpCode)
  298.                 {
  299.                         BYTE FAR *bp = Information;
  300.                         lpSource = nlsInfo.nlsExtCtryInfo.VectorTable[nIdx].Table;
  301.                         if (nOpCode == 1)
  302.                         {
  303.                             bp++;     // first byte unused    
  304.                             *bp = (BYTE)(sizeof(struct ctryInfo) + 4);
  305.                             bp += 2;
  306.                             fbcopy(lpSource, bp, InfoSize > 3? InfoSize - 3 : 0);
  307.                         } else {
  308.                             *bp++ = nOpCode;
  309.                             *((VOID FAR **)bp) = lpSource;
  310.                         }
  311.                         return TRUE;
  312.                 }
  313.         }
  314.         return FALSE;
  315. }
  316. UWORD internalUpcase(UWORD c)
  317. {            
  318.         if (!(c & 0x80)) return c;
  319.         return (c & 0xff00) | (nlsInfo.upNormCh[c & 0x7f] & 0xff);
  320. }
  321. char upMChar(UPMAP map, char ch)
  322. /* upcase character ch according to the map */
  323. {       return (ch >= 'a' && ch <= 'z')? ch + 'A' - 'a':
  324.                         ((unsigned)ch > 0x7f? map[ch & 0x7f]: ch);
  325. }
  326. VOID upMMem(UPMAP map, char FAR *str, unsigned len)
  327. {       REG unsigned c;
  328.         if(len) do {
  329.                 if((c = *str) >= 'a' && c <= 'z')
  330.                         *str += 'A' - 'a';
  331.                 else if(c > 0x7f)
  332.                         *str = map[c & 0x7f];
  333.                 ++str;
  334.         } while(--len);
  335. }
  336. BYTE yesNo(char ch)     /* returns: 0: ch == "No", 1: ch == "Yes", 2: ch crap */
  337. {
  338.         ch = upMChar(normalCh, ch);
  339.         if(ch == noChar)
  340.                 return 0;
  341.         if(ch == yesChar)
  342.                 return 1;
  343.         return 2;
  344. }
  345. char upChar(char ch) /* upcase a single character */
  346. {
  347.         return upMChar(normalCh, ch);
  348. }
  349. VOID upString(char FAR *str)    /* upcase a string */
  350. {
  351.         upMMem(normalCh, str, fstrlen(str));
  352. }
  353. VOID upMem(char FAR *str, unsigned len) /* upcase a memory area */
  354. {
  355.         upMMem(normalCh, str, len);
  356. }
  357. char upFChar(char ch) /* upcase a single character for file names */
  358. {
  359.         return upMChar(fileCh, ch);
  360. }
  361. VOID upFString(char FAR *str)   /* upcase a string for file names */
  362. {
  363.         upMMem(fileCh, str, fstrlen(str));
  364. }
  365. VOID upFMem(char FAR *str, unsigned len)        /* upcase a memory area for file names */
  366. {
  367.         upMMem(fileCh, str, len);
  368. }
  369. /*      LoadCountryInfo():
  370.  *
  371.  *      Searches a file in the COUNTRY.SYS format for an entry 
  372.  *      matching the specified code page and country code, and loads 
  373.  *      the corresponding information into memory. If code page is 0, 
  374.  *      the default code page for the country will be used.
  375.  *
  376.  *      Returns TRUE if successful, FALSE if not.
  377.  */
  378.  
  379. BOOL    LoadCountryInfo(char FAR *filename, WORD ctryCode, WORD codePage)
  380. {
  381.         struct CpiHeader hdr;
  382.         struct CountryRecord ctry;
  383.         struct CountryTableDescr ct;
  384.         COUNT i, nCountries, nSubEntries;
  385.         ULONG currpos;
  386.         int rc = FALSE;
  387.         COUNT file;
  388.         if ((file = dos_open(filename, 0)) < 0)
  389.                 return rc;
  390.         
  391.         if (dos_read(file, &hdr, sizeof hdr) == sizeof hdr)
  392.         {
  393.             /* check signature */
  394.             if (!fstrncmp(hdr.name, "377COUNTRY", 8))
  395.             {    
  396.                 dos_lseek(file, hdr.pointer[0].offset, 0);
  397.                 dos_read(file, &nCountries, sizeof nCountries);
  398.                 /* search for matching country record */
  399.                 for (i = 0; i < nCountries; i++)
  400.                 {
  401.                    if (dos_read(file, &ctry, sizeof ctry) != sizeof ctry)
  402.                        break;
  403.                    if (ctry.country == ctryCode && (!codePage || ctry.codePage == codePage))
  404.                    {    
  405.                         /* found country - now load the tables */
  406.                         dos_lseek(file, ctry.subCountryOffset, 0);
  407.                         dos_read(file, &nSubEntries, sizeof nSubEntries);
  408.                         currpos = ctry.subCountryOffset + sizeof nSubEntries;
  409.                         for (i = 0; i < nSubEntries; i++)
  410.                         {
  411.                             dos_lseek(file, currpos, 0);
  412.                             if (dos_read(file, &ct, sizeof ct) != sizeof ct)
  413.                                 break;
  414.                             currpos += ct.length + sizeof ct.length;
  415.                             ReadCountryTable(file, ct.id, ct.offset + 8);
  416.                         }
  417.                         
  418.                         if (i == nSubEntries) rc = TRUE;
  419.                         break;
  420.                    }
  421.                 }
  422.             }
  423.         }
  424.         dos_close(file);
  425.         return rc;
  426. }
  427. /*      ReadCountryTable():
  428.  *
  429.  *      Loads a country information table. 
  430.  */
  431. static  BOOL ReadCountryTable(COUNT file, WORD id, ULONG offset)
  432. {
  433.         VOID    *buf;           /* where to load the information */
  434.         UWORD   maxSize;        /* max number of bytes to read   */
  435.         UWORD   length;         /* length of table in file       */
  436.         BOOL    rc = TRUE;
  437.         switch (id)
  438.         {
  439.             case 1:     /* extended country information */
  440.                 buf = &nlsInfo.nlsExtCtryInfo.countryCode;
  441.                 maxSize = sizeof(struct ctryInfo) + sizeof(WORD) * 2;
  442.                 break;
  443.             case 2:     /* uppercase table              */
  444.                 buf = &normalCh[0];
  445.                 maxSize = sizeof normalCh;
  446.                 break;
  447.             case 4:     /* filename uppercase table     */
  448.                 buf = &fileCh[0];
  449.                 maxSize = sizeof fileCh;
  450.                 break;
  451.             case 5:     /* filename terminator table    */
  452.                 buf = &nlsInfo.nlsFn.dummy1;
  453.                 maxSize = sizeof(struct chFileNames) - sizeof(WORD);
  454.                 break;
  455.             case 6:     /* collating sequence table     */
  456.                 buf = &nlsInfo.collSeq[0];
  457.                 maxSize = sizeof nlsInfo.collSeq;
  458.                 break;
  459.             default:    /* unknown or unsupported table - ignore  */
  460.                 buf = 0;
  461.                 break;
  462.         }
  463.         if (buf)
  464.         {
  465.             dos_lseek(file, offset, 0);
  466.             dos_read(file, &length, sizeof length);
  467.             
  468.             if (length > maxSize) length = maxSize;
  469.             
  470.             if (dos_read(file, buf, length) != length)
  471.                 rc = FALSE;
  472.             if (id == 1)  
  473.                 nlsInfo.nlsExtCtryInfo.nlsCtryInfo.upCaseFct = CharMapSrvc;
  474.         }
  475.         return rc;
  476. }