From 333b605b2afd472b823aeda0adf0e8b1ea9843c0 Mon Sep 17 00:00:00 2001 From: fishsoupisgood Date: Mon, 27 May 2019 02:41:51 +0100 Subject: initial commit from asl-1.41r8.tar.gz --- nls.c | 644 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 644 insertions(+) create mode 100644 nls.c (limited to 'nls.c') diff --git a/nls.c b/nls.c new file mode 100644 index 0000000..f377003 --- /dev/null +++ b/nls.c @@ -0,0 +1,644 @@ +/* nls.c */ +/*****************************************************************************/ +/* AS-Portierung */ +/* */ +/* Abhandlung landesspezifischer Unterschiede */ +/* */ +/* Historie: 16. 5.1996 Grundsteinlegung */ +/* 28. 7.1999 %T ist Abkuerzung fuer %H:%M:%S */ +/* */ +/*****************************************************************************/ + +#undef DEBUG_NLS + +#include "stdinc.h" +#include +#include +#include + +#ifdef LOCALE_NLS +#include +#include +#endif + +#ifdef OS2_NLS +#define INCL_DOSNLS +#include +#endif + +#ifdef DOS_NLS +#include +#endif + +#include "strutil.h" + +#include "nls.h" + +CharTable UpCaseTable; /* Umsetzungstabellen */ +CharTable LowCaseTable; + +static NLS_CountryInfo NLSInfo; +static CharTable CollateTable; + +/*-------------------------------------------------------------------------------*/ + +/* einen String anhand einer Tabelle uebersetzen: */ + + static void TranslateString(char *s, CharTable Table) +BEGIN + for (; *s!='\0'; s++) *s=Table[((unsigned int) *s)&0xff]; +END + +/*-------------------------------------------------------------------------------*/ +/* Da es moeglich ist, die aktuelle Codeseite im Programmlauf zu wechseln, + ist die Initialisierung in einer getrennten Routine untergebracht. Nach + einem Wechsel stellt ein erneuter Aufruf wieder korrekte Verhaeltnisse + her. Wen das stoert, der schreibe einfach einen Aufruf in den Initiali- + sierungsteil der Unit hinein. */ + +#ifdef DOS_NLS +typedef struct + { + Byte TimeFmt; + Byte DateFmt; + char Currency[2]; + char ThouSep[2]; + char DecSep[2]; + Byte Reserved[24]; + } Dos2CountryInfo; +typedef struct + { + Word DateFmt; + char Currency[5]; + char ThouSep[2]; + char DecSep[2]; + char DateSep[2]; + char TimeSep[2]; + Byte CurrFmt; + Byte CurrDecimals; + Byte TimeFmt; + char *UpCasePtr; + char DataSep[2]; + Byte Dummy[8]; + } Dos3CountryInfo; +typedef struct + { + Byte SubFuncNo; + char *Result; + } DosTableRec; + + char *DosCopy(char *Src, int Len) +BEGIN + char *res=malloc(sizeof(char)*(Len+1)); + memcpy(res,Src,Len); res[Len]='\0'; + return res; +END + + void StandardUpCases(void) +BEGIN + char *s1,*s2; + + s1=CH_ae; s2=CH_Ae; UpCaseTable[((unsigned int) *s1)&0xff]=*s2; + s1=CH_oe; s2=CH_Oe; UpCaseTable[((unsigned int) *s1)&0xff]=*s2; + s1=CH_ue; s2=CH_Ue; UpCaseTable[((unsigned int) *s1)&0xff]=*s2; +END +#endif + + void NLS_Initialize(void) +BEGIN + char *tmpstr,*run,*cpy; + Word FmtBuffer; + int z; +#ifdef DEBUG_NLS + int z2; +#endif + Boolean DidDate; + +#ifdef LOCALE_NLS + struct lconv *lc; +#endif + +#ifdef OS2_NLS + COUNTRYCODE ccode; + COUNTRYINFO cinfo; + ULONG erglen; +#endif + +#ifdef DOS_NLS + union REGS Regs; + struct SREGS SRegs; + void *info; + Dos2CountryInfo DOS2Info; + Dos3CountryInfo DOS3Info; + DosTableRec DOSTablePtr; +#endif + + /* get currency format, separators */ + +#ifdef NO_NLS + NLSInfo.DecSep="."; + NLSInfo.DataSep=","; + NLSInfo.ThouSep=","; + NLSInfo.Currency="$"; + NLSInfo.CurrDecimals=2; + NLSInfo.CurrFmt=CurrFormatPreNoBlank; +#endif + +#ifdef LOCALE_NLS + lc=localeconv(); + + NLSInfo.DecSep=(lc->mon_decimal_point!=Nil)?lc->decimal_point:"."; + + NLSInfo.ThouSep=(lc->mon_thousands_sep!=Nil)?lc->mon_thousands_sep:","; + + NLSInfo.DataSep=","; + + NLSInfo.Currency=(lc->currency_symbol!=Nil)?lc->currency_symbol:"$"; + + NLSInfo.CurrDecimals=lc->int_frac_digits; + if (NLSInfo.CurrDecimals>4) NLSInfo.CurrDecimals=2; + + if (lc->p_cs_precedes) + if (lc->p_sep_by_space) NLSInfo.CurrFmt=CurrFormatPreBlank; + else NLSInfo.CurrFmt=CurrFormatPreNoBlank; + else + if (lc->p_sep_by_space) NLSInfo.CurrFmt=CurrFormatPostBlank; + else NLSInfo.CurrFmt=CurrFormatPostNoBlank; +#endif + +#ifdef OS2_NLS + ccode.country=0; ccode.codepage=0; + DosQueryCtryInfo(sizeof(cinfo),&ccode,&cinfo,&erglen); + + NLSInfo.Country=cinfo.country; + NLSInfo.CodePage=cinfo.codepage; + NLSInfo.DecSep=strdup(cinfo.szDecimal); + NLSInfo.DataSep=strdup(cinfo.szDataSeparator); + NLSInfo.ThouSep=strdup(cinfo.szThousandsSeparator); + NLSInfo.Currency=strdup(cinfo.szCurrency); + NLSInfo.CurrDecimals=cinfo.cDecimalPlace; + NLSInfo.CurrFmt=(CurrFormat) cinfo.fsCurrencyFmt; +#endif + +#ifdef DOS_NLS + if (_osmajor<3) NLSInfo.CodePage=437; + else if (_osminor<30) NLSInfo.CodePage=437; + else + BEGIN + Regs.x.ax=0x6601; + int86(0x21,&Regs,&Regs); + NLSInfo.CodePage=Regs.x.bx; + END + + Regs.x.ax=0x3800; + if (_osmajor<3) info=&DOS2Info; else info=&DOS3Info; + SRegs.ds=FP_SEG(info); Regs.x.dx=FP_OFF(info); + int86x(0x21,&Regs,&Regs,&SRegs); + NLSInfo.Country=Regs.x.bx; + if (_osmajor>=3) + BEGIN + NLSInfo.DecSep=DosCopy(DOS3Info.DecSep,2); + NLSInfo.DataSep=DosCopy(DOS3Info.DataSep,2); + NLSInfo.ThouSep=DosCopy(DOS3Info.ThouSep,2); + NLSInfo.Currency=DosCopy(DOS3Info.Currency,5); + NLSInfo.CurrDecimals=DOS3Info.CurrDecimals; + NLSInfo.CurrFmt=(CurrFormat) DOS3Info.CurrFmt; + END + /* DOS 2 kennt noch nicht soviel, daher muessen wir selber etwas beisteuern */ + else + BEGIN + NLSInfo.DecSep=DosCopy(DOS2Info.DecSep,2); + NLSInfo.DataSep=","; + NLSInfo.ThouSep=DosCopy(DOS2Info.ThouSep,2); + NLSInfo.Currency=DosCopy(DOS2Info.Currency,2); + NLSInfo.CurrDecimals=(NLSInfo.Country==39) ? 0 : 2; + switch (NLSInfo.Country) + BEGIN + case 1: case 39: + NLSInfo.CurrFmt=CurrFormatPreNoBlank; break; + case 3: case 33: case 34: case 358: + NLSInfo.CurrFmt=CurrFormatPostBlank; break; + default: + NLSInfo.CurrFmt=CurrFormatPreBlank; + END + END +#endif + + /* get date format */ + +#ifdef NO_NLS + tmpstr="%m/%d/%y"; DidDate=False; +#endif + +#ifdef LOCALE_NLS + tmpstr=nl_langinfo(D_FMT); + if ((tmpstr==Nil) OR (*tmpstr == '\0')) tmpstr="%m/%d/%y"; + DidDate=False; +#endif + +#ifdef OS2_NLS + NLSInfo.DateFmt=(DateFormat) cinfo.fsDateFmt; + NLSInfo.DateSep=strdup(cinfo.szDateSeparator); + DidDate=True; +#endif + +#ifdef DOS_NLS + if (_osmajor>=3) + BEGIN + NLSInfo.DateFmt=(DateFormat) DOS3Info.DateFmt; + NLSInfo.DateSep=DosCopy(DOS3Info.DateSep,2); + END + else + BEGIN + NLSInfo.DateFmt=(DateFormat) DOS2Info.DateFmt; + switch (NLSInfo.Country) + BEGIN + case 3: case 47: case 351: case 32: case 33: case 39: case 34: + NLSInfo.DateSep="/"; break; + case 49: case 358: case 41: + NLSInfo.DateSep="."; break; + case 972: + NLSInfo.DateSep=" "; break; + default: + NLSInfo.DateSep="-"; + END + END + DidDate=True; +#endif + + if (NOT DidDate) + BEGIN + NLSInfo.DateSep=Nil; FmtBuffer=0; run=tmpstr; + while (*run!='\0') + if (*run=='%') + BEGIN + FmtBuffer<<=4; + switch (toupper(*(++run))) + BEGIN + case 'D': FmtBuffer+=1; break; + case 'M': FmtBuffer+=2; break; + case 'Y': FmtBuffer+=3; break; + END + if (NLSInfo.DateSep==Nil) + BEGIN + run++; cpy=NLSInfo.DateSep=strdup(" "); + while ((*run!=' ') AND (*run!='%')) *(cpy++)=(*(run++)); + *cpy='\0'; + END + else run++; + END + else run++; + if (FmtBuffer==0x213) NLSInfo.DateFmt=DateFormatMTY; + else if (FmtBuffer==0x123) NLSInfo.DateFmt=DateFormatTMY; + else NLSInfo.DateFmt=DateFormatYMT; + END + + /* get time format */ + +#ifdef NO_NLS + tmpstr="%H:%M:%S"; DidDate=False; +#endif + +#ifdef LOCALE_NLS + tmpstr=nl_langinfo(T_FMT); + if ((tmpstr==Nil) OR (*tmpstr == '\0')) tmpstr="%H:%M:%S"; + DidDate=False; +#endif + +#ifdef OS2_NLS + NLSInfo.TimeFmt=(TimeFormat) cinfo.fsTimeFmt; + NLSInfo.TimeSep=strdup(cinfo.szTimeSeparator); + DidDate=True; +#endif + +#ifdef DOS_NLS + if (_osmajor>=3) + BEGIN + NLSInfo.TimeFmt=(TimeFormat) DOS3Info.TimeFmt; + NLSInfo.TimeSep=DosCopy(DOS3Info.TimeSep,2); + END + else + BEGIN + NLSInfo.TimeFmt=(TimeFormat) DOS2Info.TimeFmt; + switch (NLSInfo.Country) + BEGIN + case 41: case 46: case 47: case 358: + NLSInfo.TimeSep="."; + default: + NLSInfo.TimeSep=":"; + END + END + DidDate=True; +#endif + + if (NOT DidDate) + BEGIN + NLSInfo.TimeSep=Nil; FmtBuffer=0; run=tmpstr; + while (*run!='\0') + if (*run=='%') + BEGIN + FmtBuffer<<=4; + switch (toupper(*(++run))) + BEGIN + case 'S': FmtBuffer+=1; break; + case 'M': FmtBuffer+=2; break; + case 'H': FmtBuffer+=3; break; + case 'T': fprintf(stderr, "\nwarning, detected non-ANSI time format specifier '%%T'"); + run = "H:%M:%S"; break; + case 'R': fprintf(stderr, "\nwarning, detected non-ANSI time format specifier '%%R'"); + run = "H:%M"; break; + END + if (NLSInfo.TimeSep==Nil) + BEGIN + run++; cpy=NLSInfo.TimeSep=strdup(" "); + while ((*run != '\0') AND (*run!=' ') AND (*run!='%')) + *(cpy++)=(*(run++)); + *cpy='\0'; + END + else run++; + END + else run++; + NLSInfo.TimeFmt=TimeFormatEurope; + END + + /* get lower->upper case table */ + +#if defined(NO_NLS) || defined(LOCALE_NLS) + for (z=0; z<256; z++) UpCaseTable[z]=toupper(z); +#endif + +#ifdef OS2_NLS + for (z=0; z<256; z++) UpCaseTable[z]=(char) z; + for (z='a'; z<='z'; z++) UpCaseTable[z]-='a'-'A'; + DosMapCase(sizeof(UpCaseTable),&ccode,UpCaseTable); +#endif + +#ifdef DOS_NLS + for (z=0; z<256; z++) UpCaseTable[z]=(char) z; + for (z='a'; z<='z'; z++) UpCaseTable[z]-='a'-'A'; +#ifdef __DPMI16__ + StandardUpCases(); +#else + if ((((Word)_osmajor)*100)+_osminor>=330) + BEGIN + Regs.x.ax=0x6502; + Regs.x.bx=NLSInfo.CodePage; + Regs.x.dx=NLSInfo.Country; + Regs.x.cx=sizeof(DOSTablePtr); + info=&DOSTablePtr; SRegs.es=FP_SEG(info); Regs.x.di=FP_OFF(info); + int86x(0x21,&Regs,&Regs,&SRegs); + if (Regs.x.cx==sizeof(DOSTablePtr)) + BEGIN + DOSTablePtr.Result+=sizeof(Word); + memcpy(UpCaseTable+128,DOSTablePtr.Result,128); + END + else StandardUpCases(); + END + else StandardUpCases(); +#endif +#endif + + /* get upper->lower case table */ + +#if defined(NO_NLS) || defined(LOCALE_NLS) + for (z=0; z<256; z++) LowCaseTable[z]=tolower(z); +#endif + +#if defined(OS2_NLS) || defined(DOS_NLS) + for (z=0; z<256; z++) LowCaseTable[z]=(char) z; + for (z=255; z>=0; z--) + if (UpCaseTable[z]!=(char) z) + LowCaseTable[((unsigned int) UpCaseTable[z])&0xff]=(char) z; +#endif + + /* get collation table */ + +#if defined(NO_NLS) || defined(LOCALE_NLS) + for (z=0; z<256; z++) CollateTable[z]=z; + for (z='a'; z<='z'; z++) CollateTable[z]=toupper(z); +#endif + +#ifdef OS2_NLS + for (z=0; z<256; z++) CollateTable[z]=(char) z; + DosQueryCollate(sizeof(CollateTable),&ccode,CollateTable,&erglen); +#endif + +#ifdef DOS_NLS + for (z=0; z<256; z++) CollateTable[z]=(char) z; + for (z='a'; z<='z'; z++) CollateTable[z]=(char) (z-('a'-'A')); +#ifndef __DPMI16__ + if ((((Word)_osmajor)*100)+_osminor>=330) + BEGIN + Regs.x.ax=0x6506; + Regs.x.bx=NLSInfo.CodePage; + Regs.x.dx=NLSInfo.Country; + Regs.x.cx=sizeof(DOSTablePtr); + info=&DOSTablePtr; SRegs.es=FP_SEG(info); Regs.x.di=FP_OFF(info); + int86x(0x21,&Regs,&Regs,&SRegs); + if (Regs.x.cx==sizeof(DOSTablePtr)) + BEGIN + DOSTablePtr.Result+=sizeof(Word); + memcpy(CollateTable,DOSTablePtr.Result,256); + END + END +#endif +#endif + +#ifdef DEBUG_NLS + printf("Country = %d\n",NLSInfo.Country); + printf("CodePage = %d\n",NLSInfo.CodePage); + printf("DateFmt = "); + switch(NLSInfo.DateFmt) + BEGIN + case DateFormatMTY: printf("MTY\n"); break; + case DateFormatTMY: printf("TMY\n"); break; + case DateFormatYMT: printf("YMT\n"); break; + default: printf("???\n"); + END + printf("DateSep = %s\n",NLSInfo.DateSep); + printf("TimeFmt = "); + switch(NLSInfo.TimeFmt) + BEGIN + case TimeFormatUSA: printf("USA\n"); break; + case TimeFormatEurope: printf("Europe\n"); break; + case TimeFormatJapan: printf("Japan\n"); break; + default: printf("???\n"); + END + printf("TimeSep = %s\n",NLSInfo.TimeSep); + printf("Currency = %s\n",NLSInfo.Currency); + printf("CurrFmt = "); + switch (NLSInfo.CurrFmt) + BEGIN + case CurrFormatPreNoBlank: printf("PreNoBlank\n"); break; + case CurrFormatPostNoBlank: printf("PostNoBlank\n"); break; + case CurrFormatPreBlank: printf("PreBlank\n"); break; + case CurrFormatPostBlank: printf("PostBlank\n"); break; + default: printf("???\n"); + END + printf("CurrDecimals = %d\n",NLSInfo.CurrDecimals); + printf("ThouSep = %s\n",NLSInfo.ThouSep); + printf("DecSep = %s\n",NLSInfo.DecSep); + printf("DataSep = %s\n",NLSInfo.DataSep); + + printf("\nUpcaseTable:\n"); + for (z=0; z<4; z++) + BEGIN + for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(z*64+z2); putchar ('\n'); + for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(UpCaseTable[z*64+z2]); putchar ('\n'); + putchar('\n'); + END + + printf("\nLowcaseTable:\n"); + for (z=0; z<4; z++) + BEGIN + for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(z*64+z2); putchar ('\n'); + for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(LowCaseTable[z*64+z2]); putchar ('\n'); + putchar('\n'); + END + + printf("\nCollateTable:\n"); + for (z=0; z<4; z++) + BEGIN + for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(z*64+z2); putchar ('\n'); + for (z2=0; z2<63; z2++) if (z*64+z2>32) putchar(CollateTable[z*64+z2]); putchar ('\n'); + putchar('\n'); + END + + exit(0); +#endif +END + + void NLS_GetCountryInfo(NLS_CountryInfo *Info) +BEGIN + *Info=NLSInfo; +END + + void NLS_DateString(Word Year, Word Month, Word Day, char *Dest) +BEGIN + switch (NLSInfo.DateFmt) + BEGIN + case DateFormatMTY: + sprintf(Dest,"%d%s%d%s%d",Month,NLSInfo.DateSep,Day,NLSInfo.DateSep,Year); break; + case DateFormatTMY: + sprintf(Dest,"%d%s%d%s%d",Day,NLSInfo.DateSep,Month,NLSInfo.DateSep,Year); break; + case DateFormatYMT: + sprintf(Dest,"%d%s%d%s%d",Year,NLSInfo.DateSep,Month,NLSInfo.DateSep,Day); break; + END +END + + void NLS_CurrDateString(char *Dest) +BEGIN + time_t timep; + struct tm *trec; + + time(&timep); trec=localtime(&timep); + NLS_DateString(trec->tm_year+1900,trec->tm_mon+1,trec->tm_mday,Dest); +END + + void NLS_TimeString(Word Hour, Word Minute, Word Second, Word Sec100, char *Dest) +BEGIN + Word OriHour; + String ext; + + OriHour=Hour; + if (NLSInfo.TimeFmt==TimeFormatUSA) + BEGIN + Hour%=12; if (Hour==0) Hour=12; + END + sprintf(Dest,"%d%s%02d%s%02d",Hour,NLSInfo.TimeSep,Minute,NLSInfo.TimeSep,Second); + if (Sec100<100) + BEGIN + sprintf(ext,"%s%02d",NLSInfo.DecSep,Sec100); strcat(Dest,ext); + END + if (NLSInfo.TimeFmt==TimeFormatUSA) + strcat(Dest,(OriHour>12)?"p":"a"); +END + + void NLS_CurrTimeString(Boolean Use100, char *Dest) +BEGIN + time_t timep; + struct tm *trec; + + time(&timep); trec=localtime(&timep); + NLS_TimeString(trec->tm_hour,trec->tm_min,trec->tm_sec,Use100?0:100,Dest); +END + + void NLS_CurrencyString(double inp, char *erg) +BEGIN + char s[1024],form[1024]; + char *p,*z; + + /* Schritt 1: mit passender Nachkommastellenzahl wandeln */ + + sprintf(form,"%%0.%df",NLSInfo.CurrDecimals); + sprintf(s,form,inp); + + /* Schritt 2: vorne den Punkt suchen */ + + p=(NLSInfo.CurrDecimals==0) ? s+strlen(s) : strchr(s,'.'); + + /* Schritt 3: Tausenderstellen einfuegen */ + + z=p; + while (z-s>3) + BEGIN + strins(s,NLSInfo.ThouSep,z-s-3); z-=3; p+=strlen(NLSInfo.ThouSep); + END; + + /* Schritt 4: Komma anpassen */ + + strcpy(p,p+1); strins(s,NLSInfo.DecSep,p-s); + + /* Schritt 5: Einheit anbauen */ + + switch (NLSInfo.CurrFmt) + BEGIN + case CurrFormatPreNoBlank: + sprintf(erg,"%s%s",NLSInfo.Currency,s); break; + case CurrFormatPreBlank: + sprintf(erg,"%s %s",NLSInfo.Currency,s); break; + case CurrFormatPostNoBlank: + sprintf(erg,"%s%s",s,NLSInfo.Currency); break; + case CurrFormatPostBlank: + sprintf(erg,"%s%s",s,NLSInfo.Currency); break; + default: + strcpy(p,p+strlen(NLSInfo.DecSep)); strins(NLSInfo.Currency,s,p-s); + END +END + + char Upcase(char inp) +BEGIN + return UpCaseTable[((unsigned int) inp)&0xff]; +END + + void NLS_UpString(char *s) +BEGIN + char *z; + + for (z=s; *z!='\0'; z++) *z=UpCaseTable[((unsigned int)*z)&0xff]; +END + + void NLS_LowString(char *s) +BEGIN + char *z; + + for (z=s; *z!='\0'; z++) *z=LowCaseTable[((unsigned int)*z)&0xff]; +END + + int NLS_StrCmp(const char *s1, const char *s2) +BEGIN + while (CollateTable[((unsigned int)*s1)&0xff]==CollateTable[((unsigned int)*s2)&0xff]) + BEGIN + if ((NOT *s1) AND (NOT *s2)) return 0; + s1++; s2++; + END + return ((int) CollateTable[((unsigned int)*s1)&0xff]-CollateTable[((unsigned int)*s2)&0xff]); +END + + void nls_init(void) +BEGIN +#ifdef LOCALE_NLS + (void) setlocale(LC_TIME,""); + (void) setlocale(LC_MONETARY,""); +#endif +END -- cgit v1.2.3