home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / utility / locale.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  11.2 KB  |  369 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /* locale.h
  20.  * FE support for xp_locale stuff
  21.  */
  22.  
  23.  
  24. #include "xplocale.h"
  25. #include "macutil.h"
  26. #include <IntlResources.h>
  27. #include "uprefd.h"
  28. #include "xpassert.h"
  29. #include "csid.h"
  30. #include "structs.h"
  31. #include "intl_csi.h"
  32.  
  33. long WinCharsetIDToScript(UInt16 wincsid);
  34. Intl1Hndl GetItl1Resource(long scriptcode);
  35. Intl0Hndl GetItl0Resource(long scriptcode);
  36. void AbbrevWeekdayString(DateTimeRec &dateTime, Str255 weekdayString, Intl1Hndl Itl1RecordHandle );
  37.  
  38. /* FE_StrColl
  39.  *   -1, 0, 1 return guaranteed
  40.  */
  41.  
  42. int FE_StrColl(const char* s1, const char* s2) 
  43.  
  44.  
  45.  {
  46.     long scriptcode;
  47.     // get system script code
  48.     scriptcode = ::GetScriptManagerVariable(smSysScript);
  49.     
  50.     // get itlb of the system script
  51.     ItlbRecord **ItlbRecordHandle;
  52.     ItlbRecordHandle = (ItlbRecord **)::GetResource('itlb', scriptcode);
  53.     
  54.     // get itl2 number of current system script from itlb if possible
  55.     // otherwise, try script manager (Script manager won't update 
  56.     // itl2 number when the change on the fly )
  57.     long itl2num;
  58.     if(ItlbRecordHandle != NULL)
  59.     {
  60.         if(*ItlbRecordHandle == NULL)
  61.             ::LoadResource((Handle)ItlbRecordHandle);
  62.             
  63.         if(*ItlbRecordHandle != NULL)
  64.             itl2num = (*ItlbRecordHandle)->itlbSort;
  65.         else
  66.             itl2num = ::GetScriptVariable(scriptcode, smScriptSort);
  67.     } else {    /* Use this as fallback */
  68.         itl2num = ::GetScriptVariable(scriptcode, smScriptSort);
  69.     }
  70.     // get itl2 resource
  71.     Handle itl2Handle;
  72.     itl2Handle = ::GetResource('itl2', itl2num);
  73.     
  74.     // call CompareText with itl2Handle
  75.     // We don't need to check itl2Handle here. CompareText will use 
  76.     // default system sorting if itl2Handle is null
  77.     return( (int) CompareText(s1,  s2, 
  78.         strlen(s1), strlen(s2), itl2Handle));
  79. }
  80.  
  81. long WinCharsetIDToScript(UInt16 wincsid)
  82. {
  83.     CCharSet font;
  84.     if(CPrefs::GetFont((wincsid & ~ CS_AUTO), &font ))
  85.         return font.fFallbackFontScriptID;
  86.     else
  87.         return smRoman;
  88. }
  89.  
  90. Intl1Hndl GetItl1Resource(long scriptcode)
  91. {
  92.     // get itlb from currenty system script
  93.     ItlbRecord **ItlbRecordHandle;
  94.     ItlbRecordHandle = (ItlbRecord **)::GetResource('itlb', scriptcode);
  95.     
  96.     // get itl1 number from itlb resource, if possible
  97.     // otherwise, use the one return from script manager, 
  98.     // (Script manager won't update itl1 number when the change on the fly )
  99.     long itl1num;
  100.     if(ItlbRecordHandle != NULL)
  101.     {
  102.         if(*ItlbRecordHandle == NULL)
  103.             ::LoadResource((Handle)ItlbRecordHandle);
  104.             
  105.         if(*ItlbRecordHandle != NULL)
  106.             itl1num = (*ItlbRecordHandle)->itlbDate;
  107.         else
  108.             itl1num = ::GetScriptVariable(scriptcode, smScriptDate);
  109.     } else {    // Use this as fallback
  110.         itl1num = ::GetScriptVariable(scriptcode, smScriptDate);
  111.     }
  112.     
  113.     // get itl1 resource 
  114.     Intl1Hndl Itl1RecordHandle;
  115.     Itl1RecordHandle = (Intl1Hndl)::GetResource('itl1', itl1num);
  116.     return Itl1RecordHandle;
  117. }
  118.  
  119. Intl0Hndl GetItl0Resource(long scriptcode)
  120. {
  121.     // get itlb from currenty system script
  122.     ItlbRecord **ItlbRecordHandle;
  123.     ItlbRecordHandle = (ItlbRecord **)::GetResource('itlb', scriptcode);
  124.     
  125.     // get itl0 number from itlb resource, if possible
  126.     // otherwise, use the one return from script manager, 
  127.     // (Script manager won't update itl1 number when the change on the fly )
  128.     long itl0num;
  129.     if(ItlbRecordHandle != NULL)
  130.     {
  131.         if(*ItlbRecordHandle == NULL)
  132.             ::LoadResource((Handle)ItlbRecordHandle);
  133.             
  134.         if(*ItlbRecordHandle != NULL)
  135.             itl0num = (*ItlbRecordHandle)->itlbNumber;
  136.         else
  137.             itl0num = ::GetScriptVariable(scriptcode, smScriptNumber);
  138.     } else {    // Use this as fallback
  139.         itl0num = ::GetScriptVariable(scriptcode, smScriptNumber);
  140.     }
  141.     
  142.     // get itl1 resource 
  143.     Intl0Hndl Itl0RecordHandle;
  144.     Itl0RecordHandle = (Intl0Hndl)::GetResource('itl0', itl0num);
  145.     return Itl0RecordHandle;
  146. }
  147.  
  148.  
  149. void AbbrevWeekdayString(DateTimeRec &dateTime, Str255 weekdayString, Intl1Hndl Itl1RecordHandle )
  150. {
  151.     Boolean gotit = false;
  152.     
  153.     // If we can get itl1Resource, exam it.
  154.     if(Itl1RecordHandle != NULL )
  155.     {
  156.         if(*Itl1RecordHandle == NULL)
  157.             ::LoadResource((Handle)Itl1RecordHandle);
  158.  
  159.         if(*Itl1RecordHandle == NULL)
  160.         {
  161.             weekdayString[0] = 0;
  162.             return;
  163.         }
  164.         // if itl1 resource is in the itl1ExtRec format 
  165.         // look at the additional table
  166.         // See IM-Text Appendix B for details
  167.         if((unsigned short)((*Itl1RecordHandle)->localRtn[0]) == 0xA89F)
  168.         {    // use itl1ExtRect
  169.             Itl1ExtRec **Itl1ExtRecHandle;
  170.             Itl1ExtRecHandle = (Itl1ExtRec **) Itl1RecordHandle;
  171.             
  172.             // check abbrevDaysTableLength and abbrevDaysTableOffset
  173.             if(((*Itl1ExtRecHandle)->abbrevDaysTableLength != 0) &&
  174.                ((*Itl1ExtRecHandle)->abbrevDaysTableOffset != 0))
  175.             {    
  176.                 // use the additional table for abbreviation weekday name
  177.                 // Japanese use it.
  178.                 // Start Pointer access to Handle, no HLock since we don't
  179.                 // call any API here.
  180.                 // Be careful when you debug- don't move memory :)
  181.                 Ptr abTablePt;
  182.                 short itemlen;
  183.                 
  184.                 // Ok, change it back to range [0-6]
  185.                 short weekday = dateTime.dayOfWeek - 1;    
  186.                 
  187.                 abTablePt = (Ptr)(*Itl1ExtRecHandle);
  188.                 abTablePt +=  (*Itl1ExtRecHandle)->abbrevDaysTableOffset;
  189.                 
  190.                 // first 2 byte in the table should be the count.
  191.                 itemlen = (short) *((short*)abTablePt);    
  192.                 abTablePt += 2;    
  193.                 
  194.                 if(weekday < itemlen)
  195.                 {
  196.                     unsigned char len;
  197.                     short i;
  198.                     // iterate till we hit the weekday name we want
  199.                     for(i = 0 ; i < weekday ; i++)    
  200.                     {
  201.                         len = *abTablePt;
  202.                         // shift to the next one. don't forget the len byte itself.
  203.                         abTablePt += len + 1;    
  204.                     }
  205.                     // Ok, we got it, let's copy it.
  206.                     len = *abTablePt;
  207.                     ::BlockMoveData(abTablePt,&weekdayString[0] ,len+1);
  208.                     gotit = true;
  209.                 }
  210.             }
  211.         }
  212.         
  213.         // didn't get it. Either it is not in itl1ExtRect format or it don't have
  214.         // additional abbreviation table. 
  215.         // use itl1Rect instead.
  216.         if(! gotit)
  217.         {    
  218.             // get abbreviation length
  219.             // not the length is not always 3. Some country use longer (say 4)
  220.             // abbreviation.
  221.             short abbrLen = (*Itl1RecordHandle)->abbrLen;
  222.             // Fix  Traditional Chinese problem
  223.             if(((((*Itl1RecordHandle)->intl1Vers) >> 8) == verTaiwan ) &&
  224.                (abbrLen == 4) &&
  225.                ((*Itl1RecordHandle)->days[0][0] == 6) && 
  226.                ((*Itl1RecordHandle)->days[1][0] == 6) && 
  227.                ((*Itl1RecordHandle)->days[2][0] == 6) && 
  228.                ((*Itl1RecordHandle)->days[3][0] == 6) && 
  229.                ((*Itl1RecordHandle)->days[4][0] == 6) && 
  230.                ((*Itl1RecordHandle)->days[5][0] == 6) && 
  231.                ((*Itl1RecordHandle)->days[6][0] == 6))
  232.             {
  233.                 abbrLen = 6;
  234.             }
  235.             weekdayString[0] = abbrLen;
  236.             // copy the weekday name with that abbreviation length
  237.             ::BlockMoveData(&((*Itl1RecordHandle)->days[dateTime.dayOfWeek-1][1]),
  238.                  &weekdayString[1] , abbrLen);
  239.             gotit = true;
  240.         }
  241.     }
  242.     else 
  243.     {    // cannot get itl1 resource, return with null string.
  244.         weekdayString[0] = 0;
  245.     }
  246. }
  247.  
  248.  
  249. size_t FE_StrfTime(MWContext* context, char *result, size_t maxsize,  int format, 
  250.     const struct tm *timeptr)
  251.  
  252. {
  253.  
  254.     Str255 timeString;
  255.     int32 dateTime;    
  256.     DateTimeRec macDateTime;
  257.     
  258.     // convert struct tm to input format of mac toolbox call
  259.     
  260.     XP_ASSERT(timeptr->tm_year >= 0);
  261.     XP_ASSERT(timeptr->tm_mon >= 0);
  262.     XP_ASSERT(timeptr->tm_mday >= 0);
  263.     XP_ASSERT(timeptr->tm_hour >= 0);
  264.     XP_ASSERT(timeptr->tm_min >= 0);
  265.     XP_ASSERT(timeptr->tm_sec >= 0);
  266.     XP_ASSERT(timeptr->tm_wday >= 0);
  267.     
  268.     // Mac need a number from 1904 to 2040 
  269.     // tm only provide the last two digit of the year */
  270.     macDateTime.year = timeptr->tm_year + 1900;    
  271.     
  272.     // Mac use 1 for Jan and 12 for Dec
  273.     // tm use 0 for Jan and 11 for Dec 
  274.     macDateTime.month = timeptr->tm_mon + 1;    
  275.     macDateTime.day = timeptr->tm_mday;
  276.     macDateTime.hour = timeptr->tm_hour;
  277.     macDateTime.minute = timeptr->tm_min;
  278.     macDateTime.second = timeptr->tm_sec;
  279.     
  280.     // Mac use 1 for sunday 7 for saturday
  281.     // tm use 0 for sunday 6 for saturday 
  282.     macDateTime.dayOfWeek = timeptr->tm_wday +1 ; 
  283.     
  284.     ::DateToSeconds( &macDateTime, (unsigned long *) &dateTime);
  285.     INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context);
  286.     long scriptcode = WinCharsetIDToScript(INTL_GetCSIWinCSID(c));
  287.     Handle itl1Handle = (Handle) GetItl1Resource(scriptcode);
  288.     Handle itl0Handle = (Handle) GetItl0Resource(scriptcode);
  289.  
  290.     // get time string
  291.     if(format == XP_LONG_DATE_TIME_FORMAT)
  292.         ::TimeString(dateTime, TRUE, timeString, itl0Handle);
  293.     else
  294.         ::TimeString(dateTime, FALSE, timeString, itl0Handle);
  295.     switch(format)
  296.     {
  297.         case XP_TIME_FORMAT:
  298.             {
  299.                 if (timeString[0] >= maxsize) {
  300.                     result[0] = '\0';
  301.                     return(0);
  302.                 }
  303.                 // just copy the time string
  304.                 if(timeString[0] > 0)
  305.                     ::BlockMoveData(&timeString[1], result , timeString[0]);
  306.                 result[ timeString[0]] = '\0';
  307.                 return (  timeString[0] );
  308.             }
  309.         case XP_LONG_DATE_TIME_FORMAT:
  310.         case XP_WEEKDAY_TIME_FORMAT:
  311.         case XP_DATE_TIME_FORMAT:
  312.             {
  313.                 Str255 dateString;
  314.                 switch(format)
  315.                 {
  316.                 case XP_LONG_DATE_TIME_FORMAT:
  317.                     ::DateString(dateTime, abbrevDate, dateString, itl1Handle);
  318.                     break;
  319.                 case XP_DATE_TIME_FORMAT:
  320.                     ::DateString(dateTime, shortDate, dateString, itl0Handle);
  321.                     break;    
  322.                 case XP_WEEKDAY_TIME_FORMAT:
  323.                     AbbrevWeekdayString(macDateTime, dateString, (Intl1Hndl)itl1Handle);
  324.                     // try fallback if it return with null string.
  325.                     if(dateString[0] == 0)
  326.                     {    //    cannot get weekdayString from itl1 , try fallback
  327.                         dateString[0] =  strftime((char*)&dateString[1],254,"%a",timeptr);
  328.                     }
  329.                     break;    
  330.                 }
  331.                 // Append the date string and time string tother. seperate with " "
  332.                 if((dateString[0]+timeString[0] + 1) >= maxsize) {
  333.                     // try put dateString only
  334.                     if(dateString[0] >= maxsize)
  335.                     {
  336.                         result[0] = '\0';
  337.                         return(0);
  338.                     } 
  339.                     else    
  340.                     {    // we don't have space for Date and Time . So , just put date there
  341.                         if(dateString[0] > 0)
  342.                             ::BlockMoveData(&dateString[1], result , dateString[0]);
  343.                         result[ dateString[0]] = '\0';
  344.                         return (  dateString[0] );
  345.                     }
  346.                 } else {
  347.                     int dlen; // we need to rescan the datestring because a bug in Cyrillic itl1
  348.                     for(dlen=0;(dlen < dateString[0]) && (dateString[dlen+1] != '\0'); dlen++)
  349.                         ;
  350.                     // just incase dateString got a null string
  351.                     if(dlen > 0)
  352.                         ::BlockMoveData(&dateString[1], result , dlen);
  353.                     result[ dlen] = ' ';
  354.                     // just incase timeString got a null string
  355.                     if(timeString[0] > 0)
  356.                         ::BlockMoveData(&timeString[1], &result[dlen+1] , timeString[0]);
  357.                     result[ dlen+timeString[0] + 1] = '\0';
  358.                     return ( dlen+timeString[0] + 1);
  359.                 }
  360.             }
  361.             break;
  362.         default:
  363.             result[0] = '\0';
  364.             return(0);
  365.             break;
  366.     }
  367. }
  368.  
  369.