/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /* locale.h * FE support for xp_locale stuff */ #include "xplocale.h" #include "macutil.h" #include #include "uprefd.h" #include "xpassert.h" #include "csid.h" #include "structs.h" #include "intl_csi.h" long WinCharsetIDToScript(UInt16 wincsid); Intl1Hndl GetItl1Resource(long scriptcode); Intl0Hndl GetItl0Resource(long scriptcode); void AbbrevWeekdayString(DateTimeRec &dateTime, Str255 weekdayString, Intl1Hndl Itl1RecordHandle ); /* FE_StrColl * -1, 0, 1 return guaranteed */ int FE_StrColl(const char* s1, const char* s2) { long scriptcode; // get system script code scriptcode = ::GetScriptManagerVariable(smSysScript); // get itlb of the system script ItlbRecord **ItlbRecordHandle; ItlbRecordHandle = (ItlbRecord **)::GetResource('itlb', scriptcode); // get itl2 number of current system script from itlb if possible // otherwise, try script manager (Script manager won't update // itl2 number when the change on the fly ) long itl2num; if(ItlbRecordHandle != NULL) { if(*ItlbRecordHandle == NULL) ::LoadResource((Handle)ItlbRecordHandle); if(*ItlbRecordHandle != NULL) itl2num = (*ItlbRecordHandle)->itlbSort; else itl2num = ::GetScriptVariable(scriptcode, smScriptSort); } else { /* Use this as fallback */ itl2num = ::GetScriptVariable(scriptcode, smScriptSort); } // get itl2 resource Handle itl2Handle; itl2Handle = ::GetResource('itl2', itl2num); // call CompareText with itl2Handle // We don't need to check itl2Handle here. CompareText will use // default system sorting if itl2Handle is null return( (int) CompareText(s1, s2, strlen(s1), strlen(s2), itl2Handle)); } long WinCharsetIDToScript(UInt16 wincsid) { CCharSet font; if(CPrefs::GetFont((wincsid & ~ CS_AUTO), &font )) return font.fFallbackFontScriptID; else return smRoman; } Intl1Hndl GetItl1Resource(long scriptcode) { // get itlb from currenty system script ItlbRecord **ItlbRecordHandle; ItlbRecordHandle = (ItlbRecord **)::GetResource('itlb', scriptcode); // get itl1 number from itlb resource, if possible // otherwise, use the one return from script manager, // (Script manager won't update itl1 number when the change on the fly ) long itl1num; if(ItlbRecordHandle != NULL) { if(*ItlbRecordHandle == NULL) ::LoadResource((Handle)ItlbRecordHandle); if(*ItlbRecordHandle != NULL) itl1num = (*ItlbRecordHandle)->itlbDate; else itl1num = ::GetScriptVariable(scriptcode, smScriptDate); } else { // Use this as fallback itl1num = ::GetScriptVariable(scriptcode, smScriptDate); } // get itl1 resource Intl1Hndl Itl1RecordHandle; Itl1RecordHandle = (Intl1Hndl)::GetResource('itl1', itl1num); return Itl1RecordHandle; } Intl0Hndl GetItl0Resource(long scriptcode) { // get itlb from currenty system script ItlbRecord **ItlbRecordHandle; ItlbRecordHandle = (ItlbRecord **)::GetResource('itlb', scriptcode); // get itl0 number from itlb resource, if possible // otherwise, use the one return from script manager, // (Script manager won't update itl1 number when the change on the fly ) long itl0num; if(ItlbRecordHandle != NULL) { if(*ItlbRecordHandle == NULL) ::LoadResource((Handle)ItlbRecordHandle); if(*ItlbRecordHandle != NULL) itl0num = (*ItlbRecordHandle)->itlbNumber; else itl0num = ::GetScriptVariable(scriptcode, smScriptNumber); } else { // Use this as fallback itl0num = ::GetScriptVariable(scriptcode, smScriptNumber); } // get itl1 resource Intl0Hndl Itl0RecordHandle; Itl0RecordHandle = (Intl0Hndl)::GetResource('itl0', itl0num); return Itl0RecordHandle; } void AbbrevWeekdayString(DateTimeRec &dateTime, Str255 weekdayString, Intl1Hndl Itl1RecordHandle ) { Boolean gotit = false; // If we can get itl1Resource, exam it. if(Itl1RecordHandle != NULL ) { if(*Itl1RecordHandle == NULL) ::LoadResource((Handle)Itl1RecordHandle); if(*Itl1RecordHandle == NULL) { weekdayString[0] = 0; return; } // if itl1 resource is in the itl1ExtRec format // look at the additional table // See IM-Text Appendix B for details if((unsigned short)((*Itl1RecordHandle)->localRtn[0]) == 0xA89F) { // use itl1ExtRect Itl1ExtRec **Itl1ExtRecHandle; Itl1ExtRecHandle = (Itl1ExtRec **) Itl1RecordHandle; // check abbrevDaysTableLength and abbrevDaysTableOffset if(((*Itl1ExtRecHandle)->abbrevDaysTableLength != 0) && ((*Itl1ExtRecHandle)->abbrevDaysTableOffset != 0)) { // use the additional table for abbreviation weekday name // Japanese use it. // Start Pointer access to Handle, no HLock since we don't // call any API here. // Be careful when you debug- don't move memory :) Ptr abTablePt; short itemlen; // Ok, change it back to range [0-6] short weekday = dateTime.dayOfWeek - 1; abTablePt = (Ptr)(*Itl1ExtRecHandle); abTablePt += (*Itl1ExtRecHandle)->abbrevDaysTableOffset; // first 2 byte in the table should be the count. itemlen = (short) *((short*)abTablePt); abTablePt += 2; if(weekday < itemlen) { unsigned char len; short i; // iterate till we hit the weekday name we want for(i = 0 ; i < weekday ; i++) { len = *abTablePt; // shift to the next one. don't forget the len byte itself. abTablePt += len + 1; } // Ok, we got it, let's copy it. len = *abTablePt; ::BlockMoveData(abTablePt,&weekdayString[0] ,len+1); gotit = true; } } } // didn't get it. Either it is not in itl1ExtRect format or it don't have // additional abbreviation table. // use itl1Rect instead. if(! gotit) { // get abbreviation length // not the length is not always 3. Some country use longer (say 4) // abbreviation. short abbrLen = (*Itl1RecordHandle)->abbrLen; // Fix Traditional Chinese problem if(((((*Itl1RecordHandle)->intl1Vers) >> 8) == verTaiwan ) && (abbrLen == 4) && ((*Itl1RecordHandle)->days[0][0] == 6) && ((*Itl1RecordHandle)->days[1][0] == 6) && ((*Itl1RecordHandle)->days[2][0] == 6) && ((*Itl1RecordHandle)->days[3][0] == 6) && ((*Itl1RecordHandle)->days[4][0] == 6) && ((*Itl1RecordHandle)->days[5][0] == 6) && ((*Itl1RecordHandle)->days[6][0] == 6)) { abbrLen = 6; } weekdayString[0] = abbrLen; // copy the weekday name with that abbreviation length ::BlockMoveData(&((*Itl1RecordHandle)->days[dateTime.dayOfWeek-1][1]), &weekdayString[1] , abbrLen); gotit = true; } } else { // cannot get itl1 resource, return with null string. weekdayString[0] = 0; } } size_t FE_StrfTime(MWContext* context, char *result, size_t maxsize, int format, const struct tm *timeptr) { Str255 timeString; int32 dateTime; DateTimeRec macDateTime; // convert struct tm to input format of mac toolbox call XP_ASSERT(timeptr->tm_year >= 0); XP_ASSERT(timeptr->tm_mon >= 0); XP_ASSERT(timeptr->tm_mday >= 0); XP_ASSERT(timeptr->tm_hour >= 0); XP_ASSERT(timeptr->tm_min >= 0); XP_ASSERT(timeptr->tm_sec >= 0); XP_ASSERT(timeptr->tm_wday >= 0); // Mac need a number from 1904 to 2040 // tm only provide the last two digit of the year */ macDateTime.year = timeptr->tm_year + 1900; // Mac use 1 for Jan and 12 for Dec // tm use 0 for Jan and 11 for Dec macDateTime.month = timeptr->tm_mon + 1; macDateTime.day = timeptr->tm_mday; macDateTime.hour = timeptr->tm_hour; macDateTime.minute = timeptr->tm_min; macDateTime.second = timeptr->tm_sec; // Mac use 1 for sunday 7 for saturday // tm use 0 for sunday 6 for saturday macDateTime.dayOfWeek = timeptr->tm_wday +1 ; ::DateToSeconds( &macDateTime, (unsigned long *) &dateTime); INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context); long scriptcode = WinCharsetIDToScript(INTL_GetCSIWinCSID(c)); Handle itl1Handle = (Handle) GetItl1Resource(scriptcode); Handle itl0Handle = (Handle) GetItl0Resource(scriptcode); // get time string if(format == XP_LONG_DATE_TIME_FORMAT) ::TimeString(dateTime, TRUE, timeString, itl0Handle); else ::TimeString(dateTime, FALSE, timeString, itl0Handle); switch(format) { case XP_TIME_FORMAT: { if (timeString[0] >= maxsize) { result[0] = '\0'; return(0); } // just copy the time string if(timeString[0] > 0) ::BlockMoveData(&timeString[1], result , timeString[0]); result[ timeString[0]] = '\0'; return ( timeString[0] ); } case XP_LONG_DATE_TIME_FORMAT: case XP_WEEKDAY_TIME_FORMAT: case XP_DATE_TIME_FORMAT: { Str255 dateString; switch(format) { case XP_LONG_DATE_TIME_FORMAT: ::DateString(dateTime, abbrevDate, dateString, itl1Handle); break; case XP_DATE_TIME_FORMAT: ::DateString(dateTime, shortDate, dateString, itl0Handle); break; case XP_WEEKDAY_TIME_FORMAT: AbbrevWeekdayString(macDateTime, dateString, (Intl1Hndl)itl1Handle); // try fallback if it return with null string. if(dateString[0] == 0) { // cannot get weekdayString from itl1 , try fallback dateString[0] = strftime((char*)&dateString[1],254,"%a",timeptr); } break; } // Append the date string and time string tother. seperate with " " if((dateString[0]+timeString[0] + 1) >= maxsize) { // try put dateString only if(dateString[0] >= maxsize) { result[0] = '\0'; return(0); } else { // we don't have space for Date and Time . So , just put date there if(dateString[0] > 0) ::BlockMoveData(&dateString[1], result , dateString[0]); result[ dateString[0]] = '\0'; return ( dateString[0] ); } } else { int dlen; // we need to rescan the datestring because a bug in Cyrillic itl1 for(dlen=0;(dlen < dateString[0]) && (dateString[dlen+1] != '\0'); dlen++) ; // just incase dateString got a null string if(dlen > 0) ::BlockMoveData(&dateString[1], result , dlen); result[ dlen] = ' '; // just incase timeString got a null string if(timeString[0] > 0) ::BlockMoveData(&timeString[1], &result[dlen+1] , timeString[0]); result[ dlen+timeString[0] + 1] = '\0'; return ( dlen+timeString[0] + 1); } } break; default: result[0] = '\0'; return(0); break; } }