mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-13 18:27:35 +00:00
369 lines
11 KiB
C++
369 lines
11 KiB
C++
/* -*- 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 <IntlResources.h>
|
|
#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;
|
|
}
|
|
}
|
|
|