home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 April: Mac OS SDK / Dev.CD Apr 00 SDK1.toast / Development Kits / Mac OS / Text Encoding Converter 1.5 / Sample Code / UnicodeHub / UnicodeHub.cp < prev    next >
Encoding:
Text File  |  1999-02-09  |  43.0 KB  |  1,483 lines  |  [TEXT/CWIE]

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