home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Locale.c
- **
- ** Localization support routines
- **
- ** Copyright © 1990-1996 by Olaf `Olsen' Barthel
- ** All Rights Reserved
- **
- ** :ts=4
- */
-
- #ifndef _GLOBAL_H
- #include "Global.h"
- #endif
-
- /* LocaleOpen(STRPTR CatalogName,STRPTR BuiltIn):
- *
- * Open string translation tables.
- */
-
- VOID
- LocaleOpen(STRPTR CatalogName,STRPTR BuiltIn,LONG Version)
- {
- DecimalPoint = ".";
-
- strcpy(ConvNumber,"%ld");
- strcpy(ConvNumber10,"%10ld");
-
- if(LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38))
- {
- if(LocaleBase->lb_SysPatches)
- {
- strcpy(ConvNumber,"%lD");
- strcpy(ConvNumber10,"%10lD");
-
- if(Catalog = OpenCatalog(NULL,CatalogName,
- OC_BuiltInLanguage, BuiltIn,
- OC_BuiltInCodeSet, 0,
-
- Language[0] ? OC_Language : TAG_IGNORE,Language,
- TAG_DONE))
- {
- BOOL TooOld = FALSE;
-
- /* Don't load an outdated catalog file */
-
- if(Catalog->cat_Version < Version)
- TooOld = TRUE;
- else
- {
- if(strcmp(GetCatalogStr(Catalog,MSG_OFFSET_TEST1_TXT,""),"v4.0"))
- TooOld = TRUE;
- }
-
- if(TooOld)
- {
- BOOL IntuitionOpen;
-
- if(IntuitionBase)
- IntuitionOpen = TRUE;
- else
- {
- IntuitionOpen = FALSE;
-
- IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37);
- }
-
- if(IntuitionBase)
- ShowRequest(NULL,"The catalog file is too old to be used\nwith this `term' revision.","Continue");
-
- if(!IntuitionOpen)
- {
- CloseLibrary((struct Library *)IntuitionBase);
- IntuitionBase = NULL;
- }
-
- CloseCatalog(Catalog);
- Catalog = NULL;
- }
- }
-
- Locale = OpenLocale(NULL);
-
- DecimalPoint = Locale->loc_DecimalPoint;
- }
- else
- {
- CloseLibrary((struct Library *)LocaleBase);
- LocaleBase = NULL;
- }
- }
-
- /* If we couldn't open locale.library or if the patches are
- * not installed, and if we are running under Kickstart 2.04
- * we'll change the number formatting codes in the built-in
- * catalog strings.
- */
-
- if(!LocaleBase && SysBase->LibNode.lib_Version == 37)
- {
- struct CatCompArrayType *Entry;
- STRPTR String;
- UBYTE c;
- LONG i;
-
- for(i = 0, Entry = AppStrings ; i < NumAppStrings ; i++, Entry++)
- {
- String = Entry->cca_Str;
-
- while(c = *String++)
- {
- if(c == '%' && *String != '%')
- {
- STATIC BYTE Stops[256] =
- {
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,0,
- 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- };
-
- while(c = *String)
- {
- if(!Stops[c])
- String++;
- else
- {
- if(c == 'D')
- *String = 'd';
-
- break;
- }
- }
-
- if(!c)
- break;
- }
- }
- }
- }
- }
-
- /* LocaleClose():
- *
- * Close the translation tables.
- */
-
- VOID
- LocaleClose()
- {
- if(LocaleBase)
- {
- CloseLocale(Locale);
- Locale = NULL;
-
- CloseCatalog(Catalog);
- Catalog = NULL;
-
- CloseLibrary((struct Library *)LocaleBase);
- LocaleBase = NULL;
- }
- }
-
- /* LanguageCheck():
- *
- * Checks to see if the currently selected language
- * is english.
- */
-
- VOID
- LanguageCheck()
- {
- if(Locale && Catalog)
- {
- if(Locale->loc_LanguageName)
- {
- if(!Stricmp(Locale->loc_LanguageName,"english.language"))
- English = TRUE;
- else
- English = FALSE;
- }
- else
- English = FALSE;
- }
- else
- English = TRUE;
- }
-
- /* SmallCurrency():
- *
- * Support function for the rates control panel, returns a formatted
- * string to contain a string like "cents/unit".
- */
-
- VOID
- SmallCurrency(STRPTR Buffer,LONG BufferSize)
- {
- if(Locale)
- LimitedSPrintf(BufferSize,Buffer,LocaleString(MSG_RATEPANEL_PAY_PER_UNIT_GAD),Locale->loc_MonSmallCS);
- else
- LimitedSPrintf(BufferSize,Buffer,LocaleString(MSG_RATEPANEL_PAY_PER_UNIT_GAD),"Pay");
- }
-
- /* InsertGrouping(STRPTR Buffer,STRPTR GroupData,STRPTR GroupSeparator):
- *
- * Tricky stuff, folks! This beauty will insert grouping characters
- * into a readily-prepared string buffer filled with numeric
- * contents. It takes the group separator tokens and group separator
- * strings into account.
- */
-
- VOID
- InsertGrouping(STRPTR Buffer,STRPTR GroupData,STRPTR GroupSeparator)
- {
- UBYTE LocalBuffer[80]; /* Sufficient, but too large */
- STRPTR Index;
- LONG i,j,SeparatorSize;
- LONG Count; /* How many characters per group */
- BOOL RepeatGroupCount; /* Keep repeating group size until end */
-
- RepeatGroupCount = FALSE;
-
- /* Set up for the first group */
-
- switch(*GroupData)
- {
- case 0: /* Repeat current grouping scheme until end */
- case 255: /* No further grouping is to be performed */
-
- Count = 0;
-
- break;
-
- default: /* Initial group size */
-
- Count = *GroupData++;
-
- break;
- }
-
- /* Check the size of the group separator string */
-
- if((SeparatorSize = strlen(GroupSeparator) - 1) < 1)
- Count = 0;
-
- /* That where we'll start */
-
- Index = LocalBuffer;
-
- /* Build the string back to front, we will reverse it later */
-
- for(i = strlen(Buffer) - 1, j = 1 ; i >= 0 ; i--, j++)
- {
- /* Pick up the next number character */
-
- *Index++ = Buffer[i];
-
- /* Are we to insert the grouping characters here? */
-
- if(Count && j == Count)
- {
- LONG k;
-
- /* Insert the grouping characters */
-
- for(k = SeparatorSize ; k >= 0 ; k--)
- *Index++ = GroupSeparator[k];
-
- /* Reset the group size counter */
-
- j = 0;
-
- /* Pick up the next grouping token? */
-
- if(!RepeatGroupCount)
- {
- /* Ok, what kind of token is it? */
-
- switch(*GroupData)
- {
- case 0: /* Repeat current grouping scheme */
-
- RepeatGroupCount = TRUE;
- break;
-
- case 255: /* Perform no further grouping */
-
- Count = 0;
- break;
-
- default: /* New group size */
-
- Count = *GroupData++;
- break;
- }
- }
- }
- }
-
- /* Look how long the resulting string is */
-
- j = ((LONG)Index - (LONG)LocalBuffer) - 1;
-
- /* Copy it back */
-
- Index = Buffer;
-
- /* Reverse the order of characters while copying */
-
- for(i = j ; i >= 0 ; i--)
- *Index++ = LocalBuffer[i];
-
- /* Provide null-termination */
-
- *Index = 0;
- }
-
- STATIC VOID
- ConvertMonetaryQuantity(LONG Units,STRPTR Destination,LONG DestinationSize,BOOL UseCurrency)
- {
- UBYTE IntegerBuffer[80]; /* Sufficient, but too large */
-
- STRPTR SignText, /* Signed/unsigned quantity text */
- SpaceText, /* Currency/number separation */
- Currency; /* The name of the currency */
- LONG SpaceSep, /* A space separates currency and quantity? */
- SignPos, /* Where to place the sign text */
- CSPos; /* Where to place the currency text */
- LONG Sign; /* Negative or positive quantity? */
-
- /* Negative quantity? */
-
- if(Units < 0)
- {
- Sign = -1;
-
- Units = -Units;
- }
- else
- Sign = 1;
-
- /* Does this currency sport a fractional smaller currency? */
-
- if(Locale->loc_MonFracDigits)
- {
- UBYTE NumberBuffer[10],
- FractionBuffer[40];
- LONG Integer,
- Fraction,
- Scale;
- LONG i;
-
- /* Prepare the formatting string */
-
- LimitedSPrintf(sizeof(NumberBuffer),NumberBuffer,"%%0%ldld",Locale->loc_MonFracDigits);
-
- /* Turn the number of fractional digits into a power of ten */
-
- for(i = 0, Scale = 1 ; i < Locale->loc_MonFracDigits ; i++)
- Scale *= 10;
-
- /* Split the quantity in integer and fractional part */
-
- Integer = Units / Scale;
- Fraction = Units % Scale;
-
- /* Build the integer text */
-
- LimitedSPrintf(sizeof(IntegerBuffer),IntegerBuffer,"%ld",Integer);
-
- InsertGrouping(IntegerBuffer,Locale->loc_MonGrouping,Locale->loc_MonGroupSeparator);
-
- /* Build the fractional text */
-
- LimitedSPrintf(sizeof(FractionBuffer),FractionBuffer,NumberBuffer,Fraction);
-
- InsertGrouping(FractionBuffer,Locale->loc_MonFracGrouping,Locale->loc_MonFracGroupSeparator);
-
- /* Add the monetary decimal point */
-
- LimitedStrcat(sizeof(IntegerBuffer),IntegerBuffer,Locale->loc_MonDecimalPoint);
-
- /* Add the fractional part */
-
- LimitedStrcat(sizeof(IntegerBuffer),IntegerBuffer,FractionBuffer);
- }
- else
- {
- /* Build the integer text */
-
- LimitedSPrintf(sizeof(IntegerBuffer),IntegerBuffer,"%ld",Units);
-
- InsertGrouping(IntegerBuffer,Locale->loc_MonGrouping,Locale->loc_MonGroupSeparator);
- }
-
- /* Pick up the appropriate formatting parameters */
-
- if(Sign < 0)
- {
- SignText = Locale->loc_MonNegativeSign;
- SpaceSep = Locale->loc_MonNegativeSpaceSep;
- SignPos = Locale->loc_MonNegativeSignPos;
- CSPos = Locale->loc_MonNegativeCSPos;
- }
- else
- {
- SignText = Locale->loc_MonPositiveSign;
- SpaceSep = Locale->loc_MonPositiveSpaceSep;
- SignPos = Locale->loc_MonPositiveSignPos;
- CSPos = Locale->loc_MonPositiveCSPos;
- }
-
- /* Are we to use the currency symbol? */
-
- if(UseCurrency)
- {
- /* Pick up the currency text */
-
- Currency = Locale->loc_MonCS;
-
- /* Take care of the separation information */
-
- if(SpaceSep == SS_NOSPACE)
- SpaceText = "";
- else
- SpaceText = " ";
- }
- else
- Currency = SpaceText = "";
-
- /* Now merge all the information into one single string */
-
- if(CSPos == CSP_PRECEDES)
- {
- switch(SignPos)
- {
- case SP_PARENS:
-
- /* (Currency <Space> Sign Value) */
- LimitedSPrintf(DestinationSize,Destination,"(%s%s%s%s)",Currency,SpaceText,SignText,IntegerBuffer);
- break;
-
- case SP_PREC_ALL:
-
- /* Sign Currency <Space> Value */
- LimitedSPrintf(DestinationSize,Destination,"%s%s%s%s",SignText,Currency,SpaceText,IntegerBuffer);
- break;
-
- case SP_SUCC_ALL:
-
- /* Currency <Space> Value Sign */
- LimitedSPrintf(DestinationSize,Destination,"%s%s%s%s",Currency,SpaceText,IntegerBuffer,SignText);
- break;
-
- case SP_PREC_CURR:
-
- /* Sign Currency <Space> Value */
- LimitedSPrintf(DestinationSize,Destination,"%s%s%s%s",SignText,Currency,SpaceText,IntegerBuffer);
- break;
-
- case SP_SUCC_CURR:
-
- /* Currency Sign <Space> Value */
- LimitedSPrintf(DestinationSize,Destination,"%s%s%s%s",Currency,SignText,SpaceText,IntegerBuffer);
- break;
- }
- }
- else
- {
- switch(SignPos)
- {
- case SP_PARENS:
-
- /* (Sign Value <Space> Currency) */
- LimitedSPrintf(DestinationSize,Destination,"(%s%s%s%s)",SignText,IntegerBuffer,SpaceText,Currency);
- break;
-
- case SP_PREC_ALL:
-
- /* Sign Value <Space> Currency */
- LimitedSPrintf(DestinationSize,Destination,"%s%s%s%s",SignText,IntegerBuffer,SpaceText,Currency);
- break;
-
- case SP_SUCC_ALL:
-
- /* Value <Space> Currency Sign */
- LimitedSPrintf(DestinationSize,Destination,"%s%s%s%s",IntegerBuffer,SpaceText,Currency,SignText);
- break;
-
- case SP_PREC_CURR:
-
- /* Value <Space> Sign Currency */
- LimitedSPrintf(DestinationSize,Destination,"%s%s%s%s",IntegerBuffer,SpaceText,SignText,Currency);
- break;
-
- case SP_SUCC_CURR:
-
- /* Value <Space> Currency Sign */
- LimitedSPrintf(DestinationSize,Destination,"%s%s%s%s",IntegerBuffer,SpaceText,Currency,SignText);
- break;
- }
- }
- }
-
- /* CreateSum(LONG Quantity):
- *
- * Create a string containing a monetary quantity formatted
- * according to the current locale rules.
- */
-
- VOID
- CreateSum(LONG Quantity,BOOL UseCurrency,STRPTR Buffer,LONG BufferSize)
- {
- if(Locale)
- ConvertMonetaryQuantity(Quantity,Buffer,BufferSize,UseCurrency);
- else
- LimitedSPrintf(BufferSize,Buffer,"%ld.%02ld",Quantity / 100,Quantity % 100);
- }
-
- /* LocalizeString(STRPTR *Strings,LONG From,LONG To):
- *
- * Localize an array of strings.
- */
-
- VOID
- LocalizeString(STRPTR *Strings,LONG From,LONG To)
- {
- if(!Strings[0])
- {
- LONG i,j;
-
- for(i = From, j = 0 ; i <= To ; i++, j++)
- Strings[j] = LocaleString(i);
- }
- }
-
- /* LocalizeStringTable(STRPTR *Strings,LONG *Table)
- *
- * Localize an array of strings by table.
- */
-
- VOID
- LocalizeStringTable(STRPTR *Strings,LONG *Table)
- {
- while(*Table != -1)
- *Strings++ = LocaleString(*Table++);
-
- *Strings = NULL;
- }
-
- /* LocaleString(ULONG ID):
- *
- * Obtain a string from the translation pool.
- */
-
- STRPTR
- LocaleString(ULONG ID)
- {
- STRPTR Builtin;
-
- if(ID < NumAppStrings && AppStrings[ID].cca_ID == ID)
- Builtin = AppStrings[ID].cca_Str;
- else
- {
- LONG Left,Mid,Right;
-
- /* Binary search, note: can be applied here */
- /* only because the catalog entries are */
- /* stored in ascending ID order. But actually, */
- /* this piece of code should never get called. */
-
- Left = 0;
- Right = NumAppStrings - 1;
-
- do
- {
- Mid = (Left + Right) / 2;
-
- if(ID < AppStrings[Mid].cca_ID)
- Right = Mid - 1;
- else
- Left = Mid + 1;
- }
- while(ID != AppStrings[Mid].cca_ID && Left <= Right);
-
- if(ID == AppStrings[Mid].cca_ID)
- Builtin = AppStrings[Mid].cca_Str;
- else
- Builtin = "";
- }
-
- if(Catalog)
- {
- STRPTR String = GetCatalogStr(Catalog,ID,Builtin);
-
- if(String[0])
- return(String);
- }
-
- return(Builtin);
- }
-
- STRPTR SAVE_DS ASM
- LocaleHookFunc(REG(a0) struct Hook *UnusedHook,REG(a2) APTR Unused,REG(a1) LONG ID)
- {
- return(LocaleString(ID));
- }
-
- STATIC LONG SAVE_DS ASM
- FormatDateHookFunc(REG(a0) struct Hook *Hook,REG(a2) APTR Unused,REG(a1) UBYTE Char)
- {
- struct FormatContext *Context = Hook->h_Data;
-
- if(Context->Size > 0)
- {
- *Context->Index++ = Char;
-
- if(--Context->Size == 1)
- {
- *Context->Index = 0;
- Context->Size = 0;
- }
- }
-
- return(TRUE);
- }
-
- /* FormatStamp():
- *
- * Convert a date stamp into human readable
- * form by taking the current locale parameters
- * into account.
- */
-
- BOOL
- FormatStamp(struct DateStamp *Stamp,STRPTR BothBuffer,LONG BothBufferSize,BOOL SubstituteDay)
- {
- struct DateStamp Now;
-
- /* If no time stamp given, do with current time */
-
- if(!Stamp)
- CurrentTimeToStamp(Stamp = &Now);
-
- /* Is the current locale available? */
-
- if(Locale)
- {
- struct FormatContext Context;
- struct Hook LocalHook;
-
- InitHook(&LocalHook,(HOOKFUNC)FormatDateHookFunc,&Context);
-
- /* Combine date and time text? */
-
- if(!SubstituteDay)
- {
- Context.Index = BothBuffer;
- Context.Size = BothBufferSize;
-
- FormatDate(Locale,Locale->loc_DateTimeFormat,Stamp,&LocalHook);
-
- StripSpaces(BothBuffer);
- }
- else
- {
- UBYTE DateBuffer[40],TimeBuffer[40];
-
- /* Are we to substitute the current day with */
- /* text such as today, yesterday, etc.? */
-
- if(SubstituteDay)
- {
- struct DateStamp Today;
- STRPTR String;
-
- /* Get the current time */
-
- CurrentTimeToStamp(&Today);
-
- /* Does the date refer to yesterday? */
-
- if(Stamp->ds_Days == Today.ds_Days - 1)
- String = GetLocaleStr(Locale,YESTERDAYSTR);
- else
- {
- /* Does the date refer to today? */
-
- if(Stamp->ds_Days == Today.ds_Days)
- String = GetLocaleStr(Locale,TODAYSTR);
- else
- {
- /* Does the date refer to tomorrow? */
-
- if(Stamp->ds_Days == Today.ds_Days + 1)
- String = GetLocaleStr(Locale,TOMORROWSTR);
- else
- {
- String = NULL;
- SubstituteDay = FALSE;
- }
- }
- }
-
- if(String)
- LimitedStrcpy(sizeof(DateBuffer),DateBuffer,String);
- else
- DateBuffer[0] = 0;
- }
-
- if(!SubstituteDay)
- {
- Context.Index = DateBuffer;
- Context.Size = sizeof(DateBuffer);
-
- FormatDate(Locale,Locale->loc_DateFormat,Stamp,&LocalHook);
- }
-
- StripSpaces(DateBuffer);
-
- Context.Index = TimeBuffer;
- Context.Size = sizeof(TimeBuffer);
-
- FormatDate(Locale,Locale->loc_TimeFormat,Stamp,&LocalHook);
-
- StripSpaces(TimeBuffer);
-
- /* Combine date and time */
-
- LimitedSPrintf(BothBufferSize,BothBuffer,"%s %s",DateBuffer,TimeBuffer);
- }
- }
- else
- {
- UBYTE DateBuffer[40],TimeBuffer[40];
- struct DateTime DateTime;
-
- /* No locale, so we will use dos.library instead. */
-
- CopyMem(Stamp,&DateTime.dat_Stamp,sizeof(struct DateStamp));
-
- DateTime.dat_Format = FORMAT_DOS;
- DateTime.dat_Flags = SubstituteDay ? DTF_SUBST : NULL;
- DateTime.dat_StrDay = NULL;
- DateTime.dat_StrDate = DateBuffer;
- DateTime.dat_StrTime = TimeBuffer;
-
- if(!DateToStr(&DateTime))
- return(FALSE);
-
- StripSpaces(DateBuffer);
- StripSpaces(TimeBuffer);
-
- /* Combine date and time */
-
- LimitedSPrintf(BothBufferSize,BothBuffer,"%s %s",DateBuffer,TimeBuffer);
- }
-
- return(TRUE);
- }
-
- /* FormatTime(STRPTR Buffer,LONG Hours,LONG Minutes,LONG Seconds):
- *
- * Given hours, minutes and seconds, format this data into
- * a human-readable string.
- */
-
- VOID
- FormatTime(STRPTR Buffer,LONG BufferSize,LONG Hours,LONG Minutes,LONG Seconds)
- {
- if(Locale)
- {
- struct Hook LocalHook;
- struct FormatContext Context;
- struct DateStamp Stamp;
-
- Stamp.ds_Days = 0;
- Stamp.ds_Minute = Hours * 60 + Minutes;
- Stamp.ds_Tick = MAX(0,Seconds) * TICKS_PER_SECOND;
-
- Context.Index = Buffer;
- Context.Size = BufferSize;
-
- InitHook(&LocalHook,(HOOKFUNC)FormatDateHookFunc,&Context);
-
- if(Seconds < 0)
- FormatDate(Locale,Locale->loc_ShortTimeFormat,&Stamp,&LocalHook);
- else
- FormatDate(Locale,Locale->loc_TimeFormat,&Stamp,&LocalHook);
- }
- else
- {
- if(Seconds < 0)
- LimitedSPrintf(BufferSize,Buffer,"%02ld:%02ld",Hours,Minutes);
- else
- LimitedSPrintf(BufferSize,Buffer,"%02ld:%02ld:%02ld",Hours,Minutes,Seconds);
- }
- }
-
- /* StandardShowTime(struct Gadget *SomeGadget,LONG Level):
- *
- * Callback routine to display some time level.
- */
-
- STRPTR SAVE_DS STACKARGS
- StandardShowTime(struct Gadget *UnusedGadget,LONG Seconds)
- {
- STATIC UBYTE Time[10];
- STRPTR FormatString;
-
- if(LocaleBase)
- FormatString = "%2lD%s%02lD";
- else
- FormatString = "%2ld%s%02ld";
-
- LimitedSPrintf(sizeof(Time),Time,FormatString,Seconds / 100,DecimalPoint,Seconds % 100);
-
- return(Time);
- }
-