home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 January: Mac OS SDK / Dev.CD Jan 99 SDK2.toast / Development Kits / TEC 1.4 / SampleCode / UnicodeHub / UnicodeHub.cp < prev    next >
Encoding:
Text File  |  1998-09-25  |  41.9 KB  |  1,447 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        UnicodeHub.cp
  3.  
  4.     Contains:    
  5.  
  6.     Version:    System 8
  7.  
  8.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                Julio Gonzalez
  13.  
  14.         Other Contact:        Andrew Daniels
  15.  
  16.         Technology:            International
  17.  
  18.     Writers:
  19.  
  20.         (jag)    Julio Gonzalez
  21.  
  22.     Change History (most recent first):
  23.  
  24.       <TEC2>     6/24/98    jag        Use InsertMenuItem + SetMenuItemText instead of just
  25.                                     InsertMenuItem so that we can get all the chars in the name
  26.                                     without having to worry about menu manager meta characters.
  27.       <TEC1>     6/16/98    jag        first checked in
  28.       <TEC0>     6/16/98    jag        Moved to BBS (new change numbers!).
  29.       
  30.     Old history in NRBuild:
  31.         <2+>    12/12/97    jag        Add HFS+ Unicode Item to the list as TECCountAvailableEncodings
  32.                                     ignores all UnicodeHFS+ variants.
  33.          <2>     8/20/97    jag        Change the style from outline to bold when displaying strings
  34.                                     that are encoded in non-Mac OS encodings.
  35. */
  36.  
  37. // ===========================================================================
  38. //    <PP Starter Source>.cp         ©1994-1995 Metrowerks Inc. All rights reserved.
  39. // ===========================================================================
  40. //
  41. //    This file contains the starter code for a PowerPlant application
  42.  
  43. #include "UnicodeHub.h"
  44. #include "UnicodeHubConstants.h"
  45.  
  46. #include <Sound.h>
  47. #include <Script.h>                            // Script Manager definitions
  48.  
  49. #include <LGrowZone.h>
  50. #include <LWindow.h>
  51. #include <PP_Messages.h>
  52. #include <PP_Resources.h>
  53. #include <PPobClasses.h>
  54. #include <UDrawingState.h>
  55. #include <UMemoryMgr.h>
  56. #include <UReanimator.h>
  57. #include <UDesktop.h>
  58. #include <URegistrar.h>
  59. #include <LEditField.h>
  60. #include <LTextEdit.h>
  61. #include <UTextTraits.h>
  62. #include "LDynamicArray.h"
  63.  
  64. unsigned char UnicodeErrors [][32] = {
  65.     "\p",
  66.     "\p",
  67.     "\p",
  68.     "\p",
  69.     "\pkTECOutputBufferFullStatus",
  70.     "\pkTECNeedFlushStatus",
  71.     "\pkTECUsedFallbacksStatus",
  72.     "\p",
  73.     "\p",
  74.     "\p",
  75.     "\p",
  76.     "\p",
  77.     "\p",
  78.     "\p",
  79.     "\p",
  80.     "\p",
  81.     "\p",
  82.     "\p",
  83.     "\pkTECItemUnavailableErr",
  84.     "\pkTECGlobalsUnavailableErr",    
  85.     "\punicodeChecksumErr",
  86.     "\punicodeNoTableErr",
  87.     "\punicodeVariantErr",
  88.     "\punicodeFallbacksErr",
  89.     "\punicodePartConvertErr",
  90.     "\punicodeBufErr",
  91.     "\punicodeCharErr",
  92.     "\punicodeElementErr",
  93.     "\punicodeNotFoundErr",
  94.     "\punicodeTableFormatErr",
  95.     "\punicodeDirectionErr",
  96.     "\punicodeContextualErr",
  97.     "\punicodeTextEncodingDataErr",
  98.     "\pkTECDirectionErr",
  99.     "\pkTECIncompleteElementErr",
  100.     "\pkTECUnmappableElementErr",
  101.     "\pkTECPartialCharErr",
  102.     "\pkTECBadTextRunErr",
  103.     "\pkTECArrayFullErr",
  104.     "\pkTECBufferBelowMinimumSizeErr",
  105.     "\pkTECNoConversionPathErr",
  106.     "\pkTECCorruptConverterErr",
  107.     "\pkTECTableFormatErr",
  108.     "\pkTECTableChecksumErr",
  109.     "\pkTECMissingTableErr",
  110.     "\p",
  111.     "\p",
  112.     "\p",
  113.     "\p",
  114.     "\kTextUndefinedElementErrp",
  115.     "\pkTextMalformedInputErr",
  116.     "\pkTextUnsupportedEncodingErr",
  117.     
  118.     "\pkIllegalHexString"
  119. };
  120.  
  121.  
  122.  
  123.  
  124. CPPStarterApp*    gTheApp=0;
  125.  
  126.  
  127.  
  128. // ===========================================================================
  129. //        • Main Program
  130. // ===========================================================================
  131.  
  132. void main(void)
  133. {
  134.                                     // Set Debugging options
  135.     SetDebugThrow_(debugAction_Alert);
  136.     SetDebugSignal_(debugAction_Nothing);
  137.  
  138.     InitializeHeap(3);                // Initialize Memory Manager
  139.                                     // Parameter is number of Master Pointer
  140.                                     //   blocks to allocate
  141.     
  142.                                     // Initialize standard Toolbox managers
  143.     UQDGlobals::InitializeToolbox(&qd);
  144.     
  145.     new LGrowZone(20000);            // Install a GrowZone function to catch
  146.                                     //    low memory situations.
  147.  
  148.     CPPStarterApp    theApp;            // replace this with your App type
  149.     
  150.     gTheApp = &theApp;                // Save a pointer to the application -- there might be a better
  151.                                     // way to get a the app -- like getting to the top level commander?
  152.  
  153.     theApp.GetMappings();            // Get all the available Unicode Mappings
  154.     
  155.     theApp.Run();
  156. }
  157.  
  158.  
  159. // ---------------------------------------------------------------------------
  160. //        • CPPStarterApp             // replace this with your App type
  161. // ---------------------------------------------------------------------------
  162.  
  163. //    Constructor
  164.  
  165. CPPStarterApp::CPPStarterApp()
  166. {
  167.     // Register functions to create core PowerPlant classes
  168.     
  169.     RegisterAllPPClasses();
  170.  
  171.     URegistrar::RegisterClass(
  172.             CUnicodeTablesPopup::class_ID,
  173.             (ClassCreatorFunc) CUnicodeTablesPopup::CreateUnicodeTablesPopupStream );
  174.     
  175.     URegistrar::RegisterClass(
  176.             CFontMenuPopup::class_ID,
  177.             (ClassCreatorFunc) CFontMenuPopup::CreateFontMenuPopupStream );
  178.     
  179.     URegistrar::RegisterClass(
  180.             CUnicodeHubWindow::class_ID,
  181.             (ClassCreatorFunc) CUnicodeHubWindow::CreateUnicodeHubWindowStream );
  182.     
  183.     URegistrar::RegisterClass(
  184.             CStyleText::class_ID,
  185.             (ClassCreatorFunc) CStyleText::CreateStyleTextEditStream );
  186.     
  187.     
  188. }
  189.  
  190.  
  191. // ---------------------------------------------------------------------------
  192. //        • ~CPPStarterApp            // replace this with your App type
  193. // ---------------------------------------------------------------------------
  194. //    Destructor
  195. //
  196.  
  197. CPPStarterApp::~CPPStarterApp()
  198. {
  199. }
  200.  
  201. // ---------------------------------------------------------------------------
  202. //        • StartUp
  203. // ---------------------------------------------------------------------------
  204. //    This function lets you do something when the application starts up. 
  205. //    For example, you could issue your own new command, or respond to a system
  206. //  oDoc (open document) event.
  207.  
  208. void
  209. CPPStarterApp::StartUp()
  210. {
  211.     ObeyCommand(cmd_New, nil);        // EXAMPLE, create a new window
  212. }
  213.  
  214. // ---------------------------------------------------------------------------
  215. //        • ObeyCommand
  216. // ---------------------------------------------------------------------------
  217. //    Respond to commands
  218.  
  219. Boolean
  220. CPPStarterApp::ObeyCommand(
  221.     CommandT    inCommand,
  222.     void        *ioParam)
  223. {
  224.     Boolean        cmdHandled = true;
  225.  
  226.     switch (inCommand) {
  227.     
  228.         // Deal with command messages (defined in PP_Messages.h).
  229.         // Any that you don't handle will be passed to LApplication
  230.              
  231.         case cmd_New:
  232.                                         // EXAMPLE, create a new window
  233.             CUnicodeHubWindow    *theWindow;
  234.             theWindow = (CUnicodeHubWindow    *)CUnicodeHubWindow::CreateWindow(rPPob_UnicodeHubWindow, this);    
  235.             UReanimator::LinkListenerToControls( (CUnicodeHubWindow*)theWindow, (LWindow*)theWindow, rRidL_UnicodeHubWindow);
  236.             theWindow->Show();
  237.             break;
  238.  
  239.  
  240.  
  241.         default:
  242.             cmdHandled = LApplication::ObeyCommand(inCommand, ioParam);
  243.             break;
  244.     }
  245.     
  246.     return cmdHandled;
  247. }
  248.  
  249. // ---------------------------------------------------------------------------
  250. //        • FindCommandStatus
  251. // ---------------------------------------------------------------------------
  252. //    This function enables menu commands.
  253. //
  254.  
  255. void
  256. CPPStarterApp::FindCommandStatus(
  257.     CommandT    inCommand,
  258.     Boolean        &outEnabled,
  259.     Boolean        &outUsesMark,
  260.     Char16        &outMark,
  261.     Str255        outName)
  262. {
  263.  
  264.     switch (inCommand) {
  265.     
  266.         // Return menu item status according to command messages.
  267.         // Any that you don't handle will be passed to LApplication
  268.  
  269.         case cmd_New:                    // EXAMPLE
  270.             outEnabled = false;            // disable the New command - currently PP crashes when the 2nd
  271.                                         // window comes up - so disable it it - I don't need 2 windows
  272.             break;
  273.  
  274.         default:
  275.             LApplication::FindCommandStatus(inCommand, outEnabled,
  276.                                                 outUsesMark, outMark, outName);
  277.             break;
  278.     }
  279. }
  280.  
  281.  
  282.  
  283. // ---------------------------------------------------------------------------------
  284. //        • GetMappings
  285. // ---------------------------------------------------------------------------------
  286.  
  287. #if 0
  288. void PrepareForMenuDisplay( StringPtr str );
  289. void PrepareForMenuDisplay( StringPtr str )
  290. {
  291.     int    len=*str;
  292.     
  293.     while(len>0)
  294.     {
  295.         str++;
  296.         if( *str == '\/' || *str == '\\' || *str == ';' )
  297.             *str = '-';
  298.         else if( *str == '(' )
  299.             *str = '[';
  300.         else if( *str == ')' )
  301.             *str = ']';
  302.         else if( *str == '^' || *str == '<' || *str == '!' )
  303.             *str = ' ';
  304.         len--;
  305.     }
  306. }
  307. #endif
  308.  
  309. OSStatus
  310. CPPStarterApp::GetMappings()
  311. {
  312.     OSStatus            status;
  313.     ByteCount            outputLen;
  314.     UnicodeMapping        findMapping = {0};
  315.     short                i=0;
  316.     int                    position;    
  317.  
  318.     /**********************************************************************************************************
  319.      *    TEC SPECIFIC CODE COMMENT
  320.      *
  321.      *    Obtain a list of all the available encoding conversions that we may be able to perform.
  322.      *  This includes, all conversions that the Text Encoding Converter and the Unicode Converter
  323.      *  can perform.  First I call TECCountAvailableTextEncodings to get the number of encodings that
  324.      *    are supported.  I really don't need to do that sinve I've statically allocated the size of the
  325.      *    buffer.  However, we presume that most people will need to make this call to assertain how big
  326.      *    of a buffer to allocate before calling TECGetAvailableTextEncodings.
  327.      **********************************************************************************************************/
  328.     
  329.     status = TECCountAvailableTextEncodings( &mNumMappings);
  330.     ThrowIfError_(status);
  331.     
  332.     status = TECGetAvailableTextEncodings(mAvailableMappings, mNumMappings, &mNumMappings);
  333.     ThrowIfError_(status);
  334.     
  335.     //Manually add the HFS+ Unicode format as TECGetAvailableTextEncodings ignores any Unicode variant and format
  336.     //that it currently doesn't handle.
  337.     mNumMappings++;
  338.     mAvailableMappings[mNumMappings-1]=CreateTextEncoding( kTextEncodingUnicodeV2_0, kUnicodeCanonicalDecompVariant, kTextEncodingDefaultFormat);
  339.  
  340.     /**********************************************************************************************************
  341.      *    END TEC SPECIFIC CODE COMMENTED BLOCK
  342.      **********************************************************************************************************/
  343.  
  344.  
  345. //**** LAME SORT - sort all the encodings returned by the Text Encoding numerical value.
  346.     LDynamicArray    *myMappingsList=new LDynamicArray( (Uint32)( sizeof(mAvailableMappings[0]) ) );
  347.     
  348.     i=0;
  349.     while( i++< mNumMappings )
  350.     {
  351.         TextEncoding    theMapping;
  352.         
  353.         for ( position=1; position<=myMappingsList->GetCount(); position++ )
  354.         {
  355.             myMappingsList->FetchItemAt( position, &theMapping );
  356.             if( theMapping < mAvailableMappings[i-1] )
  357.                 break;
  358.         }
  359.         
  360.         myMappingsList->InsertItemsAt( 1, position, &mAvailableMappings[i-1] );
  361.     }
  362.     
  363.     i=0;
  364.     position =mNumMappings;
  365.     while(i++<mNumMappings)
  366.     {    
  367.         myMappingsList->FetchItemAt( position--, &mAvailableMappings[i-1] );
  368.     }    
  369.     
  370.     delete myMappingsList;
  371. //*** END OF LAME SORT
  372.     
  373.     /**********************************************************************************************************
  374.      *    TEC SPECIFIC CODE COMMENT
  375.      *
  376.      *    In the following loop, we'll get the name for every one of the encodings in our array.  We use the
  377.      *    GetTextEncodingName name API.  Currently, most tables/plugins have defined in them a name in the
  378.      *    kTextEncodingUS_ASCII encoding.  We also check for kTextEncodingMacRoman just in case.
  379.      *    First we get the name for the base encoding, later we proceed to get the name for the variant and 
  380.      *    format if any.  Currently, there are no names for variant and formats entered in the tables.  So, I've
  381.      *    added code that just displays the HEX value for the encoding.
  382.      **********************************************************************************************************/
  383.  
  384.     i=0;
  385.     while(i++<mNumMappings)
  386.     {
  387.         TextEncoding    nameEncoding;
  388.         RegionCode         oActualRegion;
  389.         
  390.         //Get the name of the encoding base
  391.         status = GetTextEncodingName(mAvailableMappings[i-1], kTextEncodingBaseName, verUS, kTextEncodingUS_ASCII,
  392.             kMaxLen, &outputLen,  &oActualRegion,&nameEncoding, (TextPtr) (mAvailableMappingNames[i-1])+1);
  393.  
  394.         if( status == noErr && (  nameEncoding == kTextEncodingMacRoman || nameEncoding == kTextEncodingUS_ASCII))
  395.         {
  396.             Str63    variantFormatName;
  397.             ByteCount    oldOutputLen=outputLen;
  398.             
  399.             *((mAvailableMappingNames[i-1]))=outputLen;
  400.  
  401.             //Get the name of the variant
  402.             status = GetTextEncodingName(mAvailableMappings[i-1], kTextEncodingVariantName, verUS, kTextEncodingUS_ASCII,
  403.             kMaxLen, &outputLen,  &oActualRegion,&nameEncoding, (TextPtr) (variantFormatName)+1);
  404.             if( status == noErr )
  405.             {
  406.                 BlockMove( (variantFormatName)+1, ((mAvailableMappingNames[i-1]))+*((mAvailableMappingNames[i-1]))+1, outputLen );
  407.                 *((mAvailableMappingNames[i-1]))+=outputLen;
  408.             }
  409.                 
  410.             //Get the name of the format
  411.             status = GetTextEncodingName(mAvailableMappings[i-1], kTextEncodingFormatName, verUS, kTextEncodingUS_ASCII,
  412.             kMaxLen, &outputLen,  &oActualRegion,&nameEncoding, (TextPtr) (variantFormatName)+1);
  413.             if( status == noErr )
  414.             {
  415.                 BlockMove( (variantFormatName)+1, ((mAvailableMappingNames[i-1]))+*((mAvailableMappingNames[i-1]))+1, outputLen );
  416.                 *((mAvailableMappingNames[i-1]))+=outputLen;
  417.             }
  418.  
  419.  
  420.             //If the encoding has either a base or a variant but no text was returned from the calls
  421.             //above, then append the encoding number in Hex.
  422.             if( ( ( GetTextEncodingVariant(mAvailableMappings[i-1]) != kTextEncodingDefaultVariant) ||
  423.                 ( GetTextEncodingFormat(mAvailableMappings[i-1]) != kTextEncodingDefaultFormat) ) &&
  424.                 oldOutputLen == *((mAvailableMappingNames[i-1])) )
  425.             {    
  426.                 BlockMove( " 0x", ((mAvailableMappingNames[i-1]))+*((mAvailableMappingNames[i-1]))+1, 3);
  427.                 BufToHex( (unsigned char*)&mAvailableMappings[i-1], (unsigned char*)  ((mAvailableMappingNames[i-1]))+*((mAvailableMappingNames[i-1]))+4,
  428.                     4, outputLen, 0);
  429.                 *((mAvailableMappingNames[i-1]))+=11;
  430.             }
  431.  
  432.             //PrepareForMenuDisplay( mAvailableMappingNames[i-1] );
  433.         }
  434.         else
  435.         {
  436.             *((mAvailableMappingNames[i-1]))=10;
  437.             ::BlockMove( "0x", (((mAvailableMappingNames[i-1]))+1), 2);
  438.             BufToHex( (unsigned char*)&mAvailableMappings[i-1], (unsigned char*) (((mAvailableMappingNames[i-1]))+3),
  439.                 4, outputLen, 0);
  440.             //PrepareForMenuDisplay( mAvailableMappingNames[i-1] );
  441.         }
  442.     }
  443.     /**********************************************************************************************************
  444.      *    END TEC SPECIFIC CODE COMMENTED BLOCK
  445.      **********************************************************************************************************/
  446.     
  447.  
  448. error:    
  449.     return status;
  450. }
  451.  
  452.  
  453. /********************************************************
  454.                 OptionKeyDown
  455. ********************************************************/
  456. Boolean OptionKeyDown(void);
  457. Boolean OptionKeyDown(void)
  458. {
  459.     return ((*(long *)0x178 & 4L) != 0L);
  460. }
  461.  
  462.  
  463. #define PLAYSOUND 0
  464.  
  465. void CPPStarterApp::ShowAboutBox()
  466. {
  467.     //inherited::ShowAboutBox();
  468.     
  469. #if PLAYSOUND
  470.     Handle    theSound=::GetNamedResource('snd ',"\pAboutSound");
  471.     if(theSound)
  472.         ::HNoPurge(theSound);
  473. #endif
  474.  
  475.     UDesktop::Deactivate();        // Alert will swallow Deactivate event
  476.     
  477.     
  478.     DialogPtr dPtr=::GetNewDialog( ALRT_About, nil, (WindowPtr)-1L);
  479.     FailNIL_( dPtr );
  480.     
  481.     ::SetDialogDefaultItem( dPtr, 1);
  482.     ::DrawDialog(dPtr);
  483.     
  484. #if PLAYSOUND
  485.     if(theSound)
  486.     {
  487.         ::SetCursor(*(::GetCursor(watchCursor)));
  488.         ::SndPlay( nil, (SndListResource**)theSound, false);
  489.         ::HPurge(theSound);
  490.         ::ReleaseResource( theSound );
  491.         ::InitCursor();
  492.     }
  493. #endif
  494.     
  495.     short    itemHit=0;
  496.     while(itemHit!=1)
  497.         ::ModalDialog( nil, &itemHit );
  498.         
  499.     if( OptionKeyDown() )
  500.         DebugStr("\pLet's do some debugging");
  501.  
  502.     DisposeDialog( dPtr );
  503.     
  504.     UDesktop::Activate();
  505. }
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512. // *********************************************************************************
  513. //        • CUnicodeTablesPopup
  514. // *********************************************************************************
  515.  
  516.  
  517. CUnicodeTablesPopup*
  518. CUnicodeTablesPopup::CreateUnicodeTablesPopupStream(LStream *inStream)
  519. {
  520.     return ( new CUnicodeTablesPopup( inStream ));
  521. }
  522.  
  523. CUnicodeTablesPopup::CUnicodeTablesPopup(const SPaneInfo &inPaneInfo,
  524.                     MessageT inValueMessage, Int16 inTitleOptions,
  525.                     ResIDT inMENUid, Int16 inTitleWidth,
  526.                     Int16 inPopupVariation, ResIDT inTextTraitsID,
  527.                     Str255 inTitle, OSType inResTypeMENU,
  528.                     Int16 inInitialMenuItem) :
  529.      LStdPopupMenu(inPaneInfo, inValueMessage, inTitleOptions,
  530.                 inMENUid, inTitleWidth, inPopupVariation, inTextTraitsID,
  531.                 inTitle, inResTypeMENU, inInitialMenuItem)
  532. {
  533.     FillMenuWithUnicodeTables();
  534. }
  535.                     
  536. CUnicodeTablesPopup::CUnicodeTablesPopup(const SPaneInfo &inPaneInfo,
  537.                     MessageT inValueMessage, Int32 inMaxValue,
  538.                     ResIDT inTextTraitsID, ControlHandle inMacControlH ) :
  539.             LStdPopupMenu(inPaneInfo, inValueMessage, inMaxValue,
  540.                         inTextTraitsID, inMacControlH)
  541. {
  542.     FillMenuWithUnicodeTables();
  543. }
  544.  
  545.                     
  546. CUnicodeTablesPopup::CUnicodeTablesPopup(LStream *inStream) : LStdPopupMenu( inStream )
  547. {
  548.     FillMenuWithUnicodeTables();
  549. }
  550.  
  551.  
  552.  
  553. CUnicodeTablesPopup::~CUnicodeTablesPopup()
  554. {
  555. }
  556.  
  557. void CUnicodeTablesPopup::FillMenuWithUnicodeTables(void)
  558. {
  559.     MenuHandle    theMenuH=GetMacMenuH();
  560.     
  561.     if(!theMenuH)    return;
  562.     
  563.     
  564.     for( UInt32 i=0; i<gTheApp->mNumMappings; i++)
  565.     {
  566.         ::InsertMenuItem(theMenuH, "\px", i+2);
  567.         ::SetMenuItemText(theMenuH,  i+2, gTheApp->mAvailableMappingNames[i]);
  568.         if( gTheApp->IsUnicode(    gTheApp->mAvailableMappings[i] ) )
  569.             ::SetItemStyle( theMenuH, i+2, bold );
  570.     }
  571.     
  572.     SetMaxValue(gTheApp->mNumMappings+1);
  573. }
  574.  
  575.  
  576. // *********************************************************************************
  577. //        • CFontMenuPopup
  578. // *********************************************************************************
  579.  
  580.  
  581. CFontMenuPopup*
  582. CFontMenuPopup::CreateFontMenuPopupStream(LStream *inStream)
  583. {
  584.     return ( new CFontMenuPopup( inStream ));
  585. }
  586.  
  587. CFontMenuPopup::CFontMenuPopup(const SPaneInfo &inPaneInfo,
  588.                     MessageT inValueMessage, Int16 inTitleOptions,
  589.                     ResIDT inMENUid, Int16 inTitleWidth,
  590.                     Int16 inPopupVariation, ResIDT inTextTraitsID,
  591.                     Str255 inTitle, OSType inResTypeMENU,
  592.                     Int16 inInitialMenuItem) :
  593.      LStdPopupMenu(inPaneInfo, inValueMessage, inTitleOptions,
  594.                 inMENUid, inTitleWidth, inPopupVariation, inTextTraitsID,
  595.                 inTitle, inResTypeMENU, inInitialMenuItem)
  596. {
  597.     FillFontMenu();
  598. }
  599.                     
  600. CFontMenuPopup::CFontMenuPopup(const SPaneInfo &inPaneInfo,
  601.                     MessageT inValueMessage, Int32 inMaxValue,
  602.                     ResIDT inTextTraitsID, ControlHandle inMacControlH ) :
  603.             LStdPopupMenu(inPaneInfo, inValueMessage, inMaxValue,
  604.                         inTextTraitsID, inMacControlH)
  605. {
  606.     FillFontMenu();
  607. }
  608.  
  609.                     
  610. CFontMenuPopup::CFontMenuPopup(LStream *inStream) : LStdPopupMenu( inStream )
  611. {
  612.     FillFontMenu();
  613. }
  614.  
  615.  
  616.  
  617. CFontMenuPopup::~CFontMenuPopup()
  618. {
  619. }
  620.  
  621.  
  622.  
  623. void CFontMenuPopup::FillFontMenu(void)
  624. {
  625.     UInt16        fontsInstalled;
  626.     UInt16        applFontIndex=1;
  627.     MenuHandle    theMenuH=GetMacMenuH();
  628.     
  629.     if(!theMenuH)    return;
  630.         
  631.     ::AppendResMenu( theMenuH, 'FONT');
  632.     fontsInstalled=::CountMItems(theMenuH);
  633.     SetMaxValue(fontsInstalled);
  634.         
  635.     /**********************************************************************************************************
  636.      *    TEC SPECIFIC CODE COMMENT
  637.      *
  638.      *    Here we loop through the font menu and build an array with TextEncodings that match every one
  639.      *    of the Font menu names.  In order to do this we use UpgradeScriptInfoToTextEncoding.  Also, just for
  640.      *    kicks, I check to see if the encoding has a variant or that doesn't correspond to a Mac script code.
  641.      *    If so, I make the item italic and bold for easy identification.
  642.      **********************************************************************************************************/
  643.     for( int i=1; i<=fontsInstalled; i++ )
  644.     {
  645.         Str31            fontName;
  646.         OSStatus        status;
  647.         TextEncoding    theEncoding;
  648.         
  649.         ::GetMenuItemText(theMenuH, i, fontName);
  650.         ::GetFNum(fontName, &mInstalledFonts[i-1] ) ;
  651.         
  652.         if( GetAppFont() == mInstalledFonts[i-1] )
  653.             applFontIndex=i;
  654.         
  655.         status = UpgradeScriptInfoToTextEncoding( kTextScriptDontCare, kTextLanguageDontCare, kTextRegionDontCare, fontName, &theEncoding );
  656.         if( status == noErr )
  657.         {
  658.             if( (theEncoding > smUninterp) || (GetTextEncodingVariant(theEncoding) != kTextEncodingDefaultVariant) )
  659.                 ::SetItemStyle( theMenuH, i, bold+italic);
  660.         }
  661.         else
  662.             ::SetItemStyle( theMenuH, i, outline );
  663.  
  664.     }
  665.     /**********************************************************************************************************
  666.      *    END TEC SPECIFIC CODE COMMENTED BLOCK
  667.      **********************************************************************************************************/
  668.      
  669.     LStdPopupMenu::SetValue( applFontIndex );
  670. }
  671.  
  672. ScriptCode CFontMenuPopup::GetSelectedScript(void)
  673. {
  674.     return ::FontToScript(mInstalledFonts[this->GetValue()-1]);
  675. }
  676.  
  677. void CFontMenuPopup::SetMValue(ScriptCode theCode)
  678. {
  679.     int i;
  680.     MenuHandle    menuH=this->GetMacMenuH();
  681.  
  682.     int maxItems=::CountMItems(menuH);
  683.     for( i=0; i<maxItems; i++ )
  684.         if( theCode ==  ::FontToScript( mInstalledFonts[i] ) )
  685.             break;
  686.  
  687.     LStdPopupMenu::SetValue( i+1 );
  688. }
  689.  
  690. void CFontMenuPopup::SetValueByFont(SInt16    theFont)
  691. {
  692.     int i;
  693.     MenuHandle    menuH=this->GetMacMenuH();
  694.  
  695.     int maxItems=::CountMItems(menuH);
  696.     for( i=0; i<maxItems; i++ )
  697.         if( theFont == mInstalledFonts[i] )
  698.             break;
  699.  
  700.     LStdPopupMenu::SetValue( i+1 );
  701. }
  702.  
  703.  
  704. // *********************************************************************************
  705. //        • CUnicodeHubWindow
  706. // *********************************************************************************
  707.  
  708.  
  709. // ---------------------------------------------------------------------------------
  710. //        • CreateUnicodeHubWindowStream
  711. // ---------------------------------------------------------------------------------
  712. CUnicodeHubWindow*
  713. CUnicodeHubWindow::CreateUnicodeHubWindowStream(LStream *inStream)
  714. {
  715.     return( new CUnicodeHubWindow( inStream ) );
  716. }
  717.  
  718. // ---------------------------------------------------------------------------------
  719. //        • CUnicodeHubWindow
  720. // ---------------------------------------------------------------------------------
  721. void CUnicodeHubWindow::InitUnicodeHubWindow(void)
  722. {
  723.     mFromUnicodeFlags=0;
  724.     mToUnicodeFlags=0;
  725. }
  726.  
  727.  
  728. CUnicodeHubWindow::CUnicodeHubWindow(LStream *inStream) :
  729.     LWindow( inStream )
  730. {
  731.     InitUnicodeHubWindow();
  732. }
  733.  
  734. CUnicodeHubWindow::CUnicodeHubWindow(
  735.         const SWindowInfo    &inWindowInfo) :
  736.     LWindow( inWindowInfo )
  737. {
  738.     InitUnicodeHubWindow();
  739. }
  740.  
  741. CUnicodeHubWindow::CUnicodeHubWindow(
  742.         ResIDT                inWINDid,
  743.         Uint32                inAttributes,
  744.         LCommander            *inSuperCommander) :
  745.     LWindow( inWINDid, inAttributes, inSuperCommander )
  746. {
  747.     InitUnicodeHubWindow();
  748. }
  749.  
  750.  
  751. // ---------------------------------------------------------------------------------
  752. //        • ListenToMessage
  753. // ---------------------------------------------------------------------------------
  754.  
  755. void
  756. CUnicodeHubWindow::ListenToMessage(
  757.     MessageT    inMessage,
  758.     void        *ioParam )
  759. {
  760. #pragma unused(ioParam)
  761.     
  762.     //Check if one of the check boxes was clicked on.  If so, toggle the bits in the
  763.     //appropriate control flag.
  764.     
  765.     //If the convert buttons are clicked on, the ConvertButtonHit method is called
  766.     
  767.     //If a popup menu is selected, we don't do anything about it
  768.         
  769.     if( inMessage >= kFirstFromUnicodeCheck && inMessage <=    kLastFromUnicodeCheck )
  770.     {
  771.             mFromUnicodeFlags ^= ( 1L << (inMessage - kFirstFromUnicodeCheck) );
  772.     }
  773.     else if( inMessage >= kFirstToUnicodeCheck && inMessage <=    kLastToUnicodeCheck )
  774.     {
  775.             mToUnicodeFlags ^= ( 1L << (inMessage - kFirstToUnicodeCheck) );
  776.     }        
  777.     else if( inMessage == kLeftConvertButton || inMessage == kRightConvertButton )
  778.         ConvertButtonHit( inMessage );
  779.     else if( inMessage == kLeftDisplayHex || inMessage == kRightDisplayHex )
  780.         ConvertTextToHex( inMessage );
  781.     else if( inMessage == kFontMenuPopup )
  782.     {
  783.         
  784.         CStyleText    *fromText =    (CStyleText*)FindPaneByID( kLeftText );
  785.         CStyleText    *toText =     (CStyleText*)FindPaneByID( kRightText );
  786.         CStyleText    *targetText;
  787.         
  788.         
  789.         Str31            fontName;
  790.         CFontMenuPopup*    scriptsPopup=((CFontMenuPopup*)FindPaneByID ( kFontMenuPopup ));
  791.         ScriptCode        theScript;
  792.         TextStyle         newStyle;
  793.  
  794.         theScript=scriptsPopup->GetSelectedScript();
  795.         ::KeyScript( theScript );
  796.         
  797.  
  798.         ::GetMenuItemText( scriptsPopup->GetMacMenuH(), scriptsPopup->GetValue(), fontName );
  799.         ::GetFNum(fontName, &newStyle.tsFont ) ;
  800.  
  801.         newStyle.tsSize = ::GetScriptVariable( theScript, smScriptPrefFondSize );
  802.         
  803.         if( fromText->IsTarget() )
  804.             targetText=fromText;
  805.         else if( toText->IsTarget() )
  806.             targetText=toText;
  807.         else
  808.             targetText=NULL;
  809.         
  810.         if( targetText )    
  811.         {
  812.             targetText->FocusDraw();
  813.             ::TESetStyle( doFont|doSize, &newStyle, true, targetText->GetMacTEH() );
  814.             targetText->mCurKeyScript=theScript;
  815.             ::SetScriptManagerVariable( smKeyScript, theScript );
  816.         }
  817.         
  818.     }
  819.  
  820. }
  821.  
  822. void
  823. CUnicodeHubWindow::ConvertButtonHit( MessageT    inMessage )
  824. {
  825.     LTextEdit        *fromText, *toText;
  826.     LStdCheckBox    *toCheckBox;
  827.     UInt32            fromEncoding, toEncoding;
  828.     Handle            theTextToConvert;
  829.     Handle            theConvertedText;
  830.     UInt32            sourceLen, inputRead, outputLen;
  831.     OSStatus         status;
  832.     Str255            theString;
  833.     ByteCount        convertedTextLen;
  834.     Boolean            wantHexOutput;
  835.     
  836.  
  837.     //Get the from and to text edit panel pointers as well as the value of the
  838.     //from and to encoding panel popup item selected
  839.     if ( inMessage == kLeftConvertButton )
  840.     {
  841.         fromText =    (LTextEdit*)FindPaneByID ( kLeftText );
  842.         toText =     (LTextEdit*)FindPaneByID ( kRightText );
  843.         
  844.         toCheckBox = (LStdCheckBox*)FindPaneByID ( kRightDisplayHex );
  845.         
  846.         fromEncoding =    ((CUnicodeTablesPopup*)FindPaneByID ( kLeftEncodingPopup ))->GetValue() - 1;
  847.         toEncoding =    ((CUnicodeTablesPopup*)FindPaneByID ( kRightEncodingPopup ))->GetValue() - 1;
  848.         
  849.         wantHexOutput = toCheckBox->GetValue();
  850.     }
  851.     else
  852.     {
  853.         toText =    (LTextEdit*)FindPaneByID ( kLeftText );
  854.         fromText =     (LTextEdit*)FindPaneByID ( kRightText );
  855.         
  856.         toCheckBox = (LStdCheckBox*)FindPaneByID ( kLeftDisplayHex );
  857.  
  858.         toEncoding =    ((CUnicodeTablesPopup*)FindPaneByID ( kLeftEncodingPopup ))->GetValue() - 1;
  859.         fromEncoding =    ((CUnicodeTablesPopup*)FindPaneByID ( kRightEncodingPopup ))->GetValue() - 1;
  860.         
  861.         wantHexOutput = toCheckBox->GetValue();
  862.     }
  863.     
  864.     //Get the handle to the from text and its length
  865.     theTextToConvert = fromText->GetTextHandle();
  866.     sourceLen = ::GetHandleSize(theTextToConvert);
  867.     
  868.     TEStyleHandle        theStyle=::TEGetStyleHandle( fromText->GetMacTEH() );
  869.     TextEncodingRunHdl    theRuns=0;
  870.     ByteCount**            theOffsets=0;
  871.         
  872.  
  873.     /**********************************************************************************************************
  874.      *    TEC SPECIFIC CODE COMMENT
  875.      *
  876.      *    I make my output buffers 3 times the size of the input buffers.  The reason being is that I handle
  877.      *    every single encoding out there.  There are some that require buffers larger than this depending on
  878.      *    the text that is being passed.  You don't need to make buffers so large.  You can always convert and
  879.      *    if you get kTECOutputBufferFullStatus, you need to increase you buffer size and continue the conversion
  880.      *    where it left of.  The convert code in Convert.cp shows you this.  However, by having such a large buffer
  881.      *    you should convert on the first try.  Look specifically in CPPStarterApp::ConvertFromMulti.
  882.      **********************************************************************************************************/
  883. #define SIZEOFOUTBUF    3L    
  884.     /**********************************************************************************************************
  885.      *    END TEC SPECIFIC CODE COMMENTED BLOCK
  886.      **********************************************************************************************************/
  887.  
  888.     //Create the output handle to be at SIZEOFOUTBUF times the size of the source length
  889.     theConvertedText = NewHandle( sourceLen * SIZEOFOUTBUF );
  890.     FailNIL_(theConvertedText);
  891.  
  892.     //Call the convert function
  893.     if( fromEncoding != 0 )
  894.     {
  895.          status = gTheApp->DoConvert(    theTextToConvert, sourceLen, fromEncoding,
  896.                     theConvertedText, inputRead, outputLen, convertedTextLen, toEncoding,
  897.                     theRuns, mFromUnicodeFlags, mToUnicodeFlags, wantHexOutput );
  898.         
  899.         //If the output is a single encoding, then figure out if it is a mac encoding, if so, add a run with it.
  900.         if( theRuns == 0 ) 
  901.         {
  902.             theRuns=(TextEncodingRunHdl)NewHandle(sizeof(TextEncodingRun) );
  903.             if( theRuns )
  904.             {
  905.                 ::HLock((Handle)theRuns);
  906.                 (**theRuns).textEncoding=gTheApp->mAvailableMappings[ toEncoding-1 ];
  907.                 (**theRuns).offset=0;
  908.             }
  909.         }
  910.     }
  911.     else
  912.     {
  913.         TextEncoding    unicodeEncoding;
  914.         
  915.         //Make sure that the check box is set since the output that we are going to
  916.         //get is in HEX
  917.         toCheckBox->SetValue(1);
  918.         
  919.         gTheApp->ResolveConversionParams(    NULL,      NULL,
  920.                                             toEncoding, &unicodeEncoding, NULL );
  921.         
  922.         if( gTheApp->IsUnicode( unicodeEncoding ) )        
  923.             status = gTheApp->ConvertFromMulti( unicodeEncoding, theTextToConvert, theStyle, sourceLen, theConvertedText,
  924.                     inputRead, outputLen, convertedTextLen, theOffsets, mToUnicodeFlags);
  925.         else
  926.         {
  927.             ::ParamText("\pStyled Text can only be converter to Unicode", "\p", "\p", "\p");
  928.             ::Alert(kSimpleAlert, NULL);
  929.             outputLen=0;
  930.             inputRead=0;
  931.             convertedTextLen=0;
  932.             status=paramErr;
  933.             ::SetHandleSize(theConvertedText, 0);
  934.         }
  935.     }
  936.     
  937.     //Reset the handle size of the converted text to as many bytes as were able to be converted
  938.     //and set the value of the toText LTextEdit to the converted string.
  939.     ::SetHandleSize(theConvertedText, convertedTextLen);
  940.     toText->SetTextHandle( theConvertedText );
  941.     if( theRuns )
  942.     {
  943.         TEHandle    toTextHdl=toText->GetMacTEH();
  944.         
  945.         ItemCount    noItems=GetHandleSize((Handle)theRuns)/sizeof(TextEncodingRun);
  946.         
  947.         toText->FocusDraw();
  948.  
  949.         ::HLock( (Handle)theRuns );
  950.         for(int i=0; i<noItems; i++)
  951.         {
  952.             TextStyle     newStyle;
  953.             ScriptCode    theScript;
  954.             UInt16        styleMode;
  955.             OSStatus    status2;
  956.             
  957.     /**********************************************************************************************************
  958.      *    TEC SPECIFIC CODE COMMENT
  959.      *
  960.      *    After I use ConvertUnicodeToTextRun, I examine each of the encoding runs to determine what Font to use
  961.      *    in order to display the string.  RevertTextEncodingToScriptInfo is used for this purpose.  If it 
  962.      *    returns a font name, then I use that one.  When it does, it means that it picked up on an encoding
  963.      *    run that has symbol, dingbats, vt100, or an encoding from a font/text encoding variant.  If it doesn't 
  964.      *    return a font name, I just just the preferred App font for the script.
  965.      **********************************************************************************************************/
  966.  
  967.             status2=RevertTextEncodingToScriptInfo( (*theRuns)[i].textEncoding, &theScript, NULL, theString );
  968.             if( status2 == noErr )
  969.             {
  970.                 if( *theString == 0 )
  971.                     newStyle.tsFont = ::GetScriptVariable( theScript, smScriptAppFond );
  972.                 else    
  973.                     GetFNum( theString, &newStyle.tsFont);
  974.                 newStyle.tsSize = ::GetScriptVariable( theScript, smScriptPrefFondSize );
  975.                 styleMode=doFont|doSize;
  976.             }
  977.             else
  978.             {
  979.                 theScript= ::GetScriptManagerVariable( smSysScript );
  980.                 newStyle.tsFont = ::GetScriptVariable( theScript, smScriptAppFond );
  981.                 newStyle.tsSize = ::GetScriptVariable( theScript, smScriptPrefFondSize );
  982.                 newStyle.tsFace = bold;
  983.                 styleMode=doFont|doSize|doFace;
  984.             }
  985.  
  986.             ByteCount endOffset= (i==noItems-1) ? -1 : (*theRuns)[i+1].offset;
  987.             ::TESetSelect((*theRuns)[i].offset, endOffset, toTextHdl);
  988.             ::TESetStyle(styleMode, &newStyle, true, toTextHdl );
  989.  
  990.     /**********************************************************************************************************
  991.      *    END TEC SPECIFIC CODE COMMENTED BLOCK
  992.      **********************************************************************************************************/
  993.  
  994.         }
  995.         
  996.         //Set the selection to the end of the text
  997.         ::TESetSelect(-1, -1, toTextHdl);
  998.         
  999.         ::HUnlock( (Handle)theRuns );
  1000.     }
  1001.     else if( theOffsets )
  1002.     {
  1003.         TEHandle    toTextHdl=toText->GetMacTEH();
  1004.         ItemCount    noItems=GetHandleSize((Handle)theOffsets)/sizeof(ByteCount);
  1005.         
  1006.         toText->FocusDraw();
  1007.  
  1008.         ::HLock( (Handle)theOffsets );
  1009.         for(int i=0; i<noItems; i++)
  1010.         {
  1011.             TextStyle    newStyle;
  1012.                         
  1013.             newStyle.tsColor.green=0;
  1014.             newStyle.tsColor.red=(i%2)==1 ?  0xFFFFFFFF : 0;
  1015.             newStyle.tsColor.blue =(i%2)==0 ? 0xFFFFFFFF: 0;
  1016.             
  1017.             
  1018.             ByteCount endOffset= (i==noItems-1) ? -1 : (*theOffsets)[i+1];
  1019.             ::TESetSelect((*theOffsets)[i], endOffset, toTextHdl);
  1020.             ::TESetStyle( doColor, &newStyle, true, toTextHdl );
  1021.         }
  1022.         ::HUnlock( (Handle)theOffsets );        
  1023.         ::DisposeHandle( (Handle)theOffsets );
  1024.         
  1025.     }
  1026.     
  1027.     //Dispose of our converted text handle
  1028.     ::DisposeHandle(theConvertedText);
  1029.  
  1030.     // convert inputRead to string
  1031.     ::NumToString(inputRead, theString);
  1032.     // display string in error pane
  1033.     SetDescriptorForPaneID( kInputReadCaption, theString);
  1034.  
  1035.     // convert outputLen to string
  1036.     ::NumToString(outputLen, theString);
  1037.     // display string in error pane
  1038.     SetDescriptorForPaneID( kOutputLenCaption, theString);
  1039.  
  1040.     // convert error to string
  1041.     if( status >= kUnicodeFirstError && status <= kIllegalHexString )
  1042.         BlockMove( UnicodeErrors[status-kUnicodeFirstError],theString, *(UnicodeErrors[status-kUnicodeFirstError])+1 );
  1043.     else
  1044.         ::NumToString(status, theString);
  1045.     // display string in error pane
  1046.     SetDescriptorForPaneID( kErrorCaption, theString);
  1047.  
  1048. }
  1049.  
  1050. void
  1051. CUnicodeHubWindow::ConvertTextToHex( MessageT    inMessage )
  1052. {
  1053.     LTextEdit        *fromText;
  1054.     UInt32            toValue;
  1055.     Handle            theTextToConvert;
  1056.     Handle            theConvertedText;
  1057.     ByteCount            sourceLen,convertedTextLen;
  1058.     //OSStatus         status;
  1059.     //Str255            theString;
  1060.     Boolean            convertOK=true;
  1061.     
  1062.     //Get the from and to text edit panel pointers as well as the value of the
  1063.     //from and to encoding panel popup item selected
  1064.     if ( inMessage == kLeftDisplayHex )
  1065.     {
  1066.         fromText =    (LTextEdit*)FindPaneByID ( kLeftText );
  1067.         toValue =    ((LStdCheckBox*)FindPaneByID ( kLeftDisplayHex ))->GetValue();
  1068.     }
  1069.     else
  1070.     {
  1071.         fromText =    (LTextEdit*)FindPaneByID ( kRightText );
  1072.         toValue =    ((LStdCheckBox*)FindPaneByID ( kRightDisplayHex ))->GetValue();
  1073.     }
  1074.     
  1075.     //Get the handle to the from text and its length
  1076.     theTextToConvert = fromText->GetTextHandle();
  1077.     sourceLen = ::GetHandleSize(theTextToConvert);
  1078.     
  1079.     //Create the output handle to be at 3 times the size of the source length
  1080.     theConvertedText = NewHandle( sourceLen * 3L );
  1081.     FailNIL_(theConvertedText);
  1082.  
  1083.     ::HLock( theTextToConvert );
  1084.     ::HLock( theConvertedText );
  1085.     
  1086.     if( toValue )
  1087.         BufToHex( (StringPtr)*theTextToConvert, (StringPtr)*theConvertedText, sourceLen, convertedTextLen, 2 );
  1088.     else
  1089.         convertOK=FromHexToString( (StringPtr)*theTextToConvert, sourceLen, (StringPtr)*theConvertedText, convertedTextLen);
  1090.         
  1091.     
  1092.     ::HUnlock( theTextToConvert );
  1093.     ::HUnlock( theConvertedText );
  1094.  
  1095.     if( convertOK )
  1096.     {
  1097.         ::SetHandleSize(theConvertedText, convertedTextLen);
  1098.         fromText->SetTextHandle( theConvertedText );
  1099.     }
  1100.     
  1101.     //Dispose of our converted text handle
  1102.     ::DisposeHandle(theConvertedText);
  1103. }
  1104.  
  1105.  
  1106.  
  1107. // *********************************************************************************
  1108. //        • String To Hex and back   Utilities
  1109. // *********************************************************************************
  1110.  
  1111.  
  1112. // ---------------------------------------------------------------------------------
  1113. //        • BufToHex
  1114. // ---------------------------------------------------------------------------------
  1115. void BufToHex( const unsigned char* src, unsigned char* dest, ByteCount    srcLen, ByteCount &destLen, UInt8    clumpSize)
  1116. {
  1117.     unsigned char    *hex=(unsigned char*)"0123456789ABCDEF";
  1118.     UInt8            tempClumpSize = clumpSize;
  1119.  
  1120.     destLen=0;
  1121.     while(srcLen--)
  1122.     {        
  1123.         *dest++ = *( hex + ((*src&0xF0)>>4) );
  1124.         *dest++ = *( hex + ( *src&0x0F ) );
  1125.         destLen+=2;
  1126.         
  1127.         if( clumpSize != 0 )
  1128.         {
  1129.             if( --tempClumpSize == 0 )
  1130.             {
  1131.                 *dest++ = ' ';
  1132.                 tempClumpSize = clumpSize;
  1133.                 destLen++;
  1134.             }
  1135.         }
  1136.         
  1137.         src++;
  1138.     }
  1139. }
  1140.  
  1141. // ---------------------------------------------------------------------------------
  1142. //        • FromHexToString
  1143. // ---------------------------------------------------------------------------------
  1144.  
  1145. #define TOUPPER(c)    ( (c>'Z') ? c & 0xDF : c )
  1146. #define ISHEX(c) ( (c>='0' && c<='9') || ( c>='A' && c<='F') )
  1147. #define HEXTONUM(c)    ( (c>'9') ? c-'A'+10 : c-'0' )
  1148.  
  1149. Boolean FromHexToString( unsigned char* str, ByteCount length, unsigned char*    dest, ByteCount &actualLen)
  1150. {
  1151.     unsigned char    high, low;
  1152.     
  1153.     actualLen = 0;
  1154.     
  1155.     while( length )
  1156.     {        
  1157.         //skip any empty spaces
  1158.         while( length && *str==' '){    str++; length--; }
  1159.         if(!length)    break;
  1160.  
  1161.         low = 0;    //initialize low to point to an impossible character
  1162.         
  1163.         //get the high byte
  1164.         high=TOUPPER(*str);
  1165.         length--;
  1166.         str++;
  1167.         
  1168.         //skip any empty spaces
  1169.         while( length && *str==' '){    str++; length--; }
  1170.         if(!length)    break;
  1171.         
  1172.         //get the low byte
  1173.         low=TOUPPER(*str);
  1174.         length--;
  1175.         str++;
  1176.         
  1177.         //convert our hex number if possible
  1178.         if( ISHEX(high) && ISHEX(low) )
  1179.         {
  1180.             *dest++=(HEXTONUM(high)<<4) | HEXTONUM(low);
  1181.             actualLen++;
  1182.         }
  1183.         else
  1184.             return false;
  1185.     }        
  1186.     
  1187.     return (low!=0);    //if low==0 then we have an incomplete hex string
  1188. }
  1189.  
  1190.  
  1191. //----------------------------------
  1192. // ---------------------------------------------------------------------------
  1193. //        • CStyleText
  1194. // ---------------------------------------------------------------------------
  1195. //    Construct from input parameters
  1196.  
  1197. CStyleText::CStyleText(
  1198.     const SPaneInfo    &inPaneInfo,
  1199.     const SViewInfo    &inViewInfo,
  1200.     Uint16            inTextAttributes,
  1201.     ResIDT            inTextTraitsID) 
  1202. {
  1203.     LView(inPaneInfo, inViewInfo);
  1204.     mTextAttributes = inTextAttributes;
  1205.     InitStyleTextEdit(inTextTraitsID);
  1206.     AlignTextEditRects();
  1207. }
  1208.  
  1209.  
  1210. // ---------------------------------------------------------------------------------
  1211. //        • CreateStyleTextEditStream
  1212. // ---------------------------------------------------------------------------------
  1213. CStyleText*
  1214. CStyleText::CreateStyleTextEditStream(LStream *inStream)
  1215. {
  1216.     return( new CStyleText( inStream ) );
  1217. }
  1218.  
  1219. // ---------------------------------------------------------------------------
  1220. //        • CStyleText(LStream*)
  1221. // ---------------------------------------------------------------------------
  1222. //    Contruct an TextEdit from the data in a Stream
  1223.  
  1224. CStyleText::CStyleText(
  1225.     LStream    *inStream)
  1226.         : LTextEdit(inStream)
  1227. {
  1228.  
  1229.     Handle    initialTextH = GetTextHandle();
  1230.     HandToHand( &initialTextH );
  1231.     
  1232.     ::TEDispose( mTextEditH );
  1233.     InitStyleTextEdit(mTextTraitsID);
  1234.     AlignTextEditRects();
  1235.     
  1236.     if (initialTextH != nil) {
  1237.         SetTextHandle(initialTextH);
  1238.         ::ReleaseResource(initialTextH);
  1239.         ::TESetSelect(0, 0, mTextEditH);
  1240.     }
  1241. }
  1242.  
  1243. // ---------------------------------------------------------------------------
  1244. //        • InitStyleTextEdit
  1245. // ---------------------------------------------------------------------------
  1246. //    Initialize member variables of a TextEdit to default values - Also overrides
  1247. //    the parent's method and creates a styled text edit record as opposed to
  1248. //    a mono-styled text
  1249.  
  1250. void
  1251. CStyleText::InitStyleTextEdit(
  1252.     ResIDT    inTextTraitsID)
  1253. {
  1254.     
  1255.     Rect    viewRect = {0, 0, 0, 0};
  1256.     mTextEditH = ::TEStyleNew(&viewRect, &viewRect);        //<JAG>
  1257.     
  1258.     mCurKeyScript = ::GetScriptManagerVariable(smKeyScript);
  1259.  
  1260.     SetTextTraitsID(inTextTraitsID);
  1261.     
  1262.         // If word wrap is on, then the Image width is always the
  1263.         // same as the Frame width, which forces text to wrap to
  1264.         // the Frame.
  1265.         
  1266.         // If the Image width is zero (or negative), the user
  1267.         // probably forgot to set it. To accommodate this error,
  1268.         // we set the Image width to the Frame width. However, the
  1269.         // Image will not change if the Frame resizes.
  1270.     
  1271.     if ((mTextAttributes & textAttr_WordWrap) ||
  1272.         (mImageSize.width <= 0)) {
  1273.         mImageSize.width = mFrameSize.width;
  1274.     }
  1275. }
  1276.  
  1277. Boolean
  1278. CStyleText::FocusDraw()
  1279. {
  1280.     
  1281.     Boolean    focused = LView::FocusDraw();
  1282.     if (focused) {
  1283.         StColorPenState::Normalize();
  1284.     }
  1285.     
  1286.     return focused;
  1287. }
  1288.  
  1289.  
  1290. // ---------------------------------------------------------------------------
  1291. //        SpendTime
  1292. // ---------------------------------------------------------------------------
  1293. //    Here we make sure that the keyScript and the sysKeyScript are in sync
  1294. //    If they aren't we set the keyScript to be that of the sysKeyScript.
  1295. //    We don't do the later if there is a selection that goes accross multiple 
  1296. //    runs
  1297. void
  1298. CStyleText::SpendTime(const EventRecord &inMacEvent)
  1299. {
  1300.         
  1301.     LTextEdit::SpendTime( inMacEvent );
  1302.     
  1303.     if( mCurKeyScript != ::GetScriptManagerVariable(smKeyScript) )
  1304.     {
  1305.     
  1306.         UInt16        noStyles=1;
  1307.         
  1308.         if( (**mTextEditH).selStart != (**mTextEditH).selEnd )
  1309.         {
  1310.             StScrpHandle    sTE=TEGetStyleScrapHandle(mTextEditH);
  1311.             
  1312.             noStyles=(**sTE).scrpNStyles;
  1313.             
  1314.             DisposeHandle((Handle)sTE);
  1315.         }
  1316.             
  1317.         if( noStyles == 1 )
  1318.         {
  1319.             mCurKeyScript = ::GetScriptManagerVariable(smKeyScript);
  1320.             
  1321.             CFontMenuPopup*    fontMenuPopup=(CFontMenuPopup*)(GetDefaultView()->FindPaneByID ( kFontMenuPopup ));
  1322.             if( fontMenuPopup )
  1323.                 fontMenuPopup->SetMValue( (ScriptCode) mCurKeyScript );
  1324.         }
  1325.     }
  1326. }
  1327.  
  1328.  
  1329. // ---------------------------------------------------------------------------
  1330. //        ObeyCommand
  1331. // ---------------------------------------------------------------------------
  1332. //    Here we handle Styled Text copy and paste which the original PP methods dont
  1333. //    handle or that have bus in them.
  1334. Boolean
  1335. CStyleText::ObeyCommand(
  1336.     CommandT    inCommand,
  1337.     void*        ioParam)
  1338. {
  1339.     Boolean        cmdHandled = true;
  1340.     
  1341.     switch (inCommand) {
  1342.         Handle    teScrap=TEScrapHandle();
  1343.             
  1344.         case cmd_Cut:
  1345.             ::ZeroScrap();            //Bug in powerplant.  ZeroScrap should be called before TECut
  1346.             ::TECut(mTextEditH);
  1347.             ::TEToScrap();
  1348.             AdjustImageToText();
  1349.             UserChangedText();
  1350.             break;
  1351.             
  1352.         case cmd_Copy:
  1353.             ::ZeroScrap();            //Bug in powerplant.  ZeroScrap should be called before TECopy
  1354.             ::TECopy(mTextEditH);
  1355.             ::TEToScrap();
  1356.             break;
  1357.  
  1358.         case cmd_Paste:
  1359.             ::TEFromScrap();
  1360.             ::TEStylePaste(mTextEditH);
  1361.             AdjustImageToText();
  1362.             UserChangedText();
  1363.             break;
  1364.             
  1365.             
  1366.         default:
  1367.             cmdHandled = LTextEdit::ObeyCommand(inCommand, ioParam);
  1368.             break;
  1369.     }
  1370.     
  1371.     return cmdHandled;
  1372. }
  1373.  
  1374. // ---------------------------------------------------------------------------
  1375. //        Click
  1376. // ---------------------------------------------------------------------------
  1377. //    Here we make a font selection depending where in the text the user click.
  1378. //    We want our font menu to have the correct font displayed.  If the click 
  1379. //    yields a selection that spreads accross multiple style runs, then we
  1380. //    do not change the font selection.  We should probably have a menu item
  1381. //    in the font menu that is blank to indicate to the user that there isn't 
  1382. //    one possible selection to be made.
  1383. void
  1384. CStyleText::Click( SMouseDownEvent        &inMouseDown) 
  1385. {
  1386.     LTextEdit::Click( inMouseDown );
  1387.     TextStyle            theStyle;
  1388.     
  1389.     
  1390.     CFontMenuPopup*    fontMenuPopup=(CFontMenuPopup*)(GetDefaultView()->FindPaneByID ( kFontMenuPopup ));
  1391.     
  1392.     SInt16        lineHeight;
  1393.     SInt16        ascend;
  1394.     UInt16        offset;
  1395.     
  1396.     UInt16        noStyles=1;
  1397.     
  1398.     if( (**mTextEditH).selStart != (**mTextEditH).selEnd )
  1399.     {
  1400.         StScrpHandle    sTE=TEGetStyleScrapHandle(mTextEditH);
  1401.         
  1402.         noStyles=(**sTE).scrpNStyles;
  1403.         
  1404.         DisposeHandle((Handle)sTE);
  1405.     }
  1406.         
  1407.     if( noStyles == 1 )
  1408.     {
  1409.         offset=::TEGetOffset( inMouseDown.whereLocal, mTextEditH );
  1410.         ::TEGetStyle( offset, &theStyle, &lineHeight, &ascend, mTextEditH);
  1411.         
  1412.         if( theStyle.tsFont == applFont )
  1413.             theStyle.tsFont = GetAppFont();
  1414.         if( fontMenuPopup->mInstalledFonts[fontMenuPopup->GetValue()-1] != theStyle.tsFont )
  1415.         {
  1416.             fontMenuPopup->SetValueByFont( theStyle.tsFont );
  1417.             mCurKeyScript=::FontToScript(theStyle.tsFont);
  1418.             ::SetScriptManagerVariable(smKeyScript, mCurKeyScript);
  1419.  
  1420.         }
  1421.     }
  1422. }
  1423.     
  1424.  
  1425.  
  1426. // ---------------------------------------------------------------------------
  1427. //        BeTarget
  1428. // ---------------------------------------------------------------------------
  1429. //    Here we make sure that the keyScript and the current font selected for the
  1430. //    text edit field being targeted is the same
  1431. void
  1432. CStyleText::BeTarget()
  1433. {
  1434.     CFontMenuPopup*    fontMenuPopup=(CFontMenuPopup*)(GetDefaultView()->FindPaneByID ( kFontMenuPopup ));
  1435.     if( fontMenuPopup )
  1436.     {
  1437.         ScriptCode    theScript=(fontMenuPopup)->GetSelectedScript();
  1438.         
  1439.         if( theScript != mCurKeyScript )
  1440.         {
  1441.             fontMenuPopup->SetMValue( (ScriptCode) mCurKeyScript );
  1442.         }
  1443.     }
  1444.  
  1445.     LTextEdit::BeTarget();
  1446. }
  1447.