home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / central / mintl.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  20.1 KB  |  742 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. #include "uprefd.h"
  20. // macfe
  21. #include "macutil.h"    // ConstrainTo
  22. #include "resgui.h"        // FENC_RESTYPE, CSIDLIST_RESTYPE, cmd2csid_tbl_ResID
  23. // Netscape
  24. #ifndef _XP_H_
  25. #include "xp_mcom.h"
  26. #endif
  27. #include "libi18n.h"    // INTL_SetUnicodeCSIDList
  28. #include "xpassert.h"
  29. /* Testing Code */
  30. #include "csid.h"        // CS_MAC_ROMAN, CS_AUTO, CS_DEFAULT
  31. #include "intlpriv.h"    // prototypes for FE_GetSingleByteTable and FE_FreeSingleByteTable
  32. #include "PascalString.h"
  33. #include "prefapi.h"
  34.  
  35. /******************************************************************************************
  36.  * INTERNATIONAL STUFF
  37.  * Better off in another file?
  38.  ******************************************************************************************/
  39.  
  40. static const char* Pref_PropFont = ".prop_font";
  41. static const char* Pref_PropSize = ".prop_size";
  42. static const char* Pref_FixedFont = ".fixed_font";
  43. static const char* Pref_FixedSize = ".fixed_size";
  44.  
  45. LArray*            CPrefs::fCharSetFonts = NULL;
  46. CCharSet        CPrefs::fDefaultFont;
  47.  
  48. static int FontChanged(const char * prefname, void * stuff);
  49. static void InitCheckScriptFont(Handle hndl);
  50.  
  51. static void ReadCharacterEncodingsHandle(Handle hndl, Boolean usePrevious)
  52. {
  53.     unsigned short        numberEncodings;
  54.     ThrowIfResError_();
  55.     ::DetachResource( hndl );
  56.     ThrowIfResError_();
  57.     
  58.     LHandleStream    stream( hndl );
  59.                 
  60.     stream.ReadData( &numberEncodings, sizeof( unsigned short) );
  61.     XP_ASSERT(numberEncodings>0);
  62.     for(int i=0;i<numberEncodings;i++)
  63.     {
  64.         CStr31            EncodingName;
  65.         CStr31            PropFont;
  66.         CStr31            FixedFont; 
  67.         unsigned short    PropFontSize;
  68.         unsigned short    FixedFontSize;
  69.         unsigned short    CSID;
  70.         unsigned short  FallbackFontScriptID;
  71.         unsigned short    TxtrButtonResID;
  72.         unsigned short    TxtrTextFieldResID;    
  73.         
  74.         stream.ReadData( &EncodingName,    sizeof( CStr31) );
  75.         stream.ReadData( &PropFont,         sizeof( CStr31) );
  76.         stream.ReadData( &FixedFont,         sizeof( CStr31) );
  77.         stream.ReadData( &PropFontSize,     sizeof( unsigned short) );
  78.         stream.ReadData( &FixedFontSize,     sizeof( unsigned short) );
  79.         stream.ReadData( &CSID,             sizeof( unsigned short) );
  80.         stream.ReadData( &FallbackFontScriptID, sizeof( unsigned short) );
  81.         stream.ReadData( &TxtrButtonResID, sizeof( unsigned short) );
  82.         stream.ReadData( &TxtrTextFieldResID, sizeof( unsigned short) );
  83.         
  84.         if ( CPrefs::SetFont( EncodingName, PropFont, FixedFont, PropFontSize, FixedFontSize,
  85.                          CSID , FallbackFontScriptID, TxtrButtonResID, TxtrTextFieldResID ) )
  86.         {
  87.             // Convert CCharSet to 4.0 xp preferences
  88.             CCharSet csFont;
  89.             CPrefs::GetFont(CSID, &csFont);
  90.             char key[256];
  91.             XP_SPRINTF(key, "intl.font%d", CSID);
  92.             
  93.             if (!usePrevious) {
  94.                 PREF_SetDefaultCharPref(CPrefs::Concat(key, Pref_PropFont), csFont.fPropFont);
  95.                 PREF_SetDefaultCharPref(CPrefs::Concat(key, Pref_FixedFont), csFont.fFixedFont);
  96.                 PREF_SetDefaultIntPref(CPrefs::Concat(key, Pref_PropSize), csFont.fPropFontSize);
  97.                 PREF_SetDefaultIntPref(CPrefs::Concat(key, Pref_FixedSize), csFont.fFixedFontSize);
  98.             }
  99.             else {
  100.                 PREF_SetCharPref(CPrefs::Concat(key, Pref_PropFont), csFont.fPropFont);
  101.                 PREF_SetCharPref(CPrefs::Concat(key, Pref_FixedFont), csFont.fFixedFont);
  102.                 PREF_SetIntPref(CPrefs::Concat(key, Pref_PropSize), csFont.fPropFontSize);
  103.                 PREF_SetIntPref(CPrefs::Concat(key, Pref_FixedSize), csFont.fFixedFontSize);
  104.             }
  105.         }
  106.     }
  107. }
  108.  
  109. void CPrefs::ReadCharacterEncodings()
  110. {
  111.     Handle hndl;
  112.     if (UseApplicationResFile())    // It will first try to read from application. Put them into our memory preference
  113.     {
  114.         hndl = ::Get1Resource( FENC_RESTYPE,FNEC_RESID );
  115.         if (hndl)
  116.         {
  117.             if (!*hndl)
  118.                 ::LoadResource(hndl);
  119.             
  120.             if (*hndl)
  121.             {
  122.                 ::HNoPurge(hndl);
  123.                 ReadCharacterEncodingsHandle(hndl, false);
  124.                 ::HPurge(hndl);
  125.             }
  126.         }
  127.     }
  128.     if (sPrefFileVersion == 3 && UsePreferencesResFile())    // It then try to read from application. overwrite the memory preference we build above
  129.     {
  130.         hndl = ::Get1Resource( FENC_RESTYPE,FNEC_RESID );
  131.         if (hndl)
  132.         {
  133.             if (!*hndl)
  134.                 ::LoadResource(hndl);
  135.             
  136.             if (*hndl)
  137.             {
  138.                 ::HNoPurge(hndl);
  139.                 ReadCharacterEncodingsHandle(hndl, true);
  140.                 ::HPurge(hndl);
  141.             }
  142.         }
  143.     }
  144.     // Convert 4.0 style preferences to CCharSet structure
  145.     else if (sPrefFileVersion == 4)
  146.     {
  147.         CCharSet csFont;
  148.         LArrayIterator iter( *fCharSetFonts );
  149.         while ( iter.Next( &csFont ) ) {
  150.             ReadXPFont(csFont.fCSID, &csFont);
  151.         }
  152.     }
  153.     
  154.     // Currently it is not customerizable, so we don't check PreferencesFile
  155.     if (UseApplicationResFile())    
  156.     {
  157.         hndl = ::Get1Resource( CSIDLIST_RESTYPE, CSIDLIST_RESID );
  158.         if (hndl)
  159.         {
  160.             if (!*hndl)
  161.                 ::LoadResource(hndl);
  162.             
  163.             if (*hndl)
  164.             {
  165.                 ::HNoPurge(hndl);
  166.                 InitCheckScriptFont(hndl);
  167.                 ::HPurge(hndl);
  168.             }
  169.         }
  170.     }
  171.     
  172.     PREF_RegisterCallback( "intl.font", FontChanged, nil );
  173. }
  174.  
  175. // 4.0: Font changes register the following callback which
  176. // reflects xp pref changes into the CCharSet structure
  177. int FontChanged(const char * prefname, void * /* stuff */)
  178. {
  179.     int csid;
  180.     if (sscanf(prefname, "intl.font%d", &csid)) {
  181.         CCharSet csFont;
  182.         if (CPrefs::GetFont(csid, &csFont)) {
  183.             CPrefs::ReadXPFont(csid, &csFont);
  184.         }
  185.     }
  186.     return 0;
  187. }
  188.  
  189. // Convert CCharSet to xp font pref
  190. void CPrefs::ReadXPFont(int16 csid, CCharSet* csFont)
  191. {
  192.     char key[256];
  193.     int len = 31;
  194.     char propFont[31];
  195.     char fixedFont[31];
  196.     int32 propSize, fixedSize;
  197.     
  198.     XP_SPRINTF(key, "intl.font%d", csid);
  199.     PREF_GetCharPref(Concat(key, Pref_PropFont), propFont, &len);
  200.     PREF_GetCharPref(Concat(key, Pref_FixedFont), fixedFont, &len);
  201.     PREF_GetIntPref(Concat(key, Pref_PropSize), &propSize);
  202.     PREF_GetIntPref(Concat(key, Pref_FixedSize), &fixedSize);
  203.     
  204.     CPrefs::SetFont( csFont->fEncodingName, propFont, fixedFont, propSize, fixedSize,
  205.                  csFont->fCSID , csFont->fFallbackFontScriptID, csFont->fTxtrButtonResID,
  206.                  csFont->fTxtrTextFieldResID );
  207. }
  208.  
  209. extern int16        cntxt_lastSize;
  210.  
  211. Boolean CPrefs::SetFont(    const CStr255& EncodingName,
  212.                             const CStr255& PropFont,
  213.                             const CStr255& FixedFont,
  214.                             unsigned short PropFontSize, 
  215.                             unsigned short FixedFontSize, 
  216.                             unsigned short CSID, 
  217.                             unsigned short FallbackFontScriptID, 
  218.                             unsigned short TxtrButtonResID, 
  219.                             unsigned short TxtrTextFieldResID )
  220. {
  221.     CCharSet            csFont;
  222.     Boolean                changed = FALSE;
  223.     long                realFixedSize;
  224.     long                realPropSize;
  225.     short                index;
  226.     CStr255                systemFont;
  227.     
  228.     ::GetFontName( 0, systemFont );
  229.     if ( CPrefs::GetFont( CSID, &csFont ) )
  230.         index = fCharSetFonts->FetchIndexOf( &csFont );
  231.     else
  232.     {
  233.         csFont.fEncodingName = EncodingName;
  234.         csFont.fCSID = CSID;
  235.         csFont.fFallbackFontScriptID = FallbackFontScriptID;
  236.         csFont.fTxtrButtonResID = TxtrButtonResID;
  237.         csFont.fTxtrTextFieldResID = TxtrTextFieldResID;
  238.             
  239.         if ( CSID == CS_MAC_ROMAN )
  240.             fCharSetFonts->InsertItemsAt( 1, LArray::index_First, &csFont );
  241.         else
  242.             fCharSetFonts->InsertItemsAt( 1, LArray::index_Last, &csFont );
  243.         index = fCharSetFonts->FetchIndexOf( &csFont );
  244.         changed = TRUE;
  245.     }
  246.     if ( index != LArray::index_Bad )
  247.     {
  248.         realFixedSize = FixedFontSize;
  249.         realPropSize = PropFontSize;
  250.         
  251.         ConstrainTo( FONT_SIZE_MIN, FONT_SIZE_MAX, realFixedSize );
  252.         ConstrainTo( FONT_SIZE_MIN, FONT_SIZE_MAX, realPropSize );
  253.         
  254.         if (     changed || 
  255.                 PropFont != csFont.fPropFont || realPropSize != csFont.fPropFontSize ||
  256.                 FixedFont != csFont.fFixedFont || realFixedSize != csFont.fFixedFontSize )
  257.         {
  258.         
  259.             csFont.fPropFont = PropFont;
  260.             csFont.fPropFontSize = realPropSize;
  261.             csFont.fFixedFont = FixedFont;
  262.             csFont.fFixedFontSize = realFixedSize;
  263.                 
  264.             ::GetFNum( PropFont, (short*)&csFont.fPropFontNum );
  265.             if(csFont.fPropFontNum == 0 && !EqualString( PropFont, systemFont, FALSE, FALSE ) )
  266.             {    
  267.                 
  268.                 // Do not have that font. Try to us smScriptAppFondSize from Script Manager
  269.                 long AppFondSize;
  270.                 unsigned short AppFond;
  271.                 CStr255 tryFontName;
  272.                 
  273.                 AppFondSize = ::GetScriptVariable(FallbackFontScriptID, smScriptAppFondSize);
  274.                 AppFond = (AppFondSize >> 16);
  275.                 ::GetFontName(AppFond, tryFontName);
  276.                 if(tryFontName[0] != 0)    // The AppFond exist
  277.                 {
  278.                     csFont.fPropFontNum = AppFond;
  279.                     csFont.fPropFont = tryFontName;
  280.                 }
  281.             }
  282.             ::GetFNum( FixedFont, (short*)&csFont.fFixedFontNum );
  283.             if(csFont.fFixedFontNum == 0 && !EqualString( FixedFont, systemFont, FALSE, FALSE ) )
  284.             {    
  285.                 // Do not have that font. Try to us smScriptAppFondSize from Script Manager
  286.                 long SmallFondSize;
  287.                 unsigned short SmallFond;
  288.                 CStr255 tryFontName;
  289.                 SmallFondSize = ::GetScriptVariable(FallbackFontScriptID,smScriptSmallFondSize);
  290.                 SmallFond = (SmallFondSize >> 16);
  291.                 ::GetFontName(SmallFond, tryFontName);
  292.                 if(tryFontName[0] != 0)    // The SmallFond exist.
  293.                 {
  294.                     csFont.fFixedFontNum = SmallFond;
  295.                     csFont.fFixedFont = tryFontName;
  296.                 }
  297.             }
  298.  
  299.             fCharSetFonts->AssignItemsAt( 1, index, &csFont );
  300.  
  301.             changed = TRUE;
  302.             if((csFont.fTxtrButtonResID!=0) || (csFont.fTxtrTextFieldResID!=0))
  303.             {
  304.             // Mapping of char set to textTraits resources
  305.             // Txtr resources need to be locked and held in memory
  306.                 Int16 buttonFont, textField;
  307.                 buttonFont = csFont.fTxtrButtonResID;
  308.                 textField = csFont.fTxtrTextFieldResID;
  309.                 
  310.                 UseApplicationResFile();
  311.                 
  312.                 TextTraitsH    buttonH = (TextTraitsH) ::GetResource( 'Txtr', buttonFont );
  313.                 TextTraitsH    textH = (TextTraitsH) ::GetResource( 'Txtr', textField );
  314.                 if (buttonH && textH )
  315.                 {
  316.                     if (!*buttonH)
  317.                         ::LoadResource((Handle)buttonH);
  318.                     
  319.                     if (*buttonH)
  320.                         ::HNoPurge( (Handle)buttonH );
  321.                     
  322.                     if (!*textH)
  323.                         ::LoadResource((Handle)textH);
  324.                     
  325.                     if (*textH)
  326.                         ::HNoPurge( (Handle)textH );
  327.                     
  328.                     if (*buttonH && *textH )
  329.                     {
  330.                         short size = ::GetHandleSize((Handle)buttonH);
  331.                         ::SetHandleSize((Handle)textH, sizeof(TextTraitsRecord));    // Because resources  are compressed
  332.                         (**textH).fontNumber = -1;//fontNumber_Unknown in UTextTraits
  333.                         StHandleLocker lock((Handle)textH);
  334.                         LString::CopyPStr(csFont.fFixedFont, (StringPtr)&(**textH).fontName, 255);
  335.                         (**textH).size = realFixedSize;
  336.                         (**buttonH).fontNumber = -1;    // fontNumber_Unknown
  337.                         ::SetHandleSize((Handle)buttonH, sizeof(TextTraitsRecord));    // Because resources  are compressed
  338.                         StHandleLocker lock2((Handle)buttonH);
  339.                         LString::CopyPStr(csFont.fPropFont, (StringPtr)&(**buttonH).fontName, 255);
  340.                     }
  341.                 }
  342.     #ifdef DEBUG
  343. //                else
  344. //                    XP_ASSERT(FALSE);
  345.     #endif
  346.             }
  347.         }
  348.     }
  349.     
  350.     if (changed)
  351.         SetModified();
  352.     return changed;
  353. }
  354.  
  355.  
  356.  
  357.  
  358. Boolean CPrefs::GetFont( UInt16 win_csid, CCharSet* font )
  359. {
  360.     CCharSet            csFont;
  361.     LArrayIterator        iter( *fCharSetFonts );
  362.     win_csid &= ~CS_AUTO;
  363.     while ( iter.Next( &csFont ) )
  364.     {
  365.         if ( (csFont.fCSID & ~CS_AUTO) == win_csid )
  366.         {
  367.             *font = csFont;
  368.             return TRUE;
  369.         }
  370.     }
  371.     font = &fDefaultFont;
  372.     return FALSE;
  373. }
  374.  
  375. Boolean CPrefs::GetFontAtIndex( unsigned long index, CCharSet* font )
  376. {
  377.     XP_ASSERT( index <= fCharSetFonts->GetCount() );
  378.     
  379.     return ( fCharSetFonts->FetchItemAt( index, font ) );
  380. }
  381. Int16 CPrefs::GetButtonFontTextResIDs(unsigned short csid)
  382. {
  383.     CCharSet csFont;
  384.     GetFont(csid, &csFont );
  385.     return csFont.fTxtrButtonResID;
  386. }
  387. Int16 CPrefs::GetTextFieldTextResIDs(unsigned short csid)
  388. {
  389.     CCharSet csFont;
  390.     GetFont(csid, &csFont );
  391.     return csFont.fTxtrTextFieldResID;
  392. }
  393.  
  394. short CPrefs::GetProportionalFont(unsigned short csid)
  395. {
  396.     CCharSet csFont;
  397.     GetFont(csid, &csFont );
  398.     return csFont.fPropFontNum;
  399. }
  400. short CPrefs::GetFixFont(unsigned short csid)
  401. {
  402.     CCharSet csFont;
  403.     GetFont(csid, &csFont );
  404.     return csFont.fFixedFontNum;
  405. }
  406.  
  407.  
  408. // pkc 1/23/97
  409. // PowerPC alignment is on by default, so we need
  410. // to set 68k alignment for these structs
  411. #pragma options align=mac68k
  412.  
  413. struct CsidPair {
  414.     int16             win_csid;
  415.     int16             doc_csid;
  416.     int32             cmdNum;
  417. };
  418.  
  419. struct CsidTable
  420. {
  421.     int16         itemcount;
  422.     CsidPair     pair[1];
  423. };
  424.  
  425. #pragma options align=reset
  426. //
  427.  
  428. int16 CPrefs::CmdNumToWinCsid( int32 cmdNum)
  429. {
  430.     // Get resource from application
  431.     Handle hndl = ::GetResource( 'Csid', cmd2csid_tbl_ResID);
  432.         // Note: ::GetResource calls _LoadResource internally.  You don't
  433.         // have to call LoadResource again, it's a waste of space and time.
  434.     ThrowIfResError_();
  435.     if (hndl != NULL)
  436.     {
  437.         // lock in on the stack.
  438.         StHandleLocker lock((Handle) hndl );
  439.         // cast it into our internal data struct
  440.         CsidTable** cthndl = (CsidTable**)hndl;
  441.         // search it.
  442.         int16 itemcount = (**cthndl).itemcount;
  443.         CsidPair* item = &(**cthndl).pair[0];
  444.         for (int16 i = 0; i < itemcount; i++, item++)
  445.         {
  446.             if (cmdNum == item->cmdNum)
  447.                 return item->win_csid;
  448.         }
  449.     }
  450.     return CS_DEFAULT;
  451. }
  452.  
  453. int16 CPrefs::CmdNumToDocCsid(int32 cmdNum)
  454. {
  455.     // Get resource from application
  456.     Handle hndl = ::GetResource( 'Csid', cmd2csid_tbl_ResID);
  457.         // Note: ::GetResource calls _LoadResource internally.  You don't
  458.         // have to call LoadResource again, it's a waste of space and time.
  459.     ThrowIfResError_();
  460.     if (hndl != NULL)
  461.     {
  462.         // lock in on the stack.
  463.         StHandleLocker lock((Handle) hndl );
  464.         // cast it into our internal data struct
  465.         CsidTable** cthndl = (CsidTable**)hndl;
  466.         // search it.
  467.         int16 itemcount = (**cthndl).itemcount;
  468.         CsidPair* item = &(**cthndl).pair[0];
  469.         for (int16 i = 0; i < itemcount; i++, item++)
  470.         {
  471.             if (cmdNum == item->cmdNum)
  472.                 return item->doc_csid;
  473.         }
  474.     }
  475.     return CS_DEFAULT;
  476. }
  477.  
  478. int32  CPrefs::WinCsidToCmdNum( int16 csid)
  479. {
  480.     // Get resource from application
  481.     Handle hndl = ::GetResource( 'Csid', cmd2csid_tbl_ResID);
  482.         // Note: ::GetResource calls _LoadResource internally.  You don't
  483.         // have to call LoadResource again, it's a waste of space and time.
  484.     ThrowIfResError_();
  485.     if(hndl != NULL)
  486.     {
  487.         // lock in on the stack
  488.         StHandleLocker lock((Handle) hndl );
  489.         // cast it into our internal data struct
  490.         CsidTable** cthndl = (CsidTable**)hndl;
  491.         // search it.
  492.         int16 itemcount = (**cthndl).itemcount;
  493.         CsidPair* item = &(**cthndl).pair[0];
  494.         for (int16 i = 0; i < itemcount; i++, item++)
  495.         {
  496.             if (csid == item->win_csid)
  497.                 return item->cmdNum;
  498.         }
  499.     }
  500.     return cmd_Nothing;
  501. }
  502.  
  503. enum {
  504.     kScriptIsNotEnabled = 0,
  505.     kScriptIsEnabled,
  506.     kScriptHasFont
  507. };
  508.  
  509. static Boolean CheckNamedFont(ConstStr255Param name)
  510. {
  511.     short family;
  512.     ::GetFNum(name, &family);
  513.     return family != 0;
  514. }
  515. ScriptCode  CPrefs::CsidToScript(int16 csid)
  516. {
  517.     switch(csid)
  518.     {
  519.         case CS_DINGBATS:
  520.             XP_ASSERT(TRUE);
  521.             return -1;
  522.         case CS_SYMBOL:
  523.             XP_ASSERT(TRUE);
  524.             return -1;
  525.         default:
  526.             CCharSet font;
  527.             if(CPrefs::GetFont(csid,&font ))
  528.                 return font.fFallbackFontScriptID;
  529.             else
  530.             {
  531.                 XP_ASSERT(TRUE);
  532.                 return -1;
  533.             }
  534.     }
  535. }
  536. static void InitCheckScriptFont(Handle hndl)
  537. {
  538.     int scriptstatus[64];
  539.     ScriptCode script;
  540.     for(script = 0 ; script < 64 ; script++)
  541.     {
  542.         if((::GetScriptVariable(script, smScriptEnabled) & 0x00FF) == 0)
  543.             scriptstatus[script] = kScriptIsNotEnabled;
  544.         else
  545.             scriptstatus[script] = kScriptIsEnabled;
  546.     }
  547.  
  548.     int numOfFond = CountResources('FOND');
  549.     ThrowIfResError_();
  550.     for(short i=0; i < numOfFond; i++)
  551.     {
  552.         ScriptCode fontscript;
  553.         short resid;
  554.         ResType type;
  555.         Str255 name;
  556.         Handle handle = GetIndResource('FOND', i+1);
  557.         GetResInfo(handle, &resid, &type, name);
  558.         ThrowIfResError_();
  559.         fontscript = FontToScript(resid);
  560.         if(scriptstatus[fontscript] == kScriptIsEnabled)
  561.             scriptstatus[fontscript] = kScriptHasFont;
  562.     }
  563.     unsigned short        numOfCsid;
  564.     ::DetachResource( hndl );
  565.     ThrowIfResError_();
  566.     
  567.     LHandleStream    stream( hndl );
  568.                 
  569.     stream.ReadData( &numOfCsid, sizeof( unsigned short) );
  570.     XP_ASSERT(numOfCsid > 0);
  571.     uint16 realNum = 0;
  572.     int16 *reallist = new int16[numOfCsid];
  573.     ThrowIfNil_( reallist );
  574.     for(int i=0;i<numOfCsid;i++)
  575.     {
  576.         int16 thiscsid;
  577.         stream.ReadData( &thiscsid,    sizeof( int16) );
  578.         Boolean csidenabled;
  579.         switch(thiscsid)
  580.         {
  581.             case CS_DINGBATS:
  582.                 csidenabled = CheckNamedFont("\pZapf Dingbats");
  583.                 break;
  584.             case CS_SYMBOL:
  585.                 csidenabled = CheckNamedFont("\pSymbol");
  586.                 break;
  587.             case CS_MAC_GREEK:
  588.                 csidenabled = (::GetScriptManagerVariable(smRegionCode) == verGreece);
  589.                 break;            
  590.             default:
  591.                 ScriptCode csidScript = CPrefs::CsidToScript(thiscsid);
  592.                 csidenabled = (scriptstatus[ csidScript ] == kScriptHasFont);
  593.                 break;
  594.         }
  595.         if(csidenabled)
  596.             reallist[ realNum++ ] = thiscsid;
  597.     }
  598.     INTL_SetUnicodeCSIDList(realNum, reallist);
  599.     delete[] reallist;
  600. }
  601.  
  602.  
  603.  
  604.  
  605. //
  606. //    I need to implement the RefCount for this table loader
  607. //
  608. struct RefCount
  609. {
  610.     int32 id;
  611.     int32 count;
  612.     char **cvthdl;
  613. };
  614. LArray* fXlatList =  NULL;
  615. class xlateRefCountList {
  616.     private:
  617.     public:
  618.         static void init();
  619.         static char ** Inc(int32 inid);
  620.         static int32 Dec(char **cvthdl);
  621.         
  622. };
  623. void xlateRefCountList::init()
  624. {
  625.     fXlatList = new LArray(sizeof(RefCount));
  626. }
  627.  
  628. char ** xlateRefCountList::Inc(int32 inid)
  629. {
  630.     RefCount            refcount;
  631.     LArrayIterator        iter( *fXlatList );
  632.     short    index;
  633.     while ( iter.Next( &refcount ) )
  634.     {
  635.         if( (refcount.id) == inid )
  636.         {
  637.             index = fXlatList->FetchIndexOf( &refcount );
  638.             if (refcount.count == 0)
  639.             {
  640.                 // If the refcount is positive, the handle is guaranteed loaded and locked.
  641.                 // Otherwise, we must do these things.
  642.                 ::LoadResource(refcount.cvthdl);
  643.                 ::HLock(refcount.cvthdl);
  644.             }
  645.             refcount.count++;
  646.             fXlatList->AssignItemsAt( 1, index, &refcount );
  647.             return refcount.cvthdl;
  648.         }
  649.     }
  650.     // we cannot find the refcount for this xlat. So, lets 
  651.     // get the table from resource and insert one.
  652.     Handle tableHandle;
  653.     tableHandle =  ::GetResource('xlat',inid); // also loads!
  654.     ThrowIfResError_();
  655.     ThrowIfNil_(tableHandle);
  656.  
  657.     ::HLock(tableHandle);
  658.     ThrowIfMemError_();
  659.  
  660.     refcount.id = inid;
  661.     refcount.count = 1;
  662.     refcount.cvthdl = tableHandle;
  663.     fXlatList->InsertItemsAt( 1, LArray::index_First, &refcount );
  664.     return tableHandle;    
  665. }
  666.  
  667. int32 xlateRefCountList::Dec(char **cvthdl)
  668. {
  669.     RefCount            refcount;
  670.     LArrayIterator        iter( *fXlatList );
  671.     while ( iter.Next( &refcount ) )
  672.     {
  673.         if( (refcount.cvthdl) == cvthdl )
  674.         {
  675.             short    index = fXlatList->FetchIndexOf( &refcount );
  676.             if (refcount.count > 0)
  677.             {
  678.                 refcount.count--;
  679.                 fXlatList->AssignItemsAt( 1, index, &refcount );
  680.  
  681.                 if (refcount.count == 0)
  682.                 {
  683.                     ::HUnlock((Handle) refcount.cvthdl);
  684.                     ThrowIfMemError_();
  685.                     // ::HPurge((Handle) refcount.cvthdl); Unnecessary, resources are purgeable.
  686.                 }
  687.             }
  688.             return refcount.count;
  689.         }
  690.     }
  691. //    XP_ASSERT(FALSE);
  692. //    Don't assert: we may receive an old copy of sLastTableHandle
  693.     return 0;
  694. }
  695.  
  696. static char **    sLastTableHandle    = nil;
  697. static int32    sLastTableID        = -1;
  698.  
  699. char ** 
  700. FE_GetSingleByteTable(int16 /*from_csid*/, int16 /*to_csid*/, int32 resourceid)
  701. {
  702.     char **            tableHandle;
  703.  
  704.     if(fXlatList == NULL)
  705.         xlateRefCountList::init();
  706.  
  707.     // if we need the same table, return the previous copy
  708.     if (resourceid == sLastTableID && sLastTableHandle != nil)
  709.     {
  710.         return sLastTableHandle;
  711.     }
  712.  
  713.     // otherwise load the new table...
  714.     tableHandle = xlateRefCountList::Inc(resourceid);
  715.  
  716.     // ...and make a copy of it
  717.     if (sLastTableHandle != nil)
  718.         ::DisposeHandle(sLastTableHandle);
  719.     sLastTableHandle = tableHandle;
  720.     if (::HandToHand(&sLastTableHandle) == noErr)
  721.         sLastTableID = resourceid;
  722.     else
  723.         sLastTableHandle = nil;
  724.  
  725.     return tableHandle;
  726. }
  727.  
  728. void FE_FreeSingleByteTable(char **cvthdl)
  729. {
  730.     if(fXlatList == NULL)
  731.         xlateRefCountList::init();
  732.  
  733.     if (cvthdl != sLastTableHandle)
  734.         (void)xlateRefCountList::Dec(cvthdl); // safe to Dec more than we Inc'ed
  735. }
  736.  
  737.  
  738.  
  739.  
  740.  
  741.  
  742.