home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / Composer / CEditView.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  140.2 KB  |  4,981 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "CEditView.h"
  20. #include "CHTMLView.h"            // ::SafeSetCursor
  21.  
  22. #include "resgui.h"
  23. #include "mprint.h"
  24. #include "meditor.h"            // HandleModalDialog
  25. #include "meditdlg.h"            // CEditDialog
  26. #include "CHTMLClickrecord.h"
  27. #include "CBrowserContext.h"    // load url
  28. #include "CPaneEnabler.h"        // CPaneEnabler::UpdatePanes()
  29. #include "CPatternButtonPopup.h"
  30. #include "CSpellChecker.h"        // cmd_CheckSpelling
  31. #include "CComposerDragTask.h"
  32. #include "CColorPopup.h"
  33. #include "CFontMenuAttachment.h"    // CFontMenuPopup
  34.  
  35. #include "TSMProxy.h"
  36. #include "LTSMSupport.h"
  37.  
  38. #include "macgui.h"                // UGraphics::MakeRGBColor
  39. #include "ufilemgr.h"            // CFileMgr::GetURLFromFileSpec
  40. #include "uerrmgr.h"            // ErrorManager::PlainAlert
  41. #include "edt.h"
  42. #include "net.h"                // FO_CACHE_AND_PRESENT
  43. #include "proto.h"                // XP_IsContextBusy()
  44. #include "CURLDispatcher.h"        // CURLDispatcher::DispatchURL
  45. #include "pa_tags.h"            // tags such as P_HEADER_5
  46. #include "ulaunch.h"            // StartDocInApp
  47. #include "shist.h"                // SHIST_GetCurrent
  48. #include "prefapi.h"            // PREF_GetBoolPref, PREF_GetIntPref
  49. #include "CPrefsDialog.h"    // CPrefsDialog::EditPrefs and related
  50. #include "CRecentEditMenuAttachment.h"    // cmd for FindCommandStatus
  51.  
  52. #include "FSpCompat.h"
  53. #include "MoreFilesExtras.h"
  54.  
  55. #include "uintl.h"
  56.  
  57. // get string constants
  58. #define WANT_ENUM_STRING_IDS
  59. #include "allxpstr.h"
  60. #undef WANT_ENUM_STRING_IDS
  61.  
  62. #include <LGAPopup.h>
  63.  
  64. #ifdef PROFILE
  65. #include <profiler.h>
  66. #endif
  67.  
  68. #include <Script.h>
  69.  
  70.  
  71. #define FLUSH_JAPANESE_TEXT    if ( mProxy ) mProxy->FlushInput();
  72.  
  73. #pragma mark -- local --
  74. // ** LOCAL functions
  75. static Boolean 
  76. sect_rect_long(SPoint32 frameLocation, SDimension16 frameSize, SPoint32 *updateUL,  SPoint32 *updateLR)
  77. {
  78.     if (updateUL->h >= frameLocation.h + frameSize.width ||            //    are we overlapping at all?
  79.         updateLR->h <= frameLocation.h ||
  80.         updateUL->v >= frameLocation.v + frameSize.height ||
  81.         updateLR->v <= frameLocation.v)
  82.     {
  83.         *updateLR = *updateUL;                                        //    no,
  84.         return false;                                                //    return.
  85.     }
  86.     
  87.     if ( updateUL->h < frameLocation.h )
  88.         updateUL->h = frameLocation.h;
  89.     if ( updateLR->h > frameLocation.h + frameSize.width )
  90.         updateLR->h = frameLocation.h + frameSize.width;
  91.     if ( updateUL->v < frameLocation.v )
  92.         updateUL->v = frameLocation.v;
  93.     if ( updateLR->v > frameLocation.v + frameSize.height )
  94.         updateLR->v = frameLocation.v + frameSize.height;
  95.     
  96.     return (updateLR->h != updateUL->h && updateLR->v != updateUL->v );        // is this test redundant; do we always return true??
  97. }
  98.  
  99.  
  100. // utility function for menu string/command swapping
  101. // if "outName" is NULL it will actually set the menu text
  102. // otherwise the menu item's text will be returned in "outName"
  103. static
  104. void SetMenuCommandAndString( CommandT oldCommand, CommandT newCommand, 
  105.                                 ResIDT newStringResourceID, ResIDT newStringIndex, 
  106.                                 Str255 outName )
  107. {
  108.     ResIDT        theMenuID;
  109.     MenuHandle    theMenuH;
  110.     Int16        theItem;
  111.     LMenuBar    *theMenuBar = LMenuBar::GetCurrentMenuBar();
  112.     
  113.     if ( theMenuBar == NULL )
  114.         return;        // something must be pretty screwed up!
  115.     
  116.     // Locate oldCommand
  117.     theMenuBar->FindMenuItem( oldCommand, theMenuID, theMenuH, theItem );
  118.     if ( theItem != 0 )
  119.     {                // Replace with newCommand
  120.         LMenu    *theMenu = theMenuBar->FetchMenu( theMenuID );
  121.         if ( newCommand )
  122.             theMenu->SetCommand( theItem, newCommand );
  123.         
  124.         if ( newStringResourceID )
  125.         {
  126.             Str255    newMenuString;
  127.             ::GetIndString( newMenuString, newStringResourceID, newStringIndex );
  128.             if ( newMenuString[ 0 ] )
  129.             {
  130.                 if ( outName )
  131.                 {
  132.                     outName[ 0 ] = 0;
  133.                     XP_STRCPY( (char *)outName, (char *)newMenuString );
  134.                 }
  135.                 else
  136.                     SetMenuItemText( theMenuH, theItem, newMenuString );
  137.             }
  138.         }
  139.     }
  140. }
  141.  
  142.  
  143. #pragma mark -- CEditView --
  144. CEditView::CEditView(LStream * inStream) : CHTMLView(inStream),
  145.     mEditorDoneLoading( false ),
  146.     mUseCharFormattingCache( false ),
  147.     mDragData( nil ),
  148.     mHoldUpdates( nil )
  149. {
  150.     // Editable views always have scrollbars, though they might be disabled.
  151.     SetScrollMode( LO_SCROLL_YES, true );
  152.  
  153.     mLastBlink = 0;
  154.     mHideCaret = false;
  155.     mCaretDrawn = false;
  156.     mCaretActive = false;
  157.     mCaretX = 0;
  158.     mCaretYLow = 0;
  159.     mCaretYHigh = 0;
  160.     mDisplayParagraphMarks = false;
  161.  
  162.     mProxy = NULL;
  163.     Int32 theResult;
  164.     ::Gestalt( gestaltTSMgrAttr, &theResult );
  165.     
  166.     // Failure just means that this edit view won't support TSM
  167.     OSErr theErr = ::Gestalt( gestaltTSMgrVersion, &theResult );
  168.     if ( theErr == noErr && theResult >= 1 )
  169.     {
  170.         try
  171.             {
  172.                 if ( LTSMSupport::HasTextServices() )
  173.                     mProxy = new HTMLInlineTSMProxy( *this );
  174.             }
  175.         catch (...)
  176.             {
  177.             }
  178.     }
  179.  
  180.     mOldLastElementOver = -1;
  181.     mOldPoint.h = -1;
  182.     mOldPoint.v = -1;
  183. }
  184.  
  185. CEditView::~CEditView()
  186. {
  187.     SetContext( NULL );    
  188.     delete mProxy;
  189. }
  190.  
  191. void CEditView::FinishCreateSelf(void)
  192. {
  193.     LView *view = GetSuperView();
  194.     while (view->GetSuperView())
  195.         view = view->GetSuperView();
  196.  
  197.     mParagraphToolbarPopup = (LGAPopup *)view->FindPaneByID( cmd_Paragraph_Hierarchical_Menu );
  198.     mSizeToolbarPopup = (LGAPopup *)view->FindPaneByID( cmd_Font_Size_Hierarchical_Menu );
  199.     mAlignToolbarPopup = (CPatternButtonPopup *)view->FindPaneByID( cmd_Align_Hierarchical_Menu );
  200.     mFontToolbarPopup = (CFontMenuPopup *)view->FindPaneByID( 'Font' );
  201.     mColorPopup = (CColorPopup *)view->FindPaneByID( 'Colr' );
  202.  
  203.     CHTMLView::FinishCreateSelf();
  204. }
  205.  
  206. void CEditView::LayoutNewDocument( URL_Struct* inURL, Int32* inWidth, Int32* inHeight,
  207.                                     Int32* inMarginWidth, Int32* inMarginHeight )
  208. {
  209.     /*
  210.         The inherited |LayoutNewDocument| arbitrarily sets the scroll mode to LO_SCROLL_AUTO,
  211.         which is wrong for editable views --- they always show their scrollbars.
  212.     */
  213.  
  214.     /*inherited*/ CHTMLView::LayoutNewDocument( inURL, inWidth, inHeight, inMarginWidth, inMarginHeight );
  215.     SetScrollMode( LO_SCROLL_YES, true );
  216. }
  217.  
  218. void CEditView::SetContext( CBrowserContext* inNewContext )
  219. {
  220.     // if we are setting this to a NULL context *and* we had a previous context...
  221.     // assume we are shutting down window and destroy edit buffer
  222.     if ( GetContext() && inNewContext == NULL )
  223.         EDT_DestroyEditBuffer( *GetContext() );
  224.  
  225.     // remove and add ourselves (the editor) as a user of the context
  226.     if ( GetContext() )
  227.         GetContext()->RemoveUser( this );
  228.     if ( inNewContext )
  229.         inNewContext->AddUser( this );
  230.  
  231.     inherited::SetContext( inNewContext );
  232.     
  233.     if ( mProxy )
  234.         mProxy->SetContext( *(inNewContext) );
  235.  
  236. }
  237.  
  238. Boolean    CEditView::CanUseCharFormatting()
  239. {
  240.     if ( ! mUseCharFormattingCache )
  241.     {
  242.         ED_ElementType elementType = EDT_GetCurrentElementType( *GetContext() );
  243.         mIsCharFormatting = elementType == ED_ELEMENT_TEXT || elementType == ED_ELEMENT_SELECTION
  244.                             || elementType == ED_ELEMENT_CELL || elementType == ED_ELEMENT_ROW
  245.                             || elementType == ED_ELEMENT_COL; 
  246.     }
  247.  
  248.     return mIsCharFormatting;
  249. }
  250.  
  251. Bool CEditView::PtInSelectedRegion( SPoint32 cpPoint )
  252. {
  253.     Bool bPtInRegion = false;
  254.     Int32 right, left, top, bottom;
  255.  
  256.     if ( EDT_IS_EDITOR( ((MWContext *)*GetContext()) ) && EDT_IsSelected( *GetContext() ) )
  257.     {
  258.         int32 start_selection, end_selection;
  259.         LO_Element * start_element = NULL;
  260.         LO_Element * end_element = NULL;
  261.         CL_Layer *layer = NULL;
  262.         // Start the search from the current selection location    
  263.         LO_GetSelectionEndpoints( *GetContext(), 
  264.                              &start_element, 
  265.                              &end_element, 
  266.                              &start_selection, 
  267.                              &end_selection,
  268.                              &layer);
  269.         
  270.         if ( start_element == NULL )
  271.             return false;
  272.         
  273.         // Do.. Until would be nice!
  274.         for ( LO_Any_struct * element = (LO_Any_struct *)start_element; ;
  275.                 element = (LO_Any_struct *)(element->next) )
  276.         {
  277.             // Linefeed rect is from end of text to right ledge, so lets ignore it
  278.             if ( element->type != LO_LINEFEED )
  279.             {
  280.                 if ( element->type == LO_TEXT && 
  281.                      (element == (LO_Any_struct*)start_element || 
  282.                       element == (LO_Any_struct*)end_element) )
  283.                 {
  284.                     // With 1st and last text elements, we need to
  285.                     // account for character offsets from start or end of selection
  286.  
  287.                     LO_TextStruct *text = (LO_TextStruct*)element;
  288.                     left = element->x + element->x_offset;
  289.                     top = element->y + element->y_offset;
  290.                     right = left + element->width;
  291.                     bottom = top + element->height;
  292.                     bPtInRegion = cpPoint.h > left &&
  293.                                   cpPoint.h < right &&
  294.                                   cpPoint.v > top &&
  295.                                   cpPoint.v < bottom;
  296.                 } 
  297.                 else
  298.                 {
  299.                     // Get the rect surrounding selected element,
  300.                     left = element->x + element->x_offset;
  301.                     top = element->y + element->y_offset;
  302.                     right = left + element->width;
  303.                     bottom = top + element->height;
  304.                     bPtInRegion = cpPoint.h > left &&
  305.                                   cpPoint.h < right &&
  306.                                   cpPoint.v > top &&
  307.                                   cpPoint.v < bottom;
  308.                 }
  309.             }
  310.             // We're done if we are in a rect or finished with last element
  311.  
  312.             if ( bPtInRegion || element == (LO_Any_struct*)end_element || element->next == NULL )
  313.             {
  314.                 break;
  315.             }
  316.         }
  317.     }
  318.     return bPtInRegion;
  319. }
  320.  
  321. // used before editSource, reload, browse
  322. Bool CEditView::VerifySaveUpToDate()
  323. {
  324.     if ( !EDT_DirtyFlag( *GetContext() ) && !EDT_IS_NEW_DOCUMENT( ((MWContext *)*GetContext()) ))
  325.         return true;
  326.     
  327.     History_entry*    newEntry = SHIST_GetCurrent( &((MWContext *)*GetContext())->hist );
  328.     CStr255 fileName;
  329.     if ( newEntry && newEntry->address )
  330.         fileName = newEntry->address;
  331.                 
  332.     MessageT itemHit = HandleModalDialog( EDITDLG_SAVE_BEFORE_BROWSE, fileName,  NULL );
  333.     if (itemHit != ok)
  334.         return false;
  335.     
  336.     return SaveDocument();
  337. }
  338.  
  339.  
  340. // Call this to check if we need to force saving file
  341. //   Conditions are New, unsaved document and when editing a remote file
  342. // Returns true for all cases except CANCEL by the user in any dialog
  343.  
  344. Bool CEditView::SaveDocumentAs()
  345. {
  346.     History_entry * hist_ent = SHIST_GetCurrent( &((MWContext *)*GetContext())->hist );
  347.     if ( hist_ent && hist_ent->address )
  348.     {
  349.         if ( XP_STRNCMP( hist_ent->address, "file", 4 ) != 0 && CPrefs::GetBoolean( CPrefs::ShowCopyright ) )
  350.             {                                // preferences
  351.                 // Show a "Hint" dialog to warn user about copyright 
  352.                 //   of downloaded documents or images
  353.  
  354.                 if ( HandleModalDialog( EDITDLG_COPYRIGHT_WARNING , NULL, NULL ) == 2 )
  355.                 {
  356.                     // set preference
  357.                     CPrefs::SetBoolean( false, CPrefs::ShowCopyright );
  358.                 }
  359.             }
  360.  
  361.         if ( hist_ent->title && XP_STRCMP( hist_ent->title, hist_ent->address ) == 0 )
  362.         {
  363.             // If there is no title, it will be set to URL address
  364.             ///  in CFE_FinishedLayout. It makes no sense to
  365.             //  use this title when changing the filename, so destroy it
  366.             XP_FREE( hist_ent->title );
  367.             hist_ent->title = NULL;
  368.             if ( ((MWContext *)*GetContext())->title )
  369.             {
  370.                 XP_FREE( ((MWContext *)*GetContext())->title );
  371.                 ((MWContext *)*GetContext())->title = NULL;
  372.             }
  373.         }
  374.  
  375.         // Try to suggest a name if not a new doc or local directory
  376.         CStr31 pSuggested;
  377.         fe_FileNameFromContext( *GetContext(), hist_ent->address, pSuggested );
  378.         
  379.         char viewableName[32];
  380.         strcpy( viewableName, pSuggested );
  381.         NET_UnEscape(viewableName);    // Hex Decode
  382.         pSuggested = viewableName;
  383.         
  384.         StandardFileReply sfReply;
  385.         ::UDesktop::Deactivate();
  386.         ::StandardPutFile( NULL, pSuggested, &sfReply );
  387.         ::UDesktop::Activate();
  388.  
  389.         if ( !sfReply.sfGood )
  390.             return false;
  391.  
  392.           char *pLocalName = CFileMgr::GetURLFromFileSpec( sfReply.sfFile );
  393.         if ( pLocalName )
  394.         {
  395.             int16    saveCsid = (GetContext())->GetWinCSID();
  396.  
  397.             if (hist_ent->title == NULL)
  398.             {
  399.                 CStr31 newName( sfReply.sfFile.name );
  400.                 StrAllocCopy( ((MWContext *)*GetContext())->title, newName );
  401.                 SHIST_SetTitleOfCurrentDoc( *GetContext() );
  402.             }
  403.  
  404.             Bool bKeepImagesWithDoc = CPrefs::GetBoolean( CPrefs::PublishKeepImages );                 // preferences
  405.             Bool bAutoAdjustLinks = CPrefs::GetBoolean( CPrefs::PublishMaintainLinks );
  406.     
  407.             // ignore result
  408.             EDT_SaveFile( *GetContext(), hist_ent->address,             // Source
  409.                                          pLocalName,                    // Destination
  410.                                          true,                          // Do SaveAs
  411.                                          bKeepImagesWithDoc, bAutoAdjustLinks );
  412.  
  413.             (GetContext())->SetWinCSID(saveCsid);            
  414.             
  415.             XP_Bool doAutoSave;
  416.             int32 iSave;
  417.             PREF_GetBoolPref( "editor.auto_save", &doAutoSave );
  418.             if ( doAutoSave )
  419.                 PREF_GetIntPref( "editor.auto_save_delay", &iSave );
  420.             else
  421.                 iSave = 0;
  422.             EDT_SetAutoSavePeriod( *GetContext(), iSave );
  423.              
  424.             XP_FREE( pLocalName );
  425.             return true;
  426.         }
  427.  
  428.         // Clear the flag!
  429.     }
  430.     return true;
  431. }
  432.  
  433.  
  434. Bool CEditView::SaveDocument()
  435. {
  436.     History_entry * hist_ent = SHIST_GetCurrent(&(((MWContext *)*GetContext())->hist));
  437.     if ( hist_ent && hist_ent->address )
  438.     {
  439.         char *szLocalFile = NULL;
  440.  
  441.         if ( !EDT_IS_NEW_DOCUMENT( ((MWContext *)*GetContext()) )
  442.         && XP_ConvertUrlToLocalFile( hist_ent->address, &szLocalFile ) )
  443.         {
  444.             Bool bKeepImagesWithDoc = CPrefs::GetBoolean( CPrefs::PublishKeepImages );
  445.             Bool bAutoAdjustLinks = CPrefs::GetBoolean( CPrefs::PublishMaintainLinks );
  446.         
  447.             ED_FileError result = EDT_SaveFile( *GetContext(), hist_ent->address,    // Source
  448.                                                 hist_ent->address,  // Destination
  449.                                                 false,  // Not doing SaveAs
  450.                                                 bKeepImagesWithDoc, bAutoAdjustLinks );
  451.  
  452.             if ( result == ED_ERROR_NONE )
  453.             {
  454.                 XP_Bool doAutoSave;
  455.                 int32 iSave;
  456.                 PREF_GetBoolPref( "editor.auto_save", &doAutoSave );
  457.                 if ( doAutoSave )
  458.                     PREF_GetIntPref( "editor.auto_save_delay", &iSave );
  459.                 else
  460.                     iSave = 0;
  461.                 EDT_SetAutoSavePeriod( *GetContext(), iSave );
  462.             }
  463.     
  464.             if ( szLocalFile )
  465.                 XP_FREE( szLocalFile );
  466.  
  467.             return true;
  468.         }
  469.         else
  470.         {
  471.             // Any URL that is NOT a file must do SaveAs to rename to a local file
  472.             // (With current model, this only happens with new document,
  473.             //  editing remote URLs immediately forces SaveAs locally)
  474.             Boolean returnValue;
  475.             returnValue = SaveDocumentAs();
  476.             
  477.             if ( returnValue )    // successfully saved
  478.                 EDT_SetDirtyFlag( *GetContext(), false );
  479.  
  480.             return returnValue;
  481.         }
  482.     }
  483.     
  484.     return true;
  485. }
  486.  
  487. URL_Struct *CEditView::GetURLForPrinting( Boolean& outSuppressURLCaption, MWContext *printingContext )
  488. {
  489.     // for the editor, we don't want to require saving the file if it's dirty or if
  490.     // it has never been saved SO we save it to a temp file and we'll print that╔
  491.     MWContext *ourContext = *GetContext();
  492.     if ( EDT_IS_EDITOR( ourContext ) 
  493.     && ( EDT_DirtyFlag( ourContext ) || EDT_IS_NEW_DOCUMENT( ourContext ) ) )
  494.     {
  495.         EDT_SaveToTempFile( *GetContext(), EditorPrintingCallback, printingContext );
  496.         return NULL;
  497.     }
  498.     else
  499.         return CHTMLView::GetURLForPrinting( outSuppressURLCaption, printingContext );
  500.  
  501. void CEditView::DrawCaret( Boolean doErase )
  502. {
  503.     if ( mHideCaret )
  504.         return;
  505.     
  506.     FocusDraw();
  507.     
  508.     // only draw caret if we are erasing it or if this view is the target of the window
  509.     if ( IsTarget() || doErase )
  510.     {
  511.         StColorPenState theState;
  512.         ::PenNormal();
  513.         ::PenMode(srcXor);
  514.         ::MoveTo(mCaretX, mCaretYLow);
  515.         ::LineTo(mCaretX, mCaretYHigh - 1);        // only want to turn on pixels down to mCaretYHigh, not beyond
  516.  
  517.         mLastBlink = TickCount();
  518.         mCaretDrawn = !mCaretDrawn;
  519.     }
  520. }
  521.  
  522.  
  523. void CEditView::EraseCaret()
  524. {
  525.     if ( mCaretDrawn )
  526.         DrawCaret( true );        // erase it if it's on the screen so we don't leave behind carets
  527. }
  528.  
  529.  
  530. void CEditView::PlaceCaret( int32 caretXi, int32 caretYLowi, int32 caretYHighi )
  531. {
  532.     if ( mCaretActive )
  533.         RemoveCaret();            // did we forget to remove the last caret?! assert here?
  534.     
  535.     mCaretActive = false;
  536.     
  537. /*    This function takes the real position of a layout element,
  538.     and returns the local position and whether it is visible.
  539.     If it's not visible, the local position is not valid.
  540. */
  541.     Point            portOrigin = {0, 0};
  542.     SPoint32        frameLocation;
  543.     SDimension16    frameSize;
  544.     SPoint32        imageLocation;
  545.     
  546.     PortToLocalPoint( portOrigin );
  547.     GetFrameLocation( frameLocation );
  548.     GetFrameSize( frameSize );
  549.     GetImageLocation( imageLocation );
  550.     
  551.     // convert local rectangle to image rectangle
  552.     long realFrameLeft         = frameLocation.h - imageLocation.h; // frameLocation.h - portOrigin.h - imageLocation.h;
  553.     long realFrameRight     = realFrameLeft + frameSize.width;
  554.     long realFrameTop         = frameLocation.v - imageLocation.v; // frameLocation.v - portOrigin.v - imageLocation.v;
  555.     long realFrameBottom     = realFrameTop + frameSize.height;
  556.         
  557.     // is it visible at all? If not, return
  558.     if (realFrameRight <= caretXi || realFrameLeft >= caretXi 
  559.             || realFrameBottom <= caretYLowi ||    realFrameTop >= caretYHighi)
  560.         return;
  561.     
  562.     mCaretActive = true;
  563.     
  564.     mCaretX = caretXi + portOrigin.h + imageLocation.h;
  565.     mCaretYLow = caretYLowi + portOrigin.v + imageLocation.v;
  566.     mCaretYHigh = mCaretYLow + caretYHighi - caretYLowi;
  567.     
  568.     DrawCaret( false );
  569.     StartIdling();
  570. }
  571.  
  572.  
  573. void CEditView::RemoveCaret()
  574. {
  575.     mCaretActive = false;
  576.     EraseCaret();
  577.     StopIdling();
  578. }
  579.  
  580.  
  581. void CEditView::DisplayGenericCaret( MWContext *context, LO_Element * pLoAny, 
  582.                                         ED_CaretObjectPosition caretPos )
  583. {
  584.     if ( !(FocusDraw()) )
  585.         return;
  586.     
  587.     int32 xVal, yVal, yValHigh;
  588.  
  589.     GetCaretPosition( context, pLoAny, caretPos, &xVal, &yVal, &yValHigh );
  590.     
  591.     if ( context->is_editor )
  592.         PlaceCaret( xVal, yVal, yValHigh );    
  593. }
  594.  
  595.  
  596. // forces a super-reload (not from cache)
  597. void CEditView::DoReload( void )
  598. {
  599.     Try_    
  600.     {
  601.         History_entry * history = SHIST_GetCurrent( &((MWContext *)*GetContext())->hist );
  602.         ThrowIfNil_(history);
  603.         
  604.         SPoint32    location;
  605.         LO_Element*    element;
  606.             
  607.         // We need to set the location before creating the new URL struct
  608.         GetScrollPosition( location );
  609.     #ifdef LAYERS
  610.         element = LO_XYToNearestElement( *GetContext(), location.h, location.v, NULL );
  611.     #else
  612.         element = LO_XYToNearestElement( *GetContext(), location.h, location.v );
  613.     #endif // LAYERS
  614.         if ( element )
  615.             SHIST_SetPositionOfCurrentDoc( &((MWContext *)*GetContext())->hist, element->lo_any.ele_id );
  616.         
  617.         URL_Struct * url = SHIST_CreateURLStructFromHistoryEntry( *GetContext(), history );
  618.         ThrowIfNil_(url);
  619.         
  620.         url->force_reload = NET_SUPER_RELOAD;
  621.         mContext->ImmediateLoadURL( url, FO_CACHE_AND_PRESENT );
  622.     }
  623.     Catch_(inErr)
  624.     {}EndCatch_
  625. }
  626.  
  627. void CEditView::NoteEditorRepagination( void )
  628. {
  629.     SetFontInfo();
  630.  
  631.     LO_InvalidateFontData( (MWContext *)(*GetContext()) );
  632.     EDT_RefreshLayout( (MWContext *)(*GetContext()) );
  633.     AdjustScrollBars();
  634. }
  635.  
  636.  
  637. void CEditView::ActivateSelf()
  638. {
  639.     if ( mCaretActive )
  640.         StartIdling();                        // don't forget to restart our caret
  641.     
  642.     if ( EDT_IsFileModified( *GetContext() ))
  643.     {
  644.         History_entry*    newEntry = SHIST_GetCurrent( &((MWContext *)*GetContext())->hist );
  645.         CStr255 fileName;
  646.         if ( newEntry && newEntry->address )
  647.             fileName = newEntry->address;
  648.                 
  649.         if ( HandleModalDialog( EDITDLG_FILE_MODIFIED, fileName, NULL ) == ok )
  650.             DoReload();
  651.     }
  652. }
  653.  
  654. void CEditView::GetDefaultBackgroundColor( LO_Color* outColor ) const
  655. {
  656.     // if we're not done loading the editor yet, 
  657.     // the default color should be the same as the browser
  658.     if ( !mEditorDoneLoading )
  659.     {
  660.         uint8 red, green, blue;
  661.         int result = PREF_GetColorPref( "editor.background_color", &red, &green, &blue );
  662.         if ( PREF_NOERROR == result )
  663.         {
  664.             outColor->red = red;
  665.             outColor->green = green;
  666.             outColor->blue = blue;
  667.         }
  668.         else
  669.             CHTMLView::GetDefaultBackgroundColor( outColor );
  670.     }
  671. }
  672.  
  673.  
  674. void CEditView:: DeactivateSelf()
  675. {
  676.     FocusDraw();
  677.     
  678. /*    if (midocID)
  679.     {
  680.         OSErr    err = ::FixTSMDocument(midocID);
  681.         ThrowIfOSErr_(err);
  682.     }
  683. */
  684.     if ( mCaretActive )
  685.     {
  686.         StopIdling();                        // don't forget to stop caret
  687.         EraseCaret();                        // oh yeah, and get rid of it if it is on the screen so we don't leave a caret
  688.     }
  689. }
  690.  
  691. // XXX CALLBACK
  692.  
  693. void CEditView::SetDocPosition( int inLocation, Int32 inX, Int32 inY, Boolean inScrollEvenIfVisible )
  694. {
  695.     // Make sure any pending updates are handled at correct origin
  696.     UpdatePort();
  697.     CHTMLView::SetDocPosition( inLocation, inX, inY, inScrollEvenIfVisible );
  698. }
  699.  
  700. /*
  701. If we are hilighted as the pane being dragged "into", we want to first hide the hilite
  702. before drawing then draw it back.  This is because we have an offscreen view which 
  703. messes up the drag hilite-ing.
  704. */
  705. void CEditView::DrawSelf()
  706. {
  707.     EraseCaret();                            // remove caret if it is showing so we don't leave it behind
  708.     
  709.     if ( mIsHilited )
  710.         ::HideDragHilite(mDragRef);
  711.     
  712.     CHTMLView::DrawSelf();
  713.     
  714.     if ( mIsHilited )
  715.         HiliteDropArea(mDragRef);
  716. }
  717.  
  718. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  719. //    Ñ    EstablishPort
  720. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  721. // This is identical to CHTMLView's EstablishPort except we don't have the
  722. // SetGDevice( GetMainDevice() ) call at the which CHTMLView does. That SetGDevice
  723. // messed up our offscreen GWorld. 
  724. Boolean CEditView::EstablishPort()
  725. {
  726.     Boolean portSet = false;
  727.     GWorldPtr gworld = NULL;
  728.     
  729.  
  730.     // if the current drawable, is an offscreen one, be sure to set it
  731.     if ( mCurrentDrawable != NULL )
  732.     {
  733.         gworld = mCurrentDrawable->GetDrawableOffscreen();
  734.     }
  735.     
  736.     if ( gworld != NULL )
  737.     {
  738.         portSet = true;
  739.         if ( UQDGlobals::GetCurrentPort() != (GrafPtr) mGWorld )
  740.         {
  741.             SetGWorld ( gworld, NULL );
  742.             mOffscreenDrawable->mClipChanged = true;
  743.         }
  744.     }
  745.     else
  746.     {
  747.         portSet = LView::EstablishPort();
  748.     }    
  749.  
  750.     return portSet;
  751. }
  752.  
  753.  
  754. /*
  755. Keep track of the drag reference number so we can re-hilite the drag area manually in DrawSelf.
  756. Also, do our superclass's LDropArea::EnterDropArea behavior
  757. */
  758. void CEditView::EnterDropArea( DragReference inDragRef, Boolean inDragHasLeftSender )
  759. {
  760.     if ( inDragHasLeftSender )
  761.         mDragRef = inDragRef;
  762.  
  763.     LDropArea::EnterDropArea( inDragRef, inDragHasLeftSender );
  764. }
  765.  
  766. // This method gets called when window changes size.
  767. // Make sure we DO NOT call mContext->Repaginate() like CHTMLView does
  768. void CEditView::AdaptToSuperFrameSize( Int32 inSurrWidthDelta,
  769.                                     Int32 inSurrHeightDelta, Boolean inRefresh )
  770. {
  771.     LView::AdaptToSuperFrameSize( inSurrWidthDelta, inSurrHeightDelta, inRefresh );
  772.     if (mContext)
  773.         EDT_RefreshLayout( *GetContext() );
  774. }
  775.  
  776.  
  777. #if 0
  778. void CEditView::SetDocDimension( int /* ledge */, Int32 inWidth, Int32 inHeight )        // this overrides the SetDocDimension which does cacheing.
  779. {
  780.     SDimension32 theImageSize;
  781.     GetImageSize(theImageSize);
  782.     
  783.     Int32 theWidthDelta = inWidth - theImageSize.width;
  784.     Int32 theHeightDelta = inHeight - theImageSize.height;
  785.  
  786.     if ((abs(theWidthDelta) > 200) || (abs(theHeightDelta) > 200))
  787.         {
  788.         mCachedImageSizeDelta.width = 0;
  789.         mCachedImageSizeDelta.height = 0;
  790.         SetDocDimensionSelf(theWidthDelta, theHeightDelta);
  791.         }
  792.     else
  793.         {
  794.         mCachedImageSizeDelta.width = theWidthDelta;
  795.         mCachedImageSizeDelta.height = theHeightDelta;
  796.         }
  797. }
  798. #endif
  799.  
  800.  
  801. void CEditView::GetDocAndWindowPosition( SPoint32 &frameLocation, SPoint32 &imageLocation, SDimension16 &frameSize )
  802. {
  803.     // Make sure we're all talking about the same thing.
  804.     FocusDraw();
  805.  
  806.     // Get the frame and image rectangles...
  807.     GetFrameLocation( frameLocation );
  808.     GetImageLocation( imageLocation );
  809.     GetFrameSize( frameSize );
  810. }
  811.  
  812.  
  813. void CEditView::CreateFindWindow()
  814. {
  815.     LWindow::CreateWindow( 5290, LCommander::GetTopCommander() );
  816. }
  817.  
  818.  
  819. void CEditView::DisplaySubtext(
  820.     int                     inLocation,
  821.     LO_TextStruct*            inText,
  822.     Int32                     inStartPos,
  823.     Int32                    inEndPos,
  824.     XP_Bool                 inNeedBG)
  825. {
  826.     if ( mHoldUpdates )
  827.         return;
  828.         
  829.     inherited::DisplaySubtext(inLocation, inText, inStartPos, inEndPos, inNeedBG);
  830. }
  831.  
  832. void CEditView::EraseBackground(
  833.     int                        inLocation,
  834.     Int32                    inX,
  835.     Int32                    inY,
  836.     Uint32                    inWidth,
  837.     Uint32                    inHeight,
  838.     LO_Color*                inColor)
  839. {
  840.     if (mHoldUpdates)
  841.         return;
  842.         
  843.     inherited::EraseBackground(inLocation, inX, inY, inWidth, inHeight, inColor);
  844. }
  845.  
  846.  
  847. void CEditView::DocumentChanged( int32 iStartY, int32 iHeight )
  848. {
  849.     SPoint32        frameLocation, imageLocation, updateUL, updateLR;
  850.     SDimension16    frameSize;
  851.     SDimension32    imageSize;
  852.     
  853.     // document may have grown but not enough to trigger SetDocDimension so force resize
  854.     FlushPendingDocResize();
  855.     
  856.     if ( mHoldUpdates )
  857.     {
  858.         mHoldUpdates->DocumentChanged( iStartY, iHeight );
  859.         return;
  860.     }
  861.         
  862.     // Make sure we're all talking about the same thing.
  863.     FocusDraw();
  864.  
  865.     // Get the frame rectangle in port coordinates
  866.     GetFrameLocation( frameLocation );            // wimpy 16 bit coordinates
  867.     GetFrameSize( frameSize );
  868.     
  869.     // Get the image rectangle in port coordinates
  870.     GetImageLocation( imageLocation );            // massive 32 bit coordinates
  871.     GetImageSize( imageSize );
  872.     
  873.     // convert the frame rectangle to image coordinates                    // massive 32 bit coordinates
  874.     frameLocation.h = frameLocation.h - imageLocation.h;
  875.     frameLocation.v = frameLocation.v - imageLocation.v;
  876.         
  877.     // Get the region to update in image coordinates.
  878.     updateUL.h = 0;        // sorry to say, the horizontal will be ignored later and set to the whole frame width
  879.     updateUL.v = iStartY;
  880.     
  881.     // we want to update all the way to right side of the frame (no matter how narrow or wide the image might be..)
  882.     updateLR.h = frameLocation.h + frameSize.width;        // sorry to say, the horizontal will be ignored later and set to the whole frame width
  883.         
  884.     // if iHeight is -1, then we want to invalidate to the end of the image or the frame (whichever is lower)
  885.     // however, we are going to clip to the frame later anyway, so just invalidate to the end of the frame.
  886.     if (iHeight == -1)
  887.         updateLR.v = frameLocation.v + frameSize.height;
  888.     else
  889.         updateLR.v = iStartY + iHeight;
  890.  
  891.     // Intersect the update rectangle with the frame rectangle and make sure they overlap (in image coordinates)
  892.     if ( sect_rect_long( frameLocation, frameSize, &updateUL, &updateLR ) )
  893.     {
  894.         Rect    updateRect;
  895.         Point    ul, lr;
  896.         
  897.         // get the frame rectange in port coordinates again.
  898.         CalcPortFrameRect( updateRect );
  899.         
  900.         // Convert from image to local to port coordinates... we don't have to worry about the conversion because we've already been clipped to the frame
  901.         ImageToLocalPoint( updateUL, ul );
  902.         ImageToLocalPoint( updateLR, lr );
  903.         LocalToPortPoint( ul );
  904.         LocalToPortPoint( lr );
  905.         
  906.         updateRect.top = ul.v;
  907.         updateRect.bottom = lr.v;
  908.         
  909.         EraseCaret();            // erase it if it's on the screen so we don't show the caret. This should be covered by DrawSelf...
  910. // There is a problem with the last line because Idling is still on and we may just redraw the caret before the InvalRect updates the screen.
  911. // The next two lines are a hack. They cause the updated region to be redrawn immediately,
  912. // this is necessary because EDT_Paste and other functions may cause an update event and then a scroll
  913. // before allowing the updated region to be redrawn (in its old location).
  914. // In other words, when the invalid text is scrolled out from under the update region, it is never updated.
  915.         InvalPortRect( &updateRect );
  916.         UpdatePort();
  917.     }
  918. }
  919.  
  920.  
  921. void CEditView::SpendTime( const EventRecord& inMacEvent )
  922. {
  923.     if ( mCaretActive )
  924.         if ( TickCount() > mLastBlink + ::LMGetCaretTime() )
  925.             DrawCaret( false );
  926.     
  927.     CHTMLView::SpendTime( inMacEvent );
  928. }
  929.  
  930. void CEditView::BeTarget()
  931. {
  932.     FocusDraw();
  933.     
  934.     inherited::BeTarget();
  935.     
  936.     if ( mProxy )
  937.         mProxy->Activate();
  938.  
  939. }
  940.  
  941. void CEditView::DontBeTarget()
  942. {
  943.     FocusDraw();
  944.     
  945.     try
  946.         {
  947.  
  948.             if ( mProxy )
  949.                 mProxy->Deactivate();
  950.  
  951.         }
  952.     catch (...)
  953.         {
  954.         }
  955.  
  956.     inherited::DontBeTarget();
  957. }
  958.  
  959.  
  960. /*
  961. IsPastable shows whether or not a character can be pasted in.  Note that right now Tab cannot be
  962. pasted in, even though it is handled in EDT_PasteText().  This is because EDT_PasteText()'s
  963. tab implementation is broken, inserting only one space.
  964.  
  965. Note: Methods HandleKeyPress and IsPastable are dependant on each other because IsPastable
  966. returns false for all keystrokes that HandleKeyPress handles other than the default 
  967. EDT_KeyDown.  Specifically, in HandleKeyPress there is a switch statement based on
  968. "theChar & charCodeMask".  If additional case statements are added to this switch which
  969. make it inappropriate to call EDT_KeyDown we may have to add an additional case statement
  970. in IsPastable which returns false.
  971.  
  972. */
  973. Boolean CEditView::IsPastable(Char16 theChar) 
  974. {
  975.     switch ( theChar & charCodeMask ) 
  976.     {
  977.         case char_LeftArrow:
  978.         case char_RightArrow:
  979.         case char_UpArrow:
  980.         case char_DownArrow:
  981.         case char_Backspace:
  982.         case char_FwdDelete:
  983.         case char_Return:
  984.         case char_Enter:
  985.         case char_Tab:
  986.         case char_Home:
  987.         case char_End:
  988.         case char_PageUp:
  989.         case char_PageDown:
  990.             return false;
  991.         default:
  992.             return true;
  993.     }
  994. }
  995.  
  996.  
  997. /*
  998. This function looks ahead into the Event Manager queue.  It finds all of the keyDown and keyUp events.
  999. The keyUp events it ignores.  The keyDown events, if they are "normal" keystrokes, puts into the 
  1000. string keys_in_q.  This is then used by HandleKeyPress so that since it's already handling a key press,
  1001. why not handle the rest also.  
  1002.  
  1003. Unfortunately, this is a bit of a hack.  Note especially that ::EventAvail() is used to check to make sure
  1004. that the event fits criteria and then ::GetNextEvent() gets the event.  If inbetween calling these two
  1005. calls the Event Queue's structure is changed, this could cause inappropriate behavior.
  1006. */
  1007. int CEditView::FindQueuedKeys(char *keys_in_q) 
  1008. {
  1009.       int curr_q_num;
  1010.       EventRecord currEvent, eventToRemove;
  1011.     
  1012.     curr_q_num = 0;
  1013.     
  1014.     /* Keep getting events while:
  1015.     1) We have room in our buffer
  1016.     2) There are events in Event Manager Queue
  1017.     3) Either we get a keyUp, or we get a key down that can be pasted    
  1018.     */ 
  1019.  
  1020.  
  1021.     Boolean foundAndClearedEvent;
  1022.     while ( (curr_q_num < (MAX_Q_SIZE-2)) && ::EventAvail( everyEvent, &currEvent ) )
  1023.     {
  1024.         if ( (currEvent.what == keyDown)     // its a backspace-keydown
  1025.         && !((cmdKey | optionKey | controlKey) & currEvent.modifiers) // with no modKeys except maybe shift
  1026.         && ( IsPastable( static_cast<Char16>(currEvent.message & 0xFFFF) )) )
  1027.         {
  1028.             keys_in_q[curr_q_num + 1] = static_cast<char>(currEvent.message & 0xFF);
  1029.             ++curr_q_num;
  1030.         }
  1031.         else if ( currEvent.what != keyUp ) // its _not_ a keyup; bail
  1032.             break;                             // keyups don't stop us, everything else does
  1033.         
  1034.         foundAndClearedEvent = ::GetNextEvent( keyDownMask | keyUpMask, &eventToRemove );
  1035.         XP_ASSERT( foundAndClearedEvent );
  1036.         if ( !foundAndClearedEvent )        // something bad must have happened; bail!
  1037.             break;
  1038.     }
  1039.                     
  1040.     return curr_q_num;                                                
  1041. }
  1042.  
  1043. /*
  1044. Note: Methods HandleKeyPress and IsPastable are dependant on each other because IsPastable
  1045. returns false for all keystrokes that HandleKeyPress handles other than the default 
  1046. EDT_KeyDown.  Specifically, in HandleKeyPress there is a switch statement based on
  1047. "theChar & charCodeMask".  If additional case statements are added to this switch which
  1048. make it inappropriate to call EDT_KeyDown we may have to add an additional case statement
  1049. in IsPastable which returns false.
  1050. */
  1051. Boolean CEditView::HandleKeyPress( const EventRecord& inKeyEvent )
  1052. {
  1053.     int lNumQKeys;
  1054.     char keys_to_type[MAX_Q_SIZE];
  1055.     
  1056.     if ( !IsDoneLoading() )
  1057.         return true;
  1058.     
  1059. #ifdef PROFILE
  1060. //    ProfilerSetStatus( true );
  1061. #endif
  1062.     
  1063.     ::ObscureCursor();
  1064.                 
  1065.     Char16        theChar = inKeyEvent.message & charCodeMask;
  1066.     short         modifiers = inKeyEvent.modifiers & (cmdKey | shiftKey | optionKey | controlKey);
  1067.     URL_Struct *request = nil;
  1068.     
  1069.     Boolean        handled = false;
  1070.     Boolean        isNormalKeyPress = false;    // whether or not to update buttons
  1071.     Boolean        shiftKeyPressed = ((modifiers & shiftKey) == shiftKey);
  1072.     
  1073.     if ( (modifiers & cmdKey) == 0)    {        // we don't do command keys. But we do everything else...
  1074.         switch ( theChar )
  1075.         {
  1076.         
  1077.     // Ñ Navigation Keys Ñ
  1078.     
  1079.             case char_LeftArrow:
  1080.                 if (modifiers & optionKey)
  1081.                     EDT_PreviousWord( *GetContext(), shiftKeyPressed );
  1082.                 else
  1083.                     EDT_PreviousChar( *GetContext(), shiftKeyPressed );
  1084.                 handled = true;
  1085.                 break;
  1086.  
  1087.             case char_RightArrow:
  1088.                 if (modifiers & optionKey)
  1089.                     EDT_NextWord( *GetContext(), shiftKeyPressed );
  1090.                 else
  1091.                     EDT_NextChar( *GetContext(), shiftKeyPressed );
  1092.                 handled = true;
  1093.                 break;
  1094.  
  1095.             case char_UpArrow:
  1096.                 if (modifiers & optionKey)
  1097.                     EDT_PageUp( *GetContext(), shiftKeyPressed );
  1098.                 else
  1099.                     EDT_Up( *GetContext(), shiftKeyPressed );
  1100.                 handled = true;
  1101.                 break;
  1102.  
  1103.             case char_DownArrow:
  1104.                 if (modifiers & optionKey)
  1105.                     EDT_PageDown( *GetContext(), shiftKeyPressed );
  1106.                 else
  1107.                     EDT_Down( *GetContext(), shiftKeyPressed );
  1108.                 handled = true;
  1109.                 break;
  1110.  
  1111.             
  1112.             case 0xCA:            // space !!
  1113.                 if (modifiers & optionKey)
  1114.                 {
  1115.                     EDT_InsertNonbreakingSpace( *GetContext() );
  1116.                 }
  1117.                 else
  1118.                 {
  1119.                     EDT_KeyDown( *GetContext(), theChar, 0, 0 );
  1120.                 }
  1121.                 handled = true;
  1122.                 break;
  1123.  
  1124.             
  1125.     // Ñ Deletion Keys Ñ
  1126.  
  1127.             case char_Backspace:
  1128.                 // if no existing selection, look for consecutive backspaces
  1129.                 if ( !EDT_IsSelected( *GetContext() ) )
  1130.                 {
  1131.                       EventRecord currEvent, eventToRemove;
  1132.                       int count = 1;    // include current keypress in count
  1133.                       Boolean foundAndClearedEvent;
  1134.  
  1135.                     while ( ::EventAvail( everyEvent, &currEvent ) )
  1136.                     {
  1137.                         if ( (currEvent.what == keyDown)     // its a backspace-keydown
  1138.                         && !((cmdKey | optionKey | controlKey) & currEvent.modifiers) // with no modKeys except maybe shift
  1139.                         && ( (static_cast<Uchar>(currEvent.message & charCodeMask)) == char_Backspace ) )
  1140.                             ++count;
  1141.                         else if ( currEvent.what != keyUp ) // its _not_ a keyup; bail
  1142.                             break;                             // keyups don't stop us, everything else does
  1143.                         
  1144.                         foundAndClearedEvent = ::GetNextEvent( keyDownMask | keyUpMask, &eventToRemove );
  1145.                         XP_ASSERT( foundAndClearedEvent );
  1146.                         if ( !foundAndClearedEvent )        // something bad must have happened; bail!
  1147.                             break;
  1148.                     }
  1149.                     
  1150.                     if ( count > 1 )    // more than just current event?
  1151.                     {
  1152.                         while ( count > 0 )
  1153.                         {
  1154.                             EDT_PreviousChar( *GetContext(), true );
  1155.                             --count;
  1156.                         }
  1157.                     }
  1158.                 }
  1159.  
  1160.                 EDT_DeletePreviousChar( *GetContext() );
  1161.                 handled = true;
  1162.                 break;
  1163.  
  1164.             case char_FwdDelete:
  1165.                 EDT_DeleteChar( *GetContext() );
  1166.                 handled = true;
  1167.                 break;
  1168.  
  1169.  
  1170.     // Ñ Action Keys Ñ
  1171.  
  1172.             case char_Return:
  1173.                 if ( (modifiers & optionKey) || (modifiers & shiftKey) )
  1174.                 {
  1175.                     if ( EDT_GetCurrentElementType( *GetContext() ) == ED_ELEMENT_TEXT )
  1176.                         EDT_InsertBreak( *GetContext(), ED_BREAK_NORMAL );
  1177.                 }
  1178.                 else
  1179.                 {
  1180.                     EDT_ReturnKey( *GetContext() );
  1181.                 }
  1182.                 handled = true;
  1183.                 break;
  1184.  
  1185.             case char_Enter:
  1186.                 if (modifiers & optionKey)
  1187.                 {
  1188.                     EDT_ReturnKey( *GetContext() );
  1189.                 } 
  1190.                 else
  1191.                 {
  1192.                     if ( EDT_GetCurrentElementType( *GetContext() ) == ED_ELEMENT_TEXT )
  1193.                         EDT_InsertBreak( *GetContext(), ED_BREAK_NORMAL );
  1194.                 }            
  1195.                 handled = true;
  1196.                 break;
  1197.  
  1198.             
  1199.             case char_Tab:
  1200.                 EDT_TabKey( *GetContext(), !shiftKeyPressed, modifiers & optionKey );
  1201. #if 0
  1202.                 if (modifiers & optionKey)
  1203.                     EDT_Outdent( *GetContext() );
  1204.                 else
  1205.                     EDT_Indent( *GetContext() );
  1206. #endif
  1207.                 handled = true;
  1208.                 break;
  1209.  
  1210.             case char_Home:
  1211.                 EDT_BeginOfDocument( *GetContext(), shiftKeyPressed );
  1212.                 handled = true;
  1213.                 break;
  1214.             
  1215.             case char_End:
  1216.                 EDT_EndOfDocument( *GetContext(), shiftKeyPressed );
  1217.                 handled = true;
  1218.                 break;
  1219.             
  1220.             case char_PageUp:
  1221.                 EDT_PageUp( *GetContext(), shiftKeyPressed );
  1222.                 handled = true;
  1223.                 break;
  1224.             
  1225.             case char_PageDown:
  1226.                 EDT_PageDown( *GetContext(), shiftKeyPressed );
  1227.                 handled = true;
  1228.                 break;
  1229.                         
  1230.             default:
  1231.                 // normal if nothing was selected (no character deletions) and file already marked dirty
  1232.                 isNormalKeyPress = !EDT_IsSelected( *GetContext() ) && EDT_DirtyFlag( *GetContext() );
  1233.                 
  1234.                 lNumQKeys = FindQueuedKeys(keys_to_type);
  1235.                 if (lNumQKeys > 0) 
  1236.                 {
  1237.                     keys_to_type[0] = theChar;
  1238.                     keys_to_type[lNumQKeys + 1] = '\0';
  1239.                     if ( (GetWinCSID() == CS_UTF8) || (GetWinCSID() == CS_UTF7) )
  1240.                     {
  1241.                         INTL_Encoding_ID scriptCSID = ScriptToEncoding( ::GetScriptManagerVariable( smKeyScript ) );
  1242.                         unsigned char* unicodestring = INTL_ConvertLineWithoutAutoDetect( scriptCSID, CS_UTF8, (unsigned char *)keys_to_type, lNumQKeys);
  1243.                         if ( unicodestring )
  1244.                         {
  1245.                             EDT_InsertText( *GetContext(), (char *)unicodestring ); 
  1246.                             XP_FREE( unicodestring );
  1247.                         }
  1248.                     }
  1249.                     else
  1250.                         EDT_InsertText( *GetContext(), keys_to_type );
  1251.                 }
  1252.                 else 
  1253.                 {
  1254.                     if ( (GetWinCSID() == CS_UTF8) || (GetWinCSID() == CS_UTF7) )
  1255.                     {
  1256.                         unsigned char characterCode[2];
  1257.                         characterCode[0] = (char) theChar;
  1258.                         characterCode[1] = '\0';
  1259.                         INTL_Encoding_ID scriptCSID = ScriptToEncoding( ::GetScriptManagerVariable( smKeyScript ) );
  1260.                         unsigned char* t_unicodestring = INTL_ConvertLineWithoutAutoDetect( scriptCSID, CS_UTF8, characterCode, 1);
  1261.                         if ( t_unicodestring )
  1262.                         {
  1263.                             EDT_InsertText( *GetContext(), (char *)t_unicodestring ); 
  1264.                             XP_FREE( t_unicodestring );
  1265.                         }
  1266.                     }
  1267.                     else
  1268.                         EDT_KeyDown( *GetContext(), theChar, 0, 0 );
  1269.                 }
  1270.                 handled = true;
  1271.                 break;
  1272.         }
  1273.     } 
  1274.     else        // command key
  1275.     {
  1276.         switch ( theChar )
  1277.         {
  1278.     // Ñ Navigation Keys Ñ
  1279.             case char_LeftArrow:
  1280.                 EDT_BeginOfLine( *GetContext(), shiftKeyPressed );
  1281.                 handled = true;
  1282.                 break;
  1283.  
  1284.             case char_RightArrow:
  1285.                 EDT_EndOfLine( *GetContext(), shiftKeyPressed );
  1286.                 handled = true;
  1287.                 break;
  1288.  
  1289.             case char_UpArrow:
  1290.                 EDT_BeginOfDocument( *GetContext(), shiftKeyPressed );
  1291.                 handled = true;
  1292.                 break;
  1293.  
  1294.             case char_DownArrow:
  1295.                 EDT_EndOfDocument( *GetContext(), shiftKeyPressed );
  1296.                 handled = true;
  1297.                 break;
  1298.         }
  1299.     }
  1300.  
  1301.     // update toolbar on navigation moves and when there is a selection
  1302.     if ( handled && !isNormalKeyPress )
  1303.     {
  1304.         StUseCharFormattingCache stCharFormat( *this );
  1305.         
  1306.         // force menu items to update (checkMarks and text (Undo/Redo) could change)
  1307.         LCommander::SetUpdateCommandStatus( true );
  1308. //        CPaneEnabler::UpdatePanes();
  1309.     }
  1310.     
  1311.     if ( !handled )
  1312.         handled = CHTMLView::HandleKeyPress(inKeyEvent);
  1313.     
  1314. #ifdef PROFILE
  1315. //    ProfilerSetStatus( false );
  1316. #endif
  1317.  
  1318.     return handled;
  1319. }
  1320.  
  1321. static
  1322. long GetAlignmentMenuItemNum( MWContext *mwcontext, Boolean& outEnabled )
  1323. {
  1324.     if ( mwcontext == NULL )
  1325.     {
  1326.         outEnabled = false;
  1327.         return 0;
  1328.     }
  1329.     
  1330.     ED_ElementType elementtype;
  1331.     elementtype = EDT_GetCurrentElementType( mwcontext );
  1332.  
  1333.     outEnabled = ( elementtype != ED_ELEMENT_UNKNOWN_TAG );
  1334.     if ( outEnabled )
  1335.     {
  1336.         ED_Alignment alignment;
  1337.         long itemNum;
  1338.  
  1339.         if ( elementtype == ED_ELEMENT_HRULE )
  1340.         {
  1341.             EDT_HorizRuleData *h_data;
  1342.             h_data = EDT_GetHorizRuleData( mwcontext );
  1343.             if ( h_data )
  1344.             {
  1345.                 alignment = h_data->align;
  1346.                 EDT_FreeHorizRuleData( h_data );
  1347.             }
  1348.             else
  1349.                 alignment = ED_ALIGN_DEFAULT;
  1350.         }
  1351.         else    /* For Images, Text, or selection, this will do all: */
  1352.             alignment = EDT_GetParagraphAlign( mwcontext );
  1353.  
  1354.         switch( alignment )
  1355.         {
  1356.             case ED_ALIGN_DEFAULT:
  1357.             case ED_ALIGN_LEFT:        itemNum = 1;    break;
  1358.             case ED_ALIGN_ABSCENTER:
  1359.             case ED_ALIGN_CENTER:    itemNum = 2;    break;
  1360.             case ED_ALIGN_RIGHT:    itemNum = 3;    break;
  1361.             default:
  1362.                 itemNum = 0;
  1363.         }
  1364.         
  1365.         Assert_(itemNum <= 3 || itemNum >= 0);
  1366.         
  1367.         outEnabled = ( itemNum != 0 );
  1368.         return itemNum;
  1369.     }
  1370.     
  1371.     return 0;
  1372. }
  1373.  
  1374. static
  1375. long GetFormatParagraphPopupItem( MWContext *mwcontext, Boolean& outEnabled, Char16& outMark )
  1376. {
  1377.     if ( mwcontext == NULL )
  1378.     {
  1379.         outEnabled = false;
  1380.         return 0;
  1381.     }
  1382.     
  1383.     long itemNum;
  1384.     TagType paragraph_type = EDT_GetParagraphFormatting( mwcontext );
  1385.     switch( paragraph_type )
  1386.     {
  1387.         case P_NSDT:
  1388.         case P_UNKNOWN:
  1389.         case P_PARAGRAPH:    itemNum = 1;    break;
  1390.         case P_HEADER_1:    itemNum = 2;    break;
  1391.         case P_HEADER_2:    itemNum = 3;    break;
  1392.         case P_HEADER_3:    itemNum = 4;    break;
  1393.         case P_HEADER_4:    itemNum = 5;    break;
  1394.         case P_HEADER_5:    itemNum = 6;    break;
  1395.         case P_HEADER_6:    itemNum = 7;    break;
  1396.         case P_ADDRESS:        itemNum = 8;    break;
  1397.         case P_PREFORMAT:    itemNum = 9;    break;
  1398.         case P_LIST_ITEM:    itemNum = 10;    break;
  1399.         case P_DESC_TITLE:    itemNum = 11;    break;
  1400.         case P_DESC_TEXT:    itemNum = 12;    break;
  1401.         default:
  1402.             itemNum = 0;
  1403.     }
  1404.         
  1405.     outMark = checkMark;
  1406.     XP_ASSERT( itemNum <= 12 && itemNum >= 0 );
  1407.     
  1408.     outEnabled = ( itemNum != 0 );
  1409.  
  1410.     return itemNum;
  1411. }
  1412.  
  1413. void CEditView::FindCommandStatus( CommandT inCommand, Boolean& outEnabled, 
  1414.                         Boolean& outUsesMark, Char16& outMark, Str255 outName )
  1415. {
  1416.     outUsesMark = false;
  1417.     outEnabled = false;
  1418.     EDT_CharacterData* better;            // used by a bunch of cases.
  1419.     short index;
  1420.     Boolean    hasBroadcasting;
  1421.     
  1422.     if ( ::StillDown() && IsDoneLoading() )
  1423.     {
  1424.         if ( FindCommandStatusForContextMenu( inCommand, outEnabled,outUsesMark, outMark, outName ) )
  1425.             return;
  1426.     }
  1427.     
  1428.     // if we haven't finished initializing yet very few commands should be enabled
  1429.     switch ( inCommand )
  1430.     {
  1431.         case cmd_AddToBookmarks:
  1432.             if ( !IsDoneLoading() )
  1433.                 return;
  1434.     
  1435.             // don't add history entries == "file:///Untitled" (unsaved editor windows)
  1436.             if ( !mContext )
  1437.                 break;
  1438.             History_entry *histentry = mContext->GetCurrentHistoryEntry();
  1439.             if ( histentry && histentry->address )
  1440.             {
  1441.                 if ( 0 != XP_STRCMP( histentry->address, XP_GetString(XP_EDIT_NEW_DOC_NAME) ) )
  1442.                     outEnabled = true;
  1443.             }
  1444.             break;
  1445.         
  1446.         case cmd_CheckSpelling:
  1447.         case cmd_Print:
  1448.         case cmd_ViewSource:
  1449.         case cmd_Publish:
  1450.         case cmd_Refresh:
  1451.         case cmd_Format_Document:
  1452.         case cmd_Format_PageTitle:
  1453.         case cmd_Format_FontHierMenu:
  1454.             outEnabled = IsDoneLoading();
  1455.             break;
  1456.         
  1457.         case 'Font':
  1458.             outUsesMark = outEnabled = IsDoneLoading() && CanUseCharFormatting();
  1459.             if ( outUsesMark )
  1460.             {
  1461.                 outMark = 0;
  1462.                 better = EDT_GetCharacterData( *GetContext() );
  1463.                 if ( better && better->pFontFace 
  1464.                 && mFontToolbarPopup && mFontToolbarPopup->IsEnabled() )
  1465.                 {
  1466.                     outMark = checkMark;
  1467.                     
  1468.                     // turn off broadcasting so we don't apply it here!
  1469.                     hasBroadcasting = mFontToolbarPopup->IsBroadcasting();
  1470.                     if ( hasBroadcasting )
  1471.                         mFontToolbarPopup->StopBroadcasting();
  1472.                     
  1473.                     // get font menu item
  1474.                     int        menuItemNum;
  1475.                     Str255    fontItemString;
  1476.                     LMenu *ppmenu = mFontToolbarPopup->GetMenu();
  1477.                     MenuHandle menuh = ppmenu ? ppmenu->GetMacMenuH() : NULL;
  1478.                     for ( menuItemNum = 0; menuItemNum < ::CountMenuItems( menuh ); menuItemNum++ )
  1479.                     {
  1480.                         fontItemString[ 0 ] = 0;
  1481.                         ::GetMenuItemText ( menuh, menuItemNum, fontItemString );
  1482.                         p2cstr( fontItemString );
  1483.                         if ( XP_STRLEN((char *)fontItemString) > 0 
  1484.                         && XP_STRSTR( better->pFontFace, (char *)fontItemString ) != NULL )
  1485.                             break;
  1486.                     }
  1487.  
  1488.                     mFontToolbarPopup->SetValue( menuItemNum );
  1489.                     
  1490.                     // resume broadcasting
  1491.                     if ( hasBroadcasting )
  1492.                         mFontToolbarPopup->StartBroadcasting();
  1493.                 }
  1494.                 if ( better )
  1495.                     EDT_FreeCharacterData( better );
  1496.             }
  1497.             break;
  1498.         
  1499.         case cmd_Font_Size_Hierarchical_Menu:
  1500.             if ( !IsDoneLoading() )
  1501.                 return;
  1502.     
  1503.             outUsesMark = outEnabled = CanUseCharFormatting();
  1504.             if ( outUsesMark )
  1505.             {
  1506.                 outMark = 0;
  1507.                 better = EDT_GetCharacterData( *GetContext() );
  1508.                 if ( better && mSizeToolbarPopup && mSizeToolbarPopup->IsEnabled() )
  1509.                 {
  1510.                     outMark = checkMark;
  1511.                     XP_ASSERT( better->iSize <= 8 || better->iSize >= 1 );
  1512.                     
  1513.                     // turn off broadcasting so we don't apply it here!
  1514.                     hasBroadcasting = mSizeToolbarPopup->IsBroadcasting();
  1515.                     if ( hasBroadcasting )
  1516.                         mSizeToolbarPopup->StopBroadcasting();
  1517.                     
  1518.                     mSizeToolbarPopup->SetValue( better->iSize );    // iSize is the menu itemNum not the size
  1519.                     
  1520.                     // resume broadcasting
  1521.                     if ( hasBroadcasting )
  1522.                         mSizeToolbarPopup->StartBroadcasting();
  1523.                 }
  1524.                 if ( better )
  1525.                     EDT_FreeCharacterData( better );
  1526.             }
  1527.             break;
  1528.  
  1529.         case cmd_Align_Hierarchical_Menu:
  1530.             if ( !IsDoneLoading() )
  1531.                 return;
  1532.     
  1533.             long alignItemNum;
  1534.             alignItemNum = GetAlignmentMenuItemNum( *GetContext(), outEnabled );
  1535.             if ( outEnabled && mAlignToolbarPopup && mAlignToolbarPopup->IsEnabled() )
  1536.             {
  1537.                 // turn off broadcasting so we don't apply it here!
  1538.                 hasBroadcasting = mAlignToolbarPopup->IsBroadcasting();
  1539.                 if ( hasBroadcasting )
  1540.                     mAlignToolbarPopup->StopBroadcasting();
  1541.                     
  1542.                 mAlignToolbarPopup->SetValue( alignItemNum );
  1543.  
  1544.                 // resume broadcasting
  1545.                 if ( hasBroadcasting )
  1546.                     mAlignToolbarPopup->StartBroadcasting();
  1547.             }
  1548.             break;
  1549.             
  1550.         case cmd_Paragraph_Hierarchical_Menu:
  1551.             if ( !IsDoneLoading() )
  1552.                 return;
  1553.     
  1554.             long formatItemNum;
  1555.             formatItemNum = GetFormatParagraphPopupItem( *GetContext(), outEnabled, outMark );
  1556.             if ( outEnabled && mParagraphToolbarPopup && mParagraphToolbarPopup->IsEnabled() )
  1557.             {
  1558.                 hasBroadcasting = mParagraphToolbarPopup->IsBroadcasting();
  1559.                 if ( hasBroadcasting )
  1560.                     mParagraphToolbarPopup->StopBroadcasting();
  1561.                     
  1562.                 mParagraphToolbarPopup->SetValue( formatItemNum );
  1563.  
  1564.                 // resume broadcasting
  1565.                 if ( hasBroadcasting )
  1566.                     mParagraphToolbarPopup->StartBroadcasting();
  1567.             }
  1568.             break;
  1569.         
  1570.         case cmd_Reload:
  1571.             outEnabled = IsDoneLoading() && !EDT_IS_NEW_DOCUMENT( ((MWContext *)*GetContext()) );
  1572.             break;
  1573.         
  1574.         case cmd_EditSource:
  1575.             {
  1576.             if ( !IsDoneLoading() )
  1577.                 return;
  1578.     
  1579.             // only enable "Edit Source" if it's a local file (so we can make an FSSpec; possibly also backend reasons)
  1580.             History_entry *histentry = mContext->GetCurrentHistoryEntry();
  1581.             outEnabled = histentry && histentry->address && ( 0 == XP_STRNCMP( histentry->address, "file", 4 ) );
  1582.             }
  1583.             break;
  1584.         
  1585.         case cmd_Remove_Links:
  1586.             if ( !IsDoneLoading() )
  1587.                 return;
  1588.     
  1589.             outEnabled = EDT_SelectionContainsLink( *GetContext() );
  1590.             break;
  1591.         
  1592. #if 0
  1593.         case cmd_DisplayTables:
  1594.             outUsesMark = outEnabled = true;
  1595.             outMark = EDT_GetDisplayTables( *GetContext() ) ? checkMark : 0;
  1596.             break;
  1597. #endif
  1598.         
  1599.         case cmd_Format_Target:
  1600.             if ( !IsDoneLoading() )
  1601.                 return;
  1602.     
  1603.             outEnabled = ED_ELEMENT_TARGET == EDT_GetCurrentElementType( *GetContext() );
  1604.             break;
  1605.         
  1606.         case cmd_Format_Unknown_Tag:
  1607.             if ( !IsDoneLoading() )
  1608.                 return;
  1609.     
  1610.             outEnabled = ED_ELEMENT_UNKNOWN_TAG == EDT_GetCurrentElementType( *GetContext() );
  1611.             break;
  1612.         
  1613.         case cmd_Format_DefaultFontColor:
  1614.             if ( !IsDoneLoading() )
  1615.                 return;
  1616.     
  1617.             outUsesMark = outEnabled = CanUseCharFormatting();
  1618.             if ( outUsesMark )
  1619.             {
  1620.                 outMark = 0;
  1621.                 better = EDT_GetCharacterData( *GetContext() );
  1622.                 if ( better )
  1623.                 {
  1624.                     if ( (better->mask & TF_FONT_COLOR) && !(better->values & TF_FONT_COLOR) )
  1625.                         outMark = checkMark;
  1626.                     if ( !(better->mask & TF_FONT_COLOR) )
  1627.                         outMark = dashMark;
  1628.                     EDT_FreeCharacterData( better );
  1629.                 }
  1630.             }
  1631.             break;
  1632.         
  1633. //Table support
  1634.         case cmd_Delete_Table:
  1635.         case cmd_Select_Table:
  1636.             if ( !IsDoneLoading() )
  1637.                 return;
  1638.     
  1639.             outEnabled = EDT_IsInsertPointInTable( *GetContext() );
  1640.             break;
  1641.         
  1642.         case cmd_Format_Table:
  1643.             if ( !IsDoneLoading() )
  1644.                 return;
  1645.     
  1646.             outEnabled = ( EDT_IsInsertPointInTableCell( *GetContext() )
  1647.                 || EDT_IsInsertPointInTableRow( *GetContext() )
  1648.                 || EDT_IsInsertPointInTable( *GetContext() ) );
  1649.             break;
  1650.         
  1651.         case cmd_Insert_Row:
  1652.         case cmd_Insert_Cell:
  1653.         case cmd_Format_Row:
  1654.         case cmd_Delete_Row:
  1655.             if ( !IsDoneLoading() )
  1656.                 return;
  1657.     
  1658.             outEnabled = EDT_IsInsertPointInTableRow( *GetContext() );
  1659.             break;
  1660.         
  1661.         case cmd_Insert_Col:
  1662.         case cmd_Delete_Col:
  1663.         case cmd_Delete_Cell:
  1664.         case cmd_Format_Cell:
  1665.             if ( !IsDoneLoading() )
  1666.                 return;
  1667.     
  1668.             outEnabled = EDT_IsInsertPointInTableCell( *GetContext() );
  1669.             break;
  1670.         
  1671. #if 0
  1672.         case cmd_DisplayTableBoundaries:
  1673.             outEnabled = true;
  1674.             Boolean areTableBordersVisible;
  1675.             areTableBordersVisible = EDT_GetDisplayTables( *GetContext() );
  1676.             index = (areTableBordersVisible) ? EDITOR_MENU_HIDE_TABLE_BORDERS : EDITOR_MENU_SHOW_TABLE_BORDERS;
  1677.             ::GetIndString( outName, STRPOUND_EDITOR_MENUS, index );
  1678.             break;
  1679. #endif
  1680.         
  1681.         case cmd_DisplayParagraphMarks:
  1682.             outEnabled = true;
  1683.             index = mDisplayParagraphMarks ? EDITOR_MENU_HIDE_PARA_SYMBOLS 
  1684.                                             : EDITOR_MENU_SHOW_PARA_SYMBOLS;
  1685.             ::GetIndString( outName, STRPOUND_EDITOR_MENUS, index );
  1686.             break;
  1687.         
  1688.         case cmd_Cut:
  1689.         case cmd_Clear:
  1690.             if ( !IsDoneLoading() )
  1691.                 return;
  1692.     
  1693.             outEnabled = LO_HaveSelection( *GetContext() )
  1694.                         && EDT_CanCut( *GetContext(), true ) == EDT_COP_OK;
  1695.             break;
  1696.         
  1697.         case cmd_Copy:
  1698.             outEnabled = IsDoneLoading() && LO_HaveSelection( *GetContext() )
  1699.                         && EDT_CanCopy( *GetContext(), true ) == EDT_COP_OK;
  1700.             break;
  1701.         
  1702.         case cmd_Paste:
  1703.             if ( !IsDoneLoading() )
  1704.                 return;
  1705.     
  1706.             Int32    offset;
  1707.             outEnabled = EDT_CanPaste( *GetContext(), true ) == EDT_COP_OK
  1708.                         && (::GetScrap( NULL, 'TEXT', &offset ) > 0)
  1709.                             || (::GetScrap( NULL, 'EHTM', &offset ) > 0)
  1710.                             || (::GetScrap( NULL, 'PICT', &offset ) > 0);
  1711.             break;
  1712.  
  1713.         case cmd_SelectAll:
  1714.             outEnabled = IsDoneLoading();
  1715.             break;
  1716.         
  1717.         case cmd_BrowseDocument:
  1718.             if ( !IsDoneLoading() )
  1719.                 return;
  1720.     
  1721.             if ( !XP_IsContextBusy( *GetContext() ) &&
  1722.                     !Memory_MemoryIsLow())
  1723.                 outEnabled = true;
  1724.             break;
  1725.         
  1726.         case cmd_Save:        // only enable if file is dirty or new
  1727.             if ( !IsDoneLoading() )
  1728.                 return;
  1729.     
  1730.             outEnabled = ( EDT_DirtyFlag( *GetContext() ) 
  1731.                         || EDT_IS_NEW_DOCUMENT( ((MWContext *)*GetContext()) ) );
  1732.             break;
  1733.         
  1734.         case CRecentEditMenuAttachment::cmd_ID_toSearchFor:
  1735.             outEnabled = true;
  1736.             break;
  1737.         
  1738.         case cmd_SaveAs:
  1739.         case cmd_InsertEdit_Target:
  1740.         case cmd_InsertEditLink:
  1741.         case cmd_InsertEditImage:
  1742.         case cmd_InsertEditLine:
  1743.         case cmd_Insert_Table:
  1744.         case cmd_Insert_Target:
  1745.         case cmd_Insert_Unknown_Tag:
  1746.         case cmd_Insert_Link:
  1747.         case cmd_Insert_Image:
  1748.         case cmd_Insert_Line:
  1749.         case cmd_Insert_Object:
  1750.         case cmd_FormatColorsAndImage:
  1751.             outEnabled = IsDoneLoading();
  1752.             break;
  1753.         
  1754.         
  1755. #if 0
  1756.         case cmd_Insert_NonbreakingSpace:
  1757. #endif
  1758.         case cmd_Insert_BreakBelowImage:            // is this always available?
  1759.         case cmd_Insert_LineBreak:
  1760.             outEnabled = IsDoneLoading() && 
  1761.                         ED_ELEMENT_TEXT == EDT_GetCurrentElementType( *GetContext() );
  1762.         break;
  1763.                 
  1764. // Edit Menu
  1765.         case cmd_Undo:
  1766.         case cmd_Redo:
  1767.             {
  1768.             if ( !IsDoneLoading() )
  1769.                 return;
  1770.     
  1771.             Boolean isUndoEnabled;
  1772.             outEnabled = isUndoEnabled = EDT_GetUndoCommandID( *GetContext(), 0 ) != CEDITCOMMAND_ID_NULL;
  1773.             if ( !isUndoEnabled )
  1774.             {    // check if redo should be enabled
  1775.                 outEnabled = EDT_GetRedoCommandID( *GetContext(), 0 ) != CEDITCOMMAND_ID_NULL;
  1776.                 if ( outEnabled && inCommand != cmd_Redo )    // reset only if not already set
  1777.                     SetMenuCommandAndString( inCommand, cmd_Redo, STRPOUND_EDITOR_MENUS, EDITOR_MENU_REDO, outName );
  1778.             }
  1779.             else if ( inCommand != cmd_Undo )
  1780.                 SetMenuCommandAndString( inCommand, cmd_Undo, STRPOUND_EDITOR_MENUS, EDITOR_MENU_UNDO, outName );
  1781.             }
  1782.             break;
  1783.         
  1784.         case cmd_Format_Paragraph_Normal:
  1785.             if ( !IsDoneLoading() )
  1786.                 return;
  1787.     
  1788.             outUsesMark = outEnabled = CanUseCharFormatting();
  1789.             if ( outUsesMark )
  1790.                 outMark = P_NSDT == EDT_GetParagraphFormatting( *GetContext() )
  1791.                             ? checkMark : 0;
  1792.             break;
  1793.         
  1794.         case cmd_Format_Paragraph_Head1:
  1795.         case cmd_Format_Paragraph_Head2:
  1796.         case cmd_Format_Paragraph_Head3:
  1797.         case cmd_Format_Paragraph_Head4:
  1798.         case cmd_Format_Paragraph_Head5:
  1799.         case cmd_Format_Paragraph_Head6:
  1800.             if ( !IsDoneLoading() )
  1801.                 return;
  1802.     
  1803.             outUsesMark = outEnabled = CanUseCharFormatting();
  1804.             if ( outUsesMark )
  1805.                 outMark = EDT_GetParagraphFormatting( *GetContext() )
  1806.                             == (inCommand - cmd_Format_Paragraph_Head1 + P_HEADER_1) ? checkMark : 0;
  1807.             break;
  1808.  
  1809.         case cmd_Format_Paragraph_Address:
  1810.             if ( !IsDoneLoading() )
  1811.                 return;
  1812.     
  1813.             outUsesMark = outEnabled = CanUseCharFormatting();
  1814.             if ( outUsesMark )
  1815.                 outMark = P_ADDRESS == EDT_GetParagraphFormatting( *GetContext() )
  1816.                              ? checkMark : 0;
  1817.             break;
  1818.         
  1819.         case cmd_Format_Paragraph_Formatted:
  1820.             if ( !IsDoneLoading() )
  1821.                 return;
  1822.     
  1823.             outUsesMark = outEnabled = CanUseCharFormatting();
  1824.             if ( outUsesMark )
  1825.                 outMark = P_PREFORMAT == EDT_GetParagraphFormatting( *GetContext() )
  1826.                             ? checkMark : 0;
  1827.             break;
  1828.         
  1829.         case cmd_Format_Paragraph_List_Item:
  1830.             if ( !IsDoneLoading() )
  1831.                 return;
  1832.     
  1833.             outUsesMark = outEnabled = CanUseCharFormatting();
  1834.             if ( outUsesMark )
  1835.                 outMark = P_LIST_ITEM == EDT_GetParagraphFormatting( *GetContext() )
  1836.                             ? checkMark : 0;
  1837.             break;
  1838.         
  1839.         case cmd_Format_Paragraph_Desc_Title:
  1840.             if ( !IsDoneLoading() )
  1841.                 return;
  1842.     
  1843.             outUsesMark = outEnabled = CanUseCharFormatting();
  1844.             if ( outUsesMark )
  1845.                 outMark = P_DESC_TITLE == EDT_GetParagraphFormatting( *GetContext() )
  1846.                             ? checkMark : 0;
  1847.             break;
  1848.         
  1849.         case cmd_Format_Paragraph_Desc_Text:
  1850.             if ( !IsDoneLoading() )
  1851.                 return;
  1852.     
  1853.             outUsesMark = outEnabled = CanUseCharFormatting();
  1854.             if ( outUsesMark )
  1855.                 outMark = P_DESC_TEXT == EDT_GetParagraphFormatting( *GetContext() )
  1856.                             ? checkMark : 0;
  1857.             break;
  1858.  
  1859.         case cmd_Bold:    // cmd_Format_Character_Bold
  1860.             if ( !IsDoneLoading() )
  1861.                 return;
  1862.     
  1863.             outUsesMark = outEnabled = CanUseCharFormatting();
  1864.             if ( outUsesMark )
  1865.             {
  1866.                 outMark = 0;
  1867.                 better = EDT_GetCharacterData( *GetContext() );
  1868.                 if ( better )
  1869.                 {
  1870.                     if ( (better->mask & TF_BOLD) && (better->values & TF_BOLD) )
  1871.                         outMark = checkMark;
  1872.                     if ( !(better->mask & TF_BOLD) )
  1873.                         outMark = dashMark;
  1874.                     EDT_FreeCharacterData( better );
  1875.                 }
  1876.             }
  1877.             break;
  1878.         
  1879.         case cmd_Italic:    // cmd_Format_Character_Italic
  1880.             if ( !IsDoneLoading() )
  1881.                 return;
  1882.     
  1883.             outUsesMark = outEnabled = CanUseCharFormatting();
  1884.             if ( outUsesMark )
  1885.             {
  1886.                 outMark = 0;
  1887.                 better = EDT_GetCharacterData( *GetContext() );
  1888.                 if ( better )
  1889.                 {
  1890.                     if ( (better->mask & TF_ITALIC) && (better->values & TF_ITALIC) )
  1891.                         outMark = checkMark;
  1892.                     if ( !(better->mask & TF_ITALIC) )
  1893.                         outMark = dashMark;
  1894.                     EDT_FreeCharacterData( better );
  1895.                 }
  1896.             }
  1897.             break;
  1898.  
  1899.         case cmd_Underline:        // cmd_Format_Character_Underline
  1900.             if ( !IsDoneLoading() )
  1901.                 return;
  1902.     
  1903.             outUsesMark = outEnabled = CanUseCharFormatting();
  1904.             if ( outUsesMark )
  1905.             {
  1906.                 outMark = 0;
  1907.                 better = EDT_GetCharacterData( *GetContext() );
  1908.                 if ( better )
  1909.                 {
  1910.                     if ( (better->mask & TF_UNDERLINE) && (better->values & TF_UNDERLINE) )
  1911.                         outMark = checkMark;
  1912.                     if ( !(better->mask & TF_UNDERLINE) )
  1913.                         outMark = dashMark;
  1914.                     EDT_FreeCharacterData( better );
  1915.                 }
  1916.             }
  1917.             break;
  1918.         
  1919.         case cmd_Format_Character_Nonbreaking:
  1920.             if ( !IsDoneLoading() )
  1921.                 return;
  1922.     
  1923.             outUsesMark = outEnabled = CanUseCharFormatting();
  1924.             if ( outUsesMark )
  1925.             {
  1926.                 outMark = 0;
  1927.                 better = EDT_GetCharacterData( *GetContext() );
  1928.                 if ( better )
  1929.                 {
  1930.                     if ( (better->mask & TF_NOBREAK) && (better->values & TF_NOBREAK) )
  1931.                         outMark = checkMark;
  1932.                     if ( !(better->mask & TF_NOBREAK) )
  1933.                         outMark = dashMark;
  1934.                     EDT_FreeCharacterData( better );
  1935.                 }
  1936.             }
  1937.             break;
  1938.         
  1939.         case cmd_Format_Character_Superscript:
  1940.             if ( !IsDoneLoading() )
  1941.                 return;
  1942.     
  1943.             outUsesMark = outEnabled = CanUseCharFormatting();
  1944.             if ( outUsesMark )
  1945.             {
  1946.                 outMark = 0;
  1947.                 better = EDT_GetCharacterData( *GetContext() );
  1948.                 if ( better )
  1949.                 {
  1950.                     if ( (better->mask & TF_SUPER) && (better->values & TF_SUPER) )
  1951.                         outMark = checkMark;
  1952.                     if ( !(better->mask & TF_SUPER) )
  1953.                         outMark = dashMark;
  1954.                     EDT_FreeCharacterData( better );
  1955.                 }
  1956.             }
  1957.             break;
  1958.         
  1959.         case cmd_Format_Character_Subscript:
  1960.             if ( !IsDoneLoading() )
  1961.                 return;
  1962.     
  1963.             outUsesMark = outEnabled = CanUseCharFormatting();
  1964.             if ( outUsesMark )
  1965.             {
  1966.                 outMark = 0;
  1967.                 better = EDT_GetCharacterData( *GetContext() );
  1968.                 if ( better )
  1969.                 {
  1970.                     if ( (better->mask & TF_SUB) && (better->values & TF_SUB) )
  1971.                         outMark = checkMark;
  1972.                     if ( !(better->mask & TF_SUB) )
  1973.                         outMark = dashMark;
  1974.                     EDT_FreeCharacterData( better );
  1975.                 }
  1976.             }
  1977.             break;
  1978.         
  1979.         case cmd_Format_Character_Strikeout:
  1980.             if ( !IsDoneLoading() )
  1981.                 return;
  1982.     
  1983.             outUsesMark = outEnabled = CanUseCharFormatting();
  1984.             if ( outUsesMark )
  1985.             {
  1986.                 outMark = 0;
  1987.                 better = EDT_GetCharacterData( *GetContext() );
  1988.                 if ( better )
  1989.                 {
  1990.                     if ( (better->mask & TF_STRIKEOUT) && (better->values & TF_STRIKEOUT) )
  1991.                         outMark = checkMark;
  1992.                     if ( !(better->mask & TF_STRIKEOUT) )
  1993.                         outMark = dashMark;
  1994.                     EDT_FreeCharacterData( better );
  1995.                 }
  1996.             }
  1997.             break;
  1998.         
  1999.         case cmd_Format_Character_Blink:
  2000.             if ( !IsDoneLoading() )
  2001.                 return;
  2002.     
  2003.             outUsesMark = outEnabled = CanUseCharFormatting();
  2004.             if ( outUsesMark )
  2005.             {
  2006.                 outMark = 0;
  2007.                 better = EDT_GetCharacterData( *GetContext() );
  2008.                 if ( better )
  2009.                 {
  2010.                     if ( (better->mask & TF_BLINK) && (better->values & TF_BLINK) )
  2011.                         outMark = checkMark;
  2012.                     if ( !(better->mask & TF_BLINK) )
  2013.                         outMark = dashMark;
  2014.                     EDT_FreeCharacterData( better );
  2015.                 }
  2016.             }
  2017.             break;
  2018.         
  2019.         case cmd_Format_Font_Size_N2:
  2020.         case cmd_Format_Font_Size_N1:
  2021.         case cmd_Format_Font_Size_0:
  2022.         case cmd_Format_Font_Size_P1:
  2023.         case cmd_Format_Font_Size_P2:
  2024.         case cmd_Format_Font_Size_P3:
  2025.         case cmd_Format_Font_Size_P4:
  2026.             if ( !IsDoneLoading() )
  2027.                 return;
  2028.     
  2029.             outUsesMark = outEnabled = CanUseCharFormatting();
  2030.             if ( outUsesMark )
  2031.             {
  2032.                 outMark = 0;
  2033.                 better = EDT_GetCharacterData( *GetContext() );
  2034.                 if ( better )
  2035.                 {
  2036.                     if ((better->mask & TF_FONT_SIZE) && better->iSize == (inCommand - cmd_Format_Font_Size_N2 + 1))
  2037.                         outMark = checkMark;
  2038.                     EDT_FreeCharacterData( better );
  2039.                 }
  2040.             }
  2041.             break;
  2042.  
  2043.         case cmd_JustifyLeft:    // cmd_AlignParagraphLeft
  2044.         case cmd_JustifyCenter:    // cmd_AlignParagraphCenter
  2045.         case cmd_JustifyRight:    // cmd_AlignParagraphRight
  2046.             if ( !IsDoneLoading() )
  2047.                 return;
  2048.     
  2049.             outEnabled = CanUseCharFormatting();
  2050.             if ( outEnabled )
  2051.             {
  2052.                 int alignItemNum = GetAlignmentMenuItemNum( *GetContext(),
  2053.                                                     outEnabled );
  2054.                 outUsesMark = true;
  2055.                 if ( ((alignItemNum == 1) && (inCommand == cmd_JustifyLeft)) 
  2056.                 || ((alignItemNum == 2) && (inCommand == cmd_JustifyCenter))
  2057.                 || ((alignItemNum == 3) && (inCommand == cmd_JustifyRight)) )
  2058.                     outMark = checkMark;
  2059.                 else
  2060.                     outMark = 0;
  2061.             }
  2062.             break;
  2063.  
  2064.         case cmd_Format_FontColor:
  2065.         case cmd_Format_Character_ClearAll:
  2066.         case cmd_Format_Paragraph_Indent:
  2067.         case cmd_Format_Paragraph_UnIndent:
  2068.             if ( !IsDoneLoading() )
  2069.                 return;
  2070.     
  2071.             outEnabled = CanUseCharFormatting();
  2072.             break;
  2073.         
  2074.         case cmd_Format_Text:    // Attributes
  2075.         {
  2076.             if ( !IsDoneLoading() )
  2077.                 return;
  2078.     
  2079.             outEnabled = true;
  2080.             if ( CanUseCharFormatting() )
  2081.             {
  2082.                 if ( EDT_CanSetHREF( *GetContext() ) && EDT_GetHREF( *GetContext() ))
  2083.                     index = EDITOR_MENU_LINK_ATTRIBUTES;
  2084.                 else
  2085.                 {
  2086.                     index = EDITOR_MENU_CHARACTER_ATTRIBS;
  2087.                     if ( ED_ELEMENT_SELECTION == EDT_GetCurrentElementType( *GetContext() ) ) 
  2088.                     {
  2089.                         // if no elements are text characteristics then--> outEnabled = false;
  2090.                         outEnabled = EDT_CanSetCharacterAttribute( *GetContext() );
  2091.                     }
  2092.                 }
  2093.             }
  2094.             else
  2095.             {
  2096.                 switch ( EDT_GetCurrentElementType( *GetContext() ) )
  2097.                 {
  2098.                     case ED_ELEMENT_IMAGE:    index = EDITOR_MENU_IMAGE_ATTRIBUTES;    break;
  2099.                     case ED_ELEMENT_HRULE:    index = EDITOR_MENU_LINE_ATTRIBUTES;    break;
  2100.                     case ED_ELEMENT_TARGET:    index = EDITOR_MENU_TARGET_ATTRIBUTES;    break;
  2101.                     case ED_ELEMENT_UNKNOWN_TAG:    index = EDITOR_MENU_UNKNOWN_ATTRIBUTES;    break;
  2102.                     default:
  2103.                         index = EDITOR_MENU_CHARACTER_ATTRIBS;    
  2104.                         outEnabled = false;
  2105.                         break;
  2106.                 }
  2107.             }        
  2108.             
  2109.             if ( index )
  2110.                 ::GetIndString( outName, STRPOUND_EDITOR_MENUS, index );
  2111.         }
  2112.             break;
  2113.         
  2114.         case msg_MakeNoList:
  2115.         case msg_MakeNumList:
  2116.         case msg_MakeUnumList:
  2117.             if ( !IsDoneLoading() )
  2118.                 return;
  2119.     
  2120.             outEnabled = true;
  2121.             outUsesMark = true;
  2122.             outMark = 0;
  2123.             
  2124.             if ( P_LIST_ITEM == EDT_GetParagraphFormatting( *GetContext() ) )
  2125.             {
  2126.                 EDT_ListData *list = EDT_GetListData( *GetContext() );
  2127.                 if ( list )
  2128.                 {
  2129.                     if ( inCommand == msg_MakeNoList )
  2130.                         ;    // already 0
  2131.                     else if ( inCommand == msg_MakeUnumList )
  2132.                         outMark = ( list->iTagType == P_UNUM_LIST ) ? checkMark : 0;
  2133.                     else if ( inCommand == msg_MakeNumList )
  2134.                         outMark = ( list->iTagType == P_NUM_LIST ) ? checkMark : 0;
  2135.  
  2136.                     EDT_FreeListData( list );
  2137.                 }
  2138.             }
  2139.             else if (inCommand == msg_MakeNoList )
  2140.                 outMark = checkMark;
  2141.             break;
  2142.         
  2143.         case cmd_FontSmaller:    // cmd_DecreaseFontSize
  2144.         case cmd_FontLarger:    // cmd_IncreaseFontSize
  2145.             outEnabled = IsDoneLoading();
  2146.             break;
  2147.         
  2148.         case cmd_DocumentInfo:
  2149.             outEnabled = IsDoneLoading() && !EDT_IS_NEW_DOCUMENT( ((MWContext *)*GetContext()) );
  2150.             break;
  2151.         
  2152.         default:
  2153.             if (inCommand >= COLOR_POPUP_MENU_BASE 
  2154.             && inCommand <= COLOR_POPUP_MENU_BASE_LAST)
  2155.             {
  2156.                 // if we haven't finished initializing yet nothing should be enabled
  2157.                 
  2158.                 outEnabled = IsDoneLoading();
  2159.                 if ( !outEnabled )
  2160.                     return;
  2161.  
  2162.                 if ( mColorPopup && mColorPopup->IsEnabled() )
  2163.                 {
  2164.                     hasBroadcasting = mColorPopup->IsBroadcasting();
  2165.                     if ( hasBroadcasting )
  2166.                         mColorPopup->StopBroadcasting();
  2167.         
  2168.                     if ( CanUseCharFormatting() )
  2169.                     {
  2170.                          better = EDT_GetCharacterData( *GetContext() );
  2171.                          if ( better && better->pColor )
  2172.                          {
  2173.                             RGBColor    rgbColor;
  2174.                             short        mItem;
  2175.  
  2176.                             rgbColor.red = (better->pColor->red << 8);
  2177.                             rgbColor.green = (better->pColor->green << 8);
  2178.                             rgbColor.blue = (better->pColor->blue << 8);
  2179.                             mItem = mColorPopup->GetMenuItemFromRGBColor( &rgbColor );
  2180.                             
  2181.                             // if it's a last resort (current item), set menu string
  2182.                             if ( mItem == CColorPopup::CURRENT_COLOR_ITEM )
  2183.                             {
  2184.                                 // set control to the color that just got picked
  2185.                                 Str255 colorstr;
  2186.                                 XP_SPRINTF( (char *)&colorstr[2], "%02X%02X%02X", better->pColor->red, better->pColor->green, better->pColor->blue);
  2187.                                 colorstr[1] = CColorPopup::CURRENT_COLOR_CHAR;    // put in leading character
  2188.                                 colorstr[0] = strlen( (char *)&colorstr[1] );
  2189.                                 mColorPopup->SetDescriptor( colorstr );
  2190.                                 ::SetMenuItemText( mColorPopup->GetMenu()->GetMacMenuH(), 
  2191.                                                     CColorPopup::CURRENT_COLOR_ITEM, 
  2192.                                                     (unsigned char *)&colorstr );
  2193.                             }
  2194.                             mColorPopup->SetValue( mItem );
  2195.                         }
  2196.                         if ( better )
  2197.                             EDT_FreeCharacterData( better );
  2198.                     }
  2199.                     
  2200.                     // resume broadcasting
  2201.                     if ( hasBroadcasting )
  2202.                         mColorPopup->StartBroadcasting();
  2203.                 }
  2204.             }
  2205.             else
  2206.                 CHTMLView::FindCommandStatus( inCommand, outEnabled, outUsesMark, outMark, outName );
  2207.     }
  2208.     
  2209.     // force menu items to update (checkMarks and text (Undo/Redo) could change)
  2210.     {
  2211.     StUseCharFormattingCache stCharFormat( *this );
  2212.     LCommander::SetUpdateCommandStatus( true );
  2213.     }
  2214. }
  2215.  
  2216.  
  2217. Boolean CEditView::FindCommandStatusForContextMenu(
  2218.     CommandT inCommand,
  2219.     Boolean    &outEnabled,
  2220.     Boolean    &outUsesMark,
  2221.     Char16    &outMark,
  2222.     Str255    outName)
  2223. {
  2224. #pragma unused( outUsesMark, outMark )
  2225.  
  2226.     // We come here only if a CContextMenuAttachment is installed.
  2227.     // Return true if we want to bypass standard status processing.
  2228.     if ( !mCurrentClickRecord )
  2229.         return false;
  2230.     
  2231.     CHTMLClickRecord& cr = *mCurrentClickRecord; // for brevity.
  2232.     Boolean isAnchor = false;
  2233.     Boolean isImage = false;
  2234.     Boolean isTable = false;
  2235.     if ( cr.mElement )
  2236.     {
  2237.         isAnchor = cr.IsAnchor();
  2238.         isImage = !isAnchor && cr.mElement->type == LO_IMAGE
  2239.                 && NET_URL_Type(mContext->GetCurrentURL()) != FTP_TYPE_URL;
  2240.         isTable = cr.mElement->type == LO_TABLE;
  2241.     }
  2242.     switch ( inCommand )
  2243.     {
  2244.         case cmd_Format_Text:
  2245.         {
  2246.             short index = 0;
  2247.             outEnabled = true;
  2248.  
  2249.             if ( mCurrentClickRecord && mCurrentClickRecord->GetLayoutElement()
  2250.             && mCurrentClickRecord->GetLayoutElement()->type == LO_TEXT )
  2251.             {
  2252.                 if ( EDT_CanSetHREF( *GetContext() ) && EDT_GetHREF( *GetContext() ) )
  2253.                     index = EDITOR_MENU_LINK_ATTRIBUTES;
  2254.                 else
  2255.                 {
  2256.                     index = EDITOR_MENU_CHARACTER_ATTRIBS;
  2257.                     if ( ED_ELEMENT_SELECTION == EDT_GetCurrentElementType( *GetContext() ) ) 
  2258.                     {
  2259.                         // if no elements are text characteristics then--> outEnabled = false;
  2260.                         outEnabled = EDT_CanSetCharacterAttribute( *GetContext() );
  2261.                     }
  2262.                 }
  2263.             }
  2264.             else
  2265.             {
  2266.                 if ( isAnchor )
  2267.                     index = EDITOR_MENU_TARGET_ATTRIBUTES;
  2268.                 else
  2269.                 {
  2270.                     switch ( cr.mElement->type )
  2271.                     {
  2272.                         case LO_IMAGE:    index = EDITOR_MENU_IMAGE_ATTRIBUTES;    break;
  2273.                         case LO_HRULE:    index = EDITOR_MENU_LINE_ATTRIBUTES;    break;
  2274.                         case LO_UNKNOWN: index = EDITOR_MENU_UNKNOWN_ATTRIBUTES;    break;
  2275.                         default:
  2276.                             index = EDITOR_MENU_CHARACTER_ATTRIBS;    
  2277.                             outEnabled = false;
  2278.                             break;
  2279.                     }
  2280.                 }
  2281.                 
  2282.             }
  2283.             
  2284.             if ( index )
  2285.                 ::GetIndString( outName, STRPOUND_EDITOR_MENUS, index );
  2286.             return true;
  2287.             break;
  2288.         }
  2289.         
  2290.         case cmd_Format_Table:
  2291.         case cmd_Insert_Row:
  2292.         case cmd_Delete_Row:
  2293.         case cmd_Insert_Col:
  2294.         case cmd_Delete_Col:
  2295.         case cmd_Insert_Cell:
  2296.         case cmd_Delete_Cell:
  2297.         case cmd_Delete_Table:
  2298.             outEnabled = isTable;
  2299.             return true;
  2300.             break;
  2301.     
  2302.         case cmd_Insert_Image:
  2303.         case cmd_Insert_Link:
  2304.             outEnabled = ( mCurrentClickRecord && mCurrentClickRecord->GetLayoutElement()
  2305.                         && mCurrentClickRecord->GetLayoutElement()->type == LO_TEXT );
  2306.             return true;
  2307.             break;
  2308.         
  2309.         case cmd_Insert_Table:
  2310.             outEnabled = true;    // always enabled (?!?); even if image or hrule selected (!!!)
  2311.             return true;
  2312.             break;
  2313.  
  2314.         case cmd_NEW_WINDOW_WITH_FRAME:
  2315.             outEnabled = ((MWContext *)*GetContext())->is_grid_cell
  2316.                             && (GetContext()->GetCurrentHistoryEntry() != NULL);
  2317.             return true;
  2318.         
  2319.         case cmd_OPEN_LINK:
  2320.             outEnabled = isAnchor;
  2321.             return true;
  2322.         
  2323.         case cmd_AddToBookmarks:
  2324.             if ( isAnchor )
  2325.                 outEnabled = true;
  2326.             return true; // for now, only have a "add bookmark for this link" command.
  2327.  
  2328.         case cmd_SAVE_LINK_AS:
  2329.             outEnabled = isAnchor;
  2330.             return true; // we don't know unless it's an anchor
  2331.  
  2332.         case cmd_COPY_LINK_LOC:
  2333.             outEnabled = isAnchor && mCurrentClickRecord->mClickURL.length() > 0;
  2334.             return true;
  2335.  
  2336.         case cmd_VIEW_IMAGE:
  2337.         case cmd_SAVE_IMAGE_AS:
  2338.         case cmd_COPY_IMAGE:
  2339.         case cmd_COPY_IMAGE_LOC:
  2340.         case cmd_LOAD_IMAGE:
  2341.             outEnabled = isImage;
  2342.             return true;
  2343.     }
  2344.  
  2345.     return false; // we don't know about it
  2346. } // CEditView::FindCommandStatusForContextMenu
  2347.  
  2348.  
  2349. void CEditView::TakeOffDuty()
  2350. {
  2351.     RemoveCaret();
  2352.     CHTMLView::TakeOffDuty();
  2353. }
  2354.  
  2355.  
  2356. void CEditView::PutOnDuty(LCommander *inNewTarget)
  2357. {
  2358.     mCaretActive = true;
  2359.     StartIdling();
  2360.     CHTMLView::PutOnDuty( inNewTarget );
  2361. }
  2362.  
  2363.  
  2364. Boolean CEditView::IsMouseInSelection( SPoint32 pt, CL_Layer *curLayer, Rect& selectRect )
  2365. {
  2366. #pragma unused(curLayer)
  2367.  
  2368.     Boolean returnValue = false;
  2369.     
  2370.     // zero out rectangle
  2371.     selectRect.top = selectRect.bottom = selectRect.left = selectRect.right = 0;
  2372.     
  2373.     int32 start_selection, end_selection;
  2374.     LO_Element *start_element = NULL, *end_element = NULL;
  2375.     CL_Layer *layer = NULL;
  2376.     
  2377.     LO_GetSelectionEndpoints( *GetContext(), &start_element, &end_element, 
  2378.                                 &start_selection, &end_selection, &layer );
  2379.     
  2380.     if ( start_element == NULL )
  2381.         return false;
  2382.     
  2383.     int32 caretX = 0, caretYLow = 0, caretYHigh = 0;
  2384.     returnValue = GetCaretPosition( *GetContext(), start_element, start_selection, 
  2385.                                 &caretX, &caretYLow, &caretYHigh );
  2386.     selectRect.left = caretX;
  2387.     selectRect.top = caretYLow;
  2388.     
  2389.     if ( returnValue )
  2390.         GetCaretPosition( *GetContext(), end_element, end_selection, 
  2391.                                 &caretX, &caretYLow, &caretYHigh );
  2392.     
  2393.     selectRect.right = caretX;
  2394.     selectRect.bottom = caretYHigh;
  2395.     
  2396.     // check if we are actually in the selection
  2397.     if ( returnValue )
  2398.         returnValue = ( pt.h >= selectRect.left && pt.h <= selectRect.right 
  2399.                     && pt.v >= selectRect.top && pt.v <= selectRect.bottom );
  2400.     
  2401.     return returnValue;
  2402. }
  2403.  
  2404.  
  2405. void CEditView::ClickSelf( const SMouseDownEvent &where )
  2406. {
  2407.     if ( !IsTarget() )
  2408.         SwitchTarget( this );
  2409.     
  2410.     FLUSH_JAPANESE_TEXT
  2411.     
  2412.     // the user may have clicked in a new location
  2413.     // erase caret in case it happens to be drawn in the window now
  2414.     EraseCaret();
  2415.     
  2416.     FocusDraw();
  2417.     
  2418.     SPoint32 firstP;
  2419.     LocalToImagePoint( where.whereLocal, firstP );
  2420.  
  2421.     if ( 2 == GetClickCount() )
  2422.     {
  2423.         EDT_DoubleClick( *GetContext(), firstP.h, firstP.v );
  2424.         
  2425.         ED_ElementType edtElemType = EDT_GetCurrentElementType( *GetContext() );
  2426.         
  2427.         if ( ED_ELEMENT_IMAGE == edtElemType )
  2428.             ObeyCommand( cmd_InsertEditImage, NULL);        
  2429.                     
  2430.         else if ( ED_ELEMENT_HRULE == edtElemType )
  2431.             ObeyCommand( cmd_InsertEditLine, NULL);        
  2432.                 
  2433.         else if ( ED_ELEMENT_TARGET == edtElemType )
  2434.             ObeyCommand( cmd_InsertEdit_Target, NULL);        
  2435.                     
  2436.         else if ( ED_ELEMENT_UNKNOWN_TAG == edtElemType )
  2437.             CEditDialog::Start( EDITDLG_UNKNOWN_TAG, *GetContext() );
  2438.                 
  2439.         else if ( ED_ELEMENT_TABLE == edtElemType || ED_ELEMENT_CELL == edtElemType 
  2440.                 || ED_ELEMENT_ROW == edtElemType || ED_ELEMENT_COL == edtElemType )
  2441.             ObeyCommand( cmd_Format_Table, NULL );
  2442.                 
  2443.         else {
  2444. #ifdef LAYERS
  2445.             LO_Element* element = LO_XYToElement( *GetContext(), firstP.h, firstP.v,  0 );
  2446. #else
  2447.             LO_Element* element = LO_XYToElement( *GetContext(), firstP.h, firstP.v );
  2448. #endif
  2449.             
  2450.             Rect selectRect;
  2451.             SMouseDownEvent modifiedEvent( where );
  2452.             if ( IsMouseInSelection( firstP, NULL, selectRect ) )
  2453.             {
  2454.                 // adjust/offset event point by same amount as image point
  2455.                 modifiedEvent.whereLocal.h += ( selectRect.left + 1 - firstP.h );
  2456. //                modifiedEvent.whereLocal.v += ( selectRect.top + 1 - firstP.v );
  2457.                 
  2458.                 firstP.h = selectRect.left + 1;
  2459.                 firstP.v = selectRect.top + 1;
  2460.             }
  2461.                 
  2462.             CHTMLClickRecord cr1( modifiedEvent.whereLocal, firstP, mContext, element );
  2463.             cr1.Recalc();
  2464.  
  2465.             SInt16 mouseAction = cr1.WaitForMouseAction( where.whereLocal, where.macEvent.when, 2 * GetDblTime() );
  2466.  
  2467.             if ( mouseAction == cr1.eMouseDragging )
  2468.             {
  2469.                 ::SafeSetCursor( iBeamCursor );
  2470.                 mDoContinueSelection = true;
  2471.                 ClickTrackSelection( modifiedEvent, cr1 );
  2472.                 mDoContinueSelection = false;
  2473.             }
  2474.         }
  2475.         
  2476.     }
  2477.     else
  2478.     {
  2479.         LO_Element*        element;
  2480. #ifdef LAYERS
  2481.         element = LO_XYToElement( *GetContext(), firstP.h, firstP.v, 0 );
  2482. #else
  2483.         element = LO_XYToElement( *GetContext(), firstP.h, firstP.v );
  2484. #endif
  2485.         CHTMLClickRecord cr2( where.whereLocal, firstP, mContext, element );
  2486.         cr2.Recalc();
  2487.  
  2488.         if ( element != NULL && element->type != LO_IMAGE && element->type != LO_HRULE )
  2489.             ::SafeSetCursor( iBeamCursor );
  2490.         else
  2491.             ::SetCursor( &UQDGlobals::GetQDGlobals()->arrow );
  2492.  
  2493.         Rect selectRect;
  2494.         Boolean isMouseInSelection = IsMouseInSelection( firstP, NULL, selectRect );
  2495.         
  2496.         // check if we should be drag/drop'ing or selecting
  2497.         // if the shift key is down, we're not drag/drop'ing
  2498.         if ( isMouseInSelection && !((where.macEvent.modifiers & shiftKey) != 0) )
  2499.         {
  2500.             Boolean canDragDrop = true /* && PrefSetToDrag&Drop */;
  2501.             if ( canDragDrop )
  2502.             {
  2503.                 ClickTrackSelection( where, cr2 );
  2504.                 // update status bar???
  2505.                 return;
  2506.             }
  2507.         }
  2508.         
  2509.         mDoContinueSelection = !isMouseInSelection;
  2510.         ClickTrackSelection( where, cr2 );
  2511.         mDoContinueSelection = false;
  2512.     }
  2513. }
  2514.  
  2515.  
  2516. // if we are over an edge, track the edge movement
  2517. // otherwise, track the text
  2518. // clean this up with TrackSelection in mclick.cp
  2519. Boolean CEditView::ClickTrackSelection( const SMouseDownEvent& where, 
  2520.                                         CHTMLClickRecord& inClickRecord )
  2521. {
  2522.     long ticks = TickCount();
  2523.     Rect    frame, oldSizingRect;
  2524.     Boolean    didTrackSelection = false, didDisplayAttachment = false;
  2525.     Boolean isSizing = false;
  2526.  
  2527.     StopRepeating();
  2528.     
  2529.     // Text selection
  2530. #ifdef SOMEDAY_MAC_EDITOR_HANDLE_LAYERS
  2531.     XP_Rect theBoundingBox;
  2532.     theBoundingBox.left = theBoundingBox.top = theBoundingBox.right = theBoundingBox.bottom = 0;
  2533.     CL_GetLayerBboxAbsolute(inClickRecord.mLayer, &theBoundingBox);
  2534. #endif
  2535.  
  2536.     
  2537.     // Convert from image to layer coordinates
  2538.     SPoint32 theImagePointStart, theImagePointEnd, newP;
  2539.     LocalToImagePoint( where.whereLocal, theImagePointStart );
  2540.     newP = theImagePointStart;
  2541. #ifdef SOMEDAY_MAC_EDITOR_HANDLE_LAYERS
  2542.     theImagePointStart.h -= theBoundingBox.left;
  2543.     theImagePointStart.v -= theBoundingBox.top;
  2544. #endif
  2545.  
  2546.     theImagePointEnd.h = theImagePointEnd.v = -1;
  2547.     
  2548. // find out what we are doing before we start
  2549. // ARE WE DRAGGING???
  2550.     Rect selectRect;
  2551.     Boolean doDragSelection = IsMouseInSelection( theImagePointStart, NULL, selectRect ) 
  2552.                                 && !((where.macEvent.modifiers & shiftKey) != 0);
  2553.     
  2554. // ARE WE IN TABLE (sizing or selecting)???
  2555.     Boolean bLock = (where.macEvent.modifiers & cmdKey) == cmdKey;
  2556.     
  2557.     LO_Element *pCurrentElement = NULL;
  2558.     ED_HitType iTableHit;
  2559.     Boolean hasSelectedTable = false;
  2560.     iTableHit = EDT_GetTableHitRegion( *GetContext(), newP.h, newP.v, &pCurrentElement, bLock );
  2561.     if ( pCurrentElement )    // we're in some part of a table
  2562.     {
  2563.         if ( iTableHit == ED_HIT_SIZE_TABLE_WIDTH || iTableHit == ED_HIT_SIZE_TABLE_HEIGHT
  2564.         || iTableHit == ED_HIT_SIZE_COL
  2565.         || iTableHit == ED_HIT_ADD_ROWS || iTableHit == ED_HIT_ADD_COLS )
  2566.         {
  2567.             isSizing = true;
  2568.         }
  2569.         else if ( iTableHit != ED_HIT_NONE )
  2570.         {
  2571.             hasSelectedTable =
  2572.                 EDT_SelectTableElement( *GetContext(), newP.h, newP.v, 
  2573.                                     pCurrentElement, iTableHit, bLock,
  2574.                                     (where.macEvent.modifiers & shiftKey) == shiftKey );
  2575.             if ( hasSelectedTable )
  2576.             {
  2577.                 mDoContinueSelection = false;
  2578.                 UpdatePort();
  2579. //            break;    // this bails out of loop on single-click; can't bring up context menu
  2580.             }
  2581.         }
  2582.     }
  2583.     
  2584.     if ( ( pCurrentElement == NULL )                         // we're not in a table or not in table hotspot
  2585.     || ( pCurrentElement &&    iTableHit == ED_HIT_NONE ) )    // get element from click record
  2586.     {
  2587. // ARE WE IN A NON-TABLE SIZEABLE ELEMENT???
  2588.         pCurrentElement = inClickRecord.GetLayoutElement();
  2589.         isSizing = pCurrentElement && EDT_CanSizeObject( *GetContext(), pCurrentElement, newP.h, newP.v );
  2590.  
  2591.         if ( !doDragSelection )
  2592.         {
  2593.             // Setup
  2594.             if ( (where.macEvent.modifiers & shiftKey) != 0 && !inClickRecord.IsClickOnAnchor() )
  2595.                 EDT_ExtendSelection( *GetContext(), theImagePointStart.h, theImagePointStart.v );    // this line modified!
  2596.             else if ( mDoContinueSelection )
  2597.                 EDT_StartSelection( *GetContext(), theImagePointStart.h, theImagePointStart.v );    // this line modified!
  2598.         }
  2599.     }
  2600.  
  2601.     Point    qdWhere;
  2602.     ::GetMouse( &qdWhere );
  2603.     LocalToPortPoint( qdWhere );        // convert qdWhere to port coordinates for cursor update
  2604.     AdjustCursorSelf( qdWhere, where.macEvent );
  2605.         
  2606. // INITIALIZATION FOR RESIZING INLINE
  2607.     XP_Rect    sizeRect;
  2608.     if ( isSizing )
  2609.     {
  2610.         if ( EDT_StartSizing( *GetContext(), pCurrentElement,
  2611.                             newP.h, newP.v, bLock, &sizeRect ) )
  2612.         {
  2613.             UpdatePort();
  2614.             
  2615.             oldSizingRect.top = sizeRect.top;
  2616.             oldSizingRect.bottom = sizeRect.bottom;
  2617.             oldSizingRect.left = sizeRect.left;
  2618.             oldSizingRect.right = sizeRect.right;
  2619.             FocusDraw();
  2620.             DisplaySelectionFeedback( LO_ELE_SELECTED, oldSizingRect );
  2621.         }
  2622.     }
  2623.  
  2624. // BEGIN ACTUAL TRACKING OF MOVEMENT
  2625.     // track mouse till we are done
  2626.     do {
  2627.         FocusDraw();        // so that we get coordinates right
  2628.         ::GetMouse( &qdWhere );
  2629.         
  2630.         if ( AutoScrollImage( qdWhere ) )        // auto-scrolling
  2631.         {    
  2632.             CalcLocalFrameRect( frame );
  2633.             if ( qdWhere.v < frame.top )
  2634.                 qdWhere.v = frame.top;
  2635.             else if ( qdWhere.v > frame.bottom )
  2636.                 qdWhere.v = frame.bottom;
  2637.         }
  2638.         
  2639.         LocalToImagePoint( qdWhere, newP );
  2640.         LocalToPortPoint( qdWhere );        // convert qdWhere to port coordinates for cursor update
  2641.  
  2642. #ifdef SOMEDAY_MAC_EDITOR_HANDLE_LAYERS
  2643.         // Convert from image to layer coordinates
  2644.         newP.h -= theBoundingBox.left;
  2645.         newP.v -= theBoundingBox.top;
  2646. #endif
  2647.  
  2648.         if ( ( newP.v != theImagePointEnd.v ) || ( newP.h != theImagePointEnd.h ) )
  2649.         {
  2650.             if ( doDragSelection )
  2651.             {
  2652.                 // the following code can't be moved out of the StillDown() loop 
  2653.                 // because we need to check if mouse moves so we can bring up
  2654.                 // context menus at the right time
  2655.                 
  2656.                 // if the mouse is not in the selection, then we will be in "move" mode
  2657.                 if ( !IsMouseInSelection( newP, NULL, frame ) )
  2658.                 {
  2659.                     // get data (store!) since selection will change as we move around!
  2660.                     char *ppText = NULL;
  2661.                     int32 pTextLen;
  2662.                     EDT_ClipboardResult result;
  2663.                     
  2664.                     mDragData = NULL;
  2665.                     mDragDataLength = 0;
  2666.                     result = EDT_CopySelection( *GetContext(), &ppText, &pTextLen, 
  2667.                                                 &mDragData, &mDragDataLength );
  2668.                     XP_FREEIF( ppText );
  2669.                     if ( result != EDT_COP_OK || mDragData == NULL )
  2670.                         mDragDataLength = 0;
  2671.                     
  2672.                     // now start the dragging!
  2673.                     ::LocalToGlobal( &topLeft(selectRect) );
  2674.                     ::LocalToGlobal( &botRight(selectRect) );
  2675.                     CComposerDragTask theDragTask( where.macEvent, selectRect, *this );
  2676.                     
  2677.                     OSErr theErr = ::SetDragSendProc(theDragTask.GetDragReference(), mSendDataUPP, (LDragAndDrop*)this);
  2678.                     ThrowIfOSErr_(theErr);
  2679.                     
  2680.                     theDragTask.DoDrag();
  2681.  
  2682.                     XP_FREEIF( mDragData );
  2683.  
  2684.                     return true;
  2685.                 }
  2686.             }
  2687.             else if ( isSizing )
  2688.             {
  2689.                 if ( EDT_GetSizingRect( *GetContext(), newP.h, newP.v, bLock, &sizeRect ) )
  2690.                 {
  2691.                     // Remove last sizing feedback
  2692.                     FocusDraw();
  2693.                     DisplaySelectionFeedback( LO_ELE_SELECTED, oldSizingRect );
  2694.                     
  2695.                     // Save the new rect.
  2696.                     oldSizingRect.top = sizeRect.top;
  2697.                     oldSizingRect.bottom = sizeRect.bottom;
  2698.                     oldSizingRect.left = sizeRect.left;
  2699.                     oldSizingRect.right = sizeRect.right;
  2700.                     
  2701.                     // then draw new feedback
  2702.                     DisplaySelectionFeedback(LO_ELE_SELECTED, oldSizingRect);
  2703.                 }
  2704.             }
  2705.             else
  2706.             {
  2707.                 didTrackSelection = true;
  2708.                 if ( mDoContinueSelection )
  2709.                     EDT_ExtendSelection( *GetContext(), newP.h, newP.v );    // this line is modified!
  2710.             }    
  2711.  
  2712.             // reset clock for context popup menu if mouse hasn't moved much
  2713.             if ( abs(newP.h - theImagePointEnd.h) >= eMouseHysteresis ||
  2714.                 abs(newP.v - theImagePointEnd.v) >= eMouseHysteresis )
  2715.                 ticks = TickCount();
  2716.         }
  2717.         
  2718.         // if mouse hasn't moved, check if it's time to bring up context menu
  2719.         if ( !isSizing 
  2720.             && ( doDragSelection 
  2721.                 || ( newP.v == theImagePointEnd.v ) && ( newP.h == theImagePointEnd.h ) )
  2722.             && TickCount() > ticks + 2 * GetDblTime() )
  2723.         {
  2724.             ::SetCursor( &UQDGlobals::GetQDGlobals()->arrow );
  2725.             SInt16 mouseAction = inClickRecord.WaitForMouseAction( where, this, 2 * GetDblTime() );
  2726.             if ( mouseAction == inClickRecord.eHandledByAttachment )
  2727.             {
  2728.                 didDisplayAttachment = true;
  2729.                 break;
  2730.             }
  2731.             else
  2732.             {
  2733.                 ::GetMouse( &qdWhere );    // local coords; mouse may have moved in WaitForMouseAction?
  2734.                 LocalToPortPoint( qdWhere );
  2735.                 AdjustCursorSelf( qdWhere, where.macEvent );
  2736.             }
  2737.         }
  2738.         
  2739.         theImagePointEnd = newP;
  2740.         
  2741.         // Ñ╩idling
  2742.         SystemTask();
  2743.         EventRecord dummy;
  2744.         ::WaitNextEvent(0, &dummy, 5, NULL);
  2745.     } while ( ::StillDown() );
  2746.     
  2747.     if ( isSizing )
  2748.     {
  2749.         // remove last sizing feedback
  2750.         FocusDraw();
  2751.         DisplaySelectionFeedback( LO_ELE_SELECTED, oldSizingRect );
  2752.  
  2753.         if ( abs(theImagePointStart.h - theImagePointEnd.h) >= eMouseHysteresis
  2754.         || abs(theImagePointStart.v - theImagePointEnd.v) >= eMouseHysteresis )
  2755.             EDT_EndSizing( *GetContext() );
  2756.         else
  2757.         {
  2758.             EDT_CancelSizing( *GetContext() );
  2759.             
  2760.             // move insertion caret
  2761.             EDT_StartSelection( *GetContext(), theImagePointEnd.h, theImagePointEnd.v );
  2762.             EDT_EndSelection( *GetContext(), theImagePointEnd.h, theImagePointEnd.v );
  2763.         }
  2764.     }
  2765.     
  2766.     if ( doDragSelection )
  2767.         return false;
  2768.     
  2769.     ::GetMouse( &qdWhere );
  2770.     LocalToImagePoint( qdWhere, newP );
  2771.     
  2772.     if ( !mDoContinueSelection && !didDisplayAttachment && !isSizing && !hasSelectedTable )
  2773.     {
  2774.         // mouse was in a selection but no context menu displayed
  2775.         EDT_StartSelection( *GetContext(), theImagePointStart.h, theImagePointStart.v );
  2776.         EDT_ExtendSelection( *GetContext(), newP.h, newP.v );    // this line is modified!
  2777.         EDT_EndSelection( *GetContext(), newP.h, newP.v );
  2778.     }
  2779.     else if ( mDoContinueSelection )
  2780.         EDT_EndSelection( *GetContext(), newP.h, newP.v );                // this line modified!
  2781.  
  2782.     return didTrackSelection;
  2783. }
  2784.  
  2785.         
  2786. Boolean 
  2787. CEditView::ItemIsAcceptable( DragReference inDragRef, ItemReference inItemRef )
  2788. {
  2789.     HFSFlavor    fileData;
  2790.     Size        dataSize = sizeof(fileData);
  2791.     FlavorFlags    flags;
  2792.     
  2793.     if ( ::GetFlavorData( inDragRef, inItemRef, flavorTypeHFS, &fileData, &dataSize, 0 ) == noErr )
  2794.         return true;            // we'll take ANY file, at least as a link
  2795.     
  2796.     if (::GetFlavorFlags( inDragRef, inItemRef, emBookmarkDrag, &flags ) == noErr )
  2797.         return true;
  2798.     
  2799.     if ( ::GetFlavorFlags( inDragRef, inItemRef, 'TEXT', &flags ) == noErr )
  2800.         return true;
  2801.  
  2802.     if ( ::GetFlavorFlags( inDragRef, inItemRef, emComposerNativeDrag, &flags ) == noErr )
  2803.         return true; 
  2804.     /*
  2805.     flavorTypePromiseHFS
  2806.     emBookmarkFile
  2807.     emXPBookmarkInternal
  2808.     'TEXT'
  2809.     'ADDR'
  2810.     'ADRS'
  2811.     emBookmarkFileDrag
  2812.     emBookmarkDrag
  2813.     'PICT'
  2814.     MAIL_MESSAGE_FLAVOR
  2815.     TEXT_FLAVOR
  2816.     NEWS_ARTICLE_FLAVOR
  2817.     */
  2818.     
  2819.     return false;
  2820. }
  2821.  
  2822. void CEditView::DoDragSendData(FlavorType inFlavor, ItemReference inItemRef, DragReference inDragRef)
  2823. {
  2824.     if ( inFlavor == emComposerNativeDrag )
  2825.     {
  2826.         OSErr theErr = ::SetDragItemFlavorData( inDragRef, inItemRef,
  2827.                                          inFlavor, mDragData, mDragDataLength, 0 );
  2828.     }
  2829.     else
  2830.         CHTMLView::DoDragSendData( inFlavor, inItemRef, inDragRef );
  2831. }
  2832.  
  2833.  
  2834. void        
  2835. CEditView::InsideDropArea(DragReference    inDragRef)
  2836. {
  2837.     Point        mouseLoc;
  2838.     SPoint32    imagePt;
  2839.         
  2840.     FocusDraw();
  2841.     
  2842.     ::GetDragMouse( inDragRef, &mouseLoc, NULL );
  2843.     ::GlobalToLocal( &mouseLoc );
  2844.     
  2845.     Rect     localFrame;
  2846.     Int32    scrollLeft = 0;
  2847.     Int32    scrollTop = 0;
  2848.     
  2849.     CalcLocalFrameRect( localFrame );
  2850.     if ( mouseLoc.h < (localFrame.left+10) )
  2851.         scrollLeft = -mScrollUnit.h;
  2852.     else if ( mouseLoc.h > (localFrame.right-10) )
  2853.         scrollLeft = mScrollUnit.h;
  2854.     
  2855.     if ( mouseLoc.v < (localFrame.top+10) )
  2856.         scrollTop = -mScrollUnit.v;
  2857.     else if ( mouseLoc.v > (localFrame.bottom-10) )
  2858.         scrollTop = mScrollUnit.v;
  2859.  
  2860.     if ( scrollLeft != 0 || scrollTop != 0 )
  2861.     {
  2862.         if ( ScrollPinnedImageBy( scrollLeft, scrollTop, true ) )
  2863.             Draw(NULL);
  2864.     }
  2865.         
  2866.     LocalToImagePoint( mouseLoc, imagePt );
  2867.     
  2868.     /* set the insert point here so that when the drag is over we can insert in the correct place. */
  2869.     EDT_PositionDropCaret( *GetContext(), imagePt.h, imagePt.v );
  2870. }
  2871.  
  2872.  
  2873. void 
  2874. CEditView::ReceiveDragItem( DragReference inDragRef, DragAttributes inDragAttr, 
  2875.                             ItemReference inItemRef, Rect& inItemBounds    )
  2876. {
  2877. #pragma unused( inDragAttr, inItemBounds )
  2878.  
  2879.     Boolean isImageDropped = false;
  2880.     char *isURLDroppedString = NULL, *isTitleDroppedString = NULL;
  2881.  
  2882.     mIsHilited = false;
  2883.     UnhiliteDropArea( inDragRef );
  2884.     
  2885.     try
  2886.     {    
  2887.         HFSFlavor    fileData;
  2888.         Size        dataSize = sizeof(fileData);
  2889.         OSErr        err;
  2890.         Point        mouseLoc;
  2891.         SPoint32    imagePt;
  2892.         Size        size;
  2893.         FlavorFlags    flags;
  2894.         SInt16        mods, mouseDownModifiers, mouseUpModifiers;
  2895.  
  2896.         err = ::GetDragModifiers( inDragRef, &mods, &mouseDownModifiers, &mouseUpModifiers );
  2897.         if (err != noErr)
  2898.             mouseDownModifiers = 0;
  2899.         Boolean doCopy = ( (mods & optionKey) == optionKey ) || ( (mouseDownModifiers & optionKey) == optionKey );
  2900.         
  2901.         FocusDraw();
  2902.         ::GetDragMouse( inDragRef, &mouseLoc, NULL );
  2903.         ::GlobalToLocal( &mouseLoc );
  2904.         LocalToImagePoint( mouseLoc, imagePt );
  2905.                 
  2906.         if ( ::GetFlavorData( inDragRef, inItemRef, flavorTypeHFS, &fileData, &dataSize, 0 ) == noErr )
  2907.         {
  2908.             switch ( fileData.fileType )
  2909.             {
  2910.                 case 'GIFf':
  2911.                 case 'JPEG':
  2912.                     isImageDropped = true;
  2913.                     isURLDroppedString = CFileMgr::GetURLFromFileSpec( fileData.fileSpec );
  2914.                     isTitleDroppedString = NULL;
  2915.                     break;
  2916.                 
  2917.                 case 'clpt':
  2918.                     /* This implements support for text clippings.  Note: I assume that 
  2919.                        the text clippings are of type 'clpt' and store the text in 'TEXT' 
  2920.                        resource ID 256.  All the examples I found fit this criteria.  
  2921.                        Unfortunately, I couldn't find any Apple documentation that
  2922.                        verified this.  The actual pasting is done below.
  2923.                     */
  2924.                     short resnum = ::FSpOpenResFile( &fileData.fileSpec, fsRdPerm );
  2925.                     if ( -1 != resnum )
  2926.                     {
  2927.                         Handle clipping_text = ::Get1Resource ( 'TEXT', 256 );
  2928.  
  2929.                         if ( clipping_text != NULL )
  2930.                         {        // Assuming we got the resource, create it
  2931.                             int clipping_text_size = ::GetHandleSize( clipping_text );
  2932.                             if ( clipping_text_size > 0 )
  2933.                             {
  2934.                                 char *droppedString = (char *)XP_ALLOC( clipping_text_size + 1 );
  2935.                                 if ( droppedString )
  2936.                                 {
  2937.                                     ::BlockMove( *clipping_text, droppedString, clipping_text_size );
  2938.                                     droppedString[ clipping_text_size ] = '\0';
  2939.                                       EDT_PasteText( *GetContext(), droppedString );
  2940.  
  2941.                                     XP_FREE( droppedString );
  2942.                                 }
  2943.                             }
  2944.                         }
  2945.                         ::CloseResFile( resnum );
  2946.                     }
  2947.                     return;
  2948.                     break;
  2949.                 
  2950.                 default:
  2951.                     char *link = CFileMgr::GetURLFromFileSpec( fileData.fileSpec );
  2952.                     if ( link )
  2953.                     {
  2954.                         Bool bAutoAdjustLinks = CPrefs::GetBoolean( CPrefs::PublishMaintainLinks );
  2955.                         if ( bAutoAdjustLinks )
  2956.                         {
  2957.                             char *abs = NULL;        // lets try making it relative
  2958.                             if ( NET_MakeRelativeURL( LO_GetBaseURL( *GetContext() ), link, &abs )
  2959.                                 != NET_URL_FAIL && abs )
  2960.                             {
  2961.                                 XP_FREE( link );
  2962.                                 link = abs;
  2963.                                 abs = NULL;
  2964.                             }
  2965.                             else if ( abs )
  2966.                                 XP_FREE(abs);
  2967.                         }
  2968.                         
  2969.                         isURLDroppedString = link;
  2970.                         isTitleDroppedString = XP_STRDUP( link );
  2971.                     }
  2972.                     break;
  2973.             }
  2974.         }
  2975.         else if ( ::GetFlavorDataSize( inDragRef, inItemRef, emBookmarkDrag, &size ) == noErr )
  2976.         {
  2977.             char *buffer = (char *)XP_ALLOC( size + 1 );
  2978.             if ( buffer )
  2979.             {
  2980.                 if ( ::GetFlavorData( inDragRef, inItemRef, emBookmarkDrag, buffer, &size, 0 ) == noErr )
  2981.                 {
  2982.                     buffer[ size ] = 0;    // Terminate the string
  2983.                     isURLDroppedString = XP_STRDUP( buffer );
  2984.  
  2985.                     char * title = strchr( isURLDroppedString, '\r' );
  2986.                     if ( title == NULL )
  2987.                     {
  2988.                         // Bookmark without a title
  2989.                         isTitleDroppedString = XP_STRDUP( buffer );
  2990.                     //    EDT_PasteHREF( mContext, &buffer, &buffer, 1);
  2991.                     }
  2992.                     else
  2993.                     {
  2994.                         *title = 0;
  2995.                         title++;
  2996.                         
  2997.                         isImageDropped = (XP_STRCMP(title,"[Image]") == 0);
  2998.                         if ( isImageDropped )
  2999.                         {
  3000.                             isTitleDroppedString = NULL;
  3001.                             
  3002.                             // we need to chop off [Image] from isURLDroppedString
  3003.                             if ( isURLDroppedString )
  3004.                             {
  3005.                                 char *positionMarker = strchr( isURLDroppedString, '\r' );
  3006.                                 if ( positionMarker )
  3007.                                     positionMarker[0] = 0;
  3008.                             }
  3009.                         }
  3010.                         else
  3011.                         {
  3012.                             isTitleDroppedString = XP_STRDUP(title);
  3013.                         //    EDT_PasteHREF( mContext, &buffer, &title, 1);
  3014.                         }
  3015.                     }
  3016.                 }
  3017.                 XP_FREE( buffer );
  3018.             }
  3019.         }
  3020.         else if ( ::GetFlavorFlags( inDragRef, inItemRef, emComposerNativeDrag, &flags ) == noErr )
  3021.         {
  3022.             /* if the mouse is over the selection (in the same window), we shouldn't do anything/just bail out */
  3023.             
  3024.             OSErr err = ::GetFlavorDataSize( inDragRef, inItemRef, emComposerNativeDrag, &size );
  3025.             ThrowIfOSErr_( err );
  3026.             
  3027.             char *datap = (char *)XP_ALLOC( size + 1 );
  3028.             if ( datap )
  3029.             {
  3030.                 if ( noErr == ::GetFlavorData( inDragRef, inItemRef, emComposerNativeDrag, datap, &size, 0 )
  3031.                     && ( size > 0 ) )
  3032.                 {
  3033.                     datap[ size ] = 0;
  3034.                     EDT_BeginBatchChanges( *GetContext() );
  3035.                     if ( doCopy || mDragData == NULL )
  3036.                         EDT_PositionCaret( *GetContext(), mouseLoc.h, mouseLoc.v );
  3037.                     else
  3038.                         EDT_DeleteSelectionAndPositionCaret( *GetContext(), mouseLoc.h, mouseLoc.v );
  3039.                       EDT_PasteHTML( *GetContext(), datap );
  3040.                       EDT_EndBatchChanges( *GetContext() );
  3041.                 } 
  3042.                 XP_FREE( datap );
  3043.             }
  3044.             
  3045.             return;
  3046.         }
  3047.         else if ( ::GetFlavorFlags( inDragRef, inItemRef, 'TEXT', &flags ) == noErr )
  3048.         {
  3049.             /* text being dragged */
  3050.             OSErr err = ::GetFlavorDataSize( inDragRef, inItemRef, 'TEXT', &size );
  3051.             ThrowIfOSErr_ (err); // caught by PP handler
  3052.             
  3053.             char *lDroppedString = (char *)XP_ALLOC( size + 1 );
  3054.             if ( lDroppedString )
  3055.             {
  3056.                 if ( ::GetFlavorData( inDragRef, inItemRef, 'TEXT', lDroppedString, &size, 0 ) == noErr )
  3057.                 {
  3058.                     lDroppedString[ size ] = 0;
  3059.                       EDT_PasteText( *GetContext(), lDroppedString );
  3060.                 } 
  3061.                 XP_FREE( lDroppedString );
  3062.             }
  3063.             
  3064.             return;
  3065.         }
  3066.         
  3067.     }
  3068.     catch(...)
  3069.     {
  3070.     }
  3071.     
  3072.     if ( isURLDroppedString )
  3073.     {
  3074.         if ( isImageDropped )
  3075.         {
  3076.             EDT_ImageData* imageData = EDT_NewImageData(); 
  3077.             if ( imageData )
  3078.             {
  3079.                 imageData->pSrc = isURLDroppedString;
  3080.                 EDT_InsertImage( *GetContext(), imageData, CPrefs::GetBoolean( CPrefs::PublishKeepImages ) );
  3081.                 EDT_FreeImageData( imageData );
  3082.             }
  3083.             
  3084.             XP_FREEIF( isTitleDroppedString );
  3085.             isURLDroppedString = NULL;
  3086.             isTitleDroppedString = NULL;
  3087.         }
  3088.         else
  3089.         {
  3090.             if ( isTitleDroppedString )
  3091.                 EDT_PasteHREF( *GetContext(), &isURLDroppedString, &isTitleDroppedString, 1 );
  3092.             else
  3093.                 EDT_PasteHREF( *GetContext(), &isURLDroppedString, &isURLDroppedString, 1 );
  3094.             
  3095.             XP_FREE( isURLDroppedString );
  3096.             XP_FREEIF( isTitleDroppedString );
  3097.             isURLDroppedString = NULL;
  3098.             isTitleDroppedString = NULL;
  3099.         }
  3100.     }
  3101. }
  3102.  
  3103.  
  3104. void CEditView::InsertDefaultLine()
  3105. {
  3106.     EDT_HorizRuleData *pData = EDT_NewHorizRuleData();    
  3107.     if ( pData )
  3108.     {
  3109.         EDT_InsertHorizRule( *GetContext(), pData );
  3110.         EDT_FreeHorizRuleData( pData );
  3111.     }
  3112. }
  3113.  
  3114.  
  3115. // should be XP code (make a list --> indent)
  3116. void CEditView::ToFromList(intn listType, ED_ListType elementType)
  3117. {
  3118.     Bool            alreadySet = false;
  3119.     EDT_ListData* list = NULL;
  3120.     
  3121.     EDT_BeginBatchChanges( *GetContext() );
  3122.  
  3123.     if (P_LIST_ITEM == EDT_GetParagraphFormatting( *GetContext() ) )
  3124.     {
  3125.         list = EDT_GetListData( *GetContext() );
  3126.         alreadySet = (list && ((list->iTagType == listType) || (listType == 0) ) );
  3127.     }
  3128.     else if ( 0 == listType )    // doesn't want to become a list and isn't a list (disable?)
  3129.         alreadySet = true;
  3130.     
  3131.     if ( alreadySet )
  3132.     {                                            // ListA -> Paragraph
  3133.          EDT_Outdent( *GetContext() );
  3134.          EDT_MorphContainer( *GetContext(), P_NSDT );
  3135.     }
  3136.     else
  3137.     {                                                    // Paragraph -> ListA, ListB -> ListA
  3138.         if ( !list )
  3139.         {                                // make it a list
  3140.             EDT_Indent( *GetContext() );
  3141.             EDT_MorphContainer( *GetContext(), P_LIST_ITEM );
  3142.             list = EDT_GetListData( *GetContext() );
  3143.             if ( list == NULL )
  3144.                 return;    // assert?
  3145.         }
  3146.         
  3147.         list->iTagType = listType;
  3148.         list->eType = elementType;
  3149.         EDT_SetListData( *GetContext(), list );
  3150.     }
  3151.     
  3152.     if ( list )
  3153.         EDT_FreeListData( list );
  3154.  
  3155.     EDT_EndBatchChanges( *GetContext() );
  3156. }
  3157.  
  3158.  
  3159. void CEditView::DisplayLineFeed( int inLocation, LO_LinefeedStruct* lineFeed, Bool needBg )
  3160. {
  3161.     CHTMLView::DisplayLineFeed( inLocation, lineFeed, needBg );
  3162.     
  3163.     if ( ! mDisplayParagraphMarks )
  3164.         return;
  3165.  
  3166.     // The editor only draws linefeeds which are breaks.
  3167.     if ( ! lineFeed->break_type )
  3168.         return;
  3169.     
  3170.     // Also, don't draw mark after end-of-doc mark.
  3171.     if ( lineFeed->prev && lineFeed->prev->lo_any.edit_offset < 0)
  3172.         return;
  3173.  
  3174.     // Allow selection feedback and display of end-of-paragraph marks in the editor.
  3175.     // We do nothing if this isn't an end-of-paragraph or hard break.
  3176.     // If we're displaying the marks, then we display them as little squares.
  3177.     // Otherwise we just do the selection feedback.
  3178.     // The selection feedback is a rectangle the height of the linefeed 1/2 of the rectangle's height.
  3179.     // located at the left edge of the linefeed's range.
  3180.  
  3181.     // We need to expand the linefeed's width here so that ResolveElement thinks it's at least as wide
  3182.     // as we're going to draw it.
  3183.     
  3184.     Bool bExpanded = false;
  3185.     
  3186.     // save these to restore later.
  3187.     int32 originalWidth = lineFeed->width;
  3188.     int32 originalHeight = lineFeed->height;
  3189.     
  3190.     const int32 kMinimumWidth = 0;                        // Oh, I love constants in my code!!
  3191.     const int32 kMaxHeight = 30;
  3192.     const int32 kMinimumHeight = 0;
  3193.  
  3194.     int32 expandedWidth = originalWidth;
  3195.     int32 expandedHeight = originalHeight;
  3196.  
  3197.     if ( expandedWidth < kMinimumWidth )
  3198.     {
  3199.         expandedWidth = kMinimumWidth;
  3200.         bExpanded = true;
  3201.     }
  3202.     
  3203.     if ( expandedHeight < kMinimumHeight )
  3204.     {
  3205.         expandedHeight = kMinimumHeight;
  3206.         bExpanded = true;
  3207.     }
  3208.     
  3209.     lineFeed->width = expandedWidth;
  3210.     lineFeed->height = expandedHeight;
  3211.     
  3212.     if ( expandedHeight > kMaxHeight )
  3213.         expandedHeight = kMaxHeight;
  3214.  
  3215.     int32 desiredWidth = expandedHeight / 2 + 3;
  3216.  
  3217.     if ( expandedWidth > desiredWidth )
  3218.         expandedWidth = desiredWidth;
  3219.  
  3220.     Rect frame;
  3221.  
  3222.     if (!CalcElementPosition( (LO_Element*)lineFeed, frame ))
  3223.         return;        // can't see it.
  3224.     
  3225.    // Limit the size of the drawn paragraph marker.
  3226.  
  3227.     frame.right = frame.left + expandedWidth;
  3228.     frame.bottom = frame.top + expandedHeight;
  3229.  
  3230.  
  3231.     if ( frame.right - frame.left > 5 )
  3232.     {
  3233.         frame.left += 2 + 3;
  3234.         frame.right -= 2;
  3235.     }
  3236.  
  3237.     if ( frame.bottom - frame.top > 5 )
  3238.     {
  3239.         frame.top += 2;
  3240.         frame.bottom -= 2;
  3241.     }
  3242.  
  3243.     // draw line breaks at 1/3 height of paragraph marks
  3244.     if ( lineFeed->break_type == LO_LINEFEED_BREAK_HARD )
  3245.         frame.top += (frame.bottom - frame.top) * 2 / 3;
  3246.  
  3247.     RGBColor    tmp;
  3248.     tmp = UGraphics::MakeRGBColor( lineFeed->text_attr->fg.red, 
  3249.                                     lineFeed->text_attr->fg.green,
  3250.                                     lineFeed->text_attr->fg.blue );
  3251.     
  3252.     // If the linefeed is selected and the linefeed color is the same as selection color, invert it.
  3253.     // This doesn't do anything if there is no selection. So it is still possible for the linefeed
  3254.     // fg color to be the same as the linefeed bg color or the page background color.
  3255.     if ( lineFeed->ele_attrmask & LO_ELE_SELECTED )
  3256.     {
  3257.         RGBColor        color;
  3258.         LMGetHiliteRGB( &color );
  3259.     
  3260.         if ( UGraphics::EqualColor( tmp, color ) )
  3261.         {
  3262.             tmp.red = ~color.red;
  3263.             tmp.blue = ~color.blue;
  3264.             tmp.green = ~color.green;
  3265.         }
  3266.     }
  3267.     
  3268.     ::RGBBackColor( &tmp );
  3269.     ::EraseRect( &frame );
  3270.     
  3271.     // restore original size
  3272.     lineFeed->width = originalWidth;
  3273.     lineFeed->height = originalHeight;
  3274. }
  3275.  
  3276.  
  3277. void CEditView::DisplayTable( int inLocation, LO_TableStruct *inTableStruct )
  3278. {
  3279.     Boolean    hasZeroBorderWidth;
  3280.     int32 savedBorderStyle;
  3281.     LO_Color savedBorderColor;
  3282.     Rect theFrame;
  3283.  
  3284.     if ( !FocusDraw() )
  3285.         return;
  3286.     
  3287.     if ( !CalcElementPosition( (LO_Element*)inTableStruct, theFrame ) )
  3288.         return;
  3289.     
  3290.     int iSelectionBorderThickness;
  3291.     if ( !(inTableStruct->ele_attrmask & LO_ELE_SELECTED) )
  3292.         iSelectionBorderThickness = 0;
  3293.     else
  3294.     {
  3295.         // set the border thickness to be the minimum of all border widths
  3296.         iSelectionBorderThickness = inTableStruct->border_left_width;
  3297.         if ( inTableStruct->border_right_width < iSelectionBorderThickness )
  3298.             iSelectionBorderThickness = inTableStruct->border_right_width;
  3299.         if ( inTableStruct->border_top_width < iSelectionBorderThickness )
  3300.             iSelectionBorderThickness = inTableStruct->border_top_width;
  3301.         if ( inTableStruct->border_bottom_width < iSelectionBorderThickness )
  3302.             iSelectionBorderThickness = inTableStruct->border_bottom_width;
  3303.         
  3304.         // allow for a larger selection if the border is large
  3305.         if ( iSelectionBorderThickness > 2 * ED_SELECTION_BORDER )
  3306.             iSelectionBorderThickness = 2 * ED_SELECTION_BORDER;
  3307.         
  3308.         // else if the area is too small, use the spacing between cells
  3309.         else if ( iSelectionBorderThickness < ED_SELECTION_BORDER )
  3310.         {
  3311.             iSelectionBorderThickness += inTableStruct->inter_cell_space;
  3312.             
  3313.             // but don't use it all; stick to the minimal amount
  3314.             if ( iSelectionBorderThickness > ED_SELECTION_BORDER )
  3315.                 iSelectionBorderThickness = ED_SELECTION_BORDER;
  3316.         }
  3317.     }
  3318.  
  3319.     hasZeroBorderWidth = (( inTableStruct->border_width == 0 ) &&
  3320.                          ( inTableStruct->border_top_width == 0 ) &&
  3321.                          ( inTableStruct->border_right_width == 0 ) &&
  3322.                          ( inTableStruct->border_bottom_width == 0 ) &&
  3323.                          ( inTableStruct->border_left_width == 0 ));
  3324.     if ( hasZeroBorderWidth )
  3325.     {
  3326.         if ( 0 == inTableStruct->inter_cell_space )
  3327.         {
  3328.             ::InsetRect( &theFrame, -1, -1 );
  3329.             iSelectionBorderThickness = 1;
  3330.         }
  3331.     
  3332.         inTableStruct->border_width = 1;
  3333.         inTableStruct->border_top_width = 1;
  3334.         inTableStruct->border_right_width = 1;
  3335.         inTableStruct->border_bottom_width = 1;
  3336.         inTableStruct->border_left_width = 1;
  3337.         
  3338.         savedBorderStyle = inTableStruct->border_style;
  3339.         inTableStruct->border_style = BORDER_DOTTED;
  3340.         savedBorderColor = inTableStruct->border_color;
  3341.         inTableStruct->border_color.red += 0x80;
  3342.         inTableStruct->border_color.green += 0x80;
  3343.         inTableStruct->border_color.blue += 0x80;
  3344.     }
  3345.  
  3346.     CHTMLView::DisplayTable( inLocation, inTableStruct );
  3347.     
  3348.     // restore previous values; necessary?
  3349.     if ( hasZeroBorderWidth )
  3350.     {
  3351.         inTableStruct->border_width = 0;
  3352.         inTableStruct->border_top_width = 0;
  3353.         inTableStruct->border_right_width = 0;
  3354.         inTableStruct->border_bottom_width = 0;
  3355.         inTableStruct->border_left_width = 0;
  3356.         inTableStruct->border_style = savedBorderStyle;
  3357.         inTableStruct->border_color = savedBorderColor;
  3358.     }
  3359.  
  3360.     if ( (inTableStruct->ele_attrmask & LO_ELE_SELECTED)
  3361.     && iSelectionBorderThickness < ED_SELECTION_BORDER )
  3362.     {
  3363.         if ( iSelectionBorderThickness )
  3364.             ::InsetRect( &theFrame, iSelectionBorderThickness, iSelectionBorderThickness );
  3365.  
  3366.         DisplaySelectionFeedback( LO_ELE_SELECTED, theFrame );
  3367.     }
  3368. }
  3369.  
  3370.  
  3371. void CEditView::DisplayCell( int inLocation, LO_CellStruct *inCellStruct )
  3372. {
  3373. #pragma unused( inLocation )
  3374.  
  3375.     if ( !FocusDraw() )
  3376.         return;
  3377.  
  3378.     Rect theFrame;
  3379.     if ( CalcElementPosition( (LO_Element*)inCellStruct, theFrame ) )
  3380.     {
  3381.         int iBorder = 0;
  3382.         
  3383.         if ( (inCellStruct->ele_attrmask & LO_ELE_SELECTED)
  3384.         || inCellStruct->ele_attrmask & LO_ELE_SELECTED_SPECIAL )
  3385.         {
  3386.             int32 iMaxWidth = 2 * ED_SELECTION_BORDER;
  3387.             
  3388.             iBorder = inCellStruct->border_width;
  3389.  
  3390.             if ( inCellStruct->inter_cell_space > 0 && iBorder < iMaxWidth )
  3391.             {
  3392.                 int iExtraSpace;
  3393.                 iExtraSpace = ::min( iMaxWidth - iBorder, inCellStruct->inter_cell_space / 2 );
  3394.                 iBorder += iExtraSpace;
  3395.                 InsetRect( &theFrame, -iExtraSpace, -iExtraSpace );
  3396.             }
  3397.         }
  3398.             
  3399.         if ( inCellStruct->border_width == 0 || LO_IsEmptyCell( inCellStruct ) )
  3400.         {
  3401.             StColorPenState state;
  3402.             PenPat( &qd.gray );
  3403.             PenMode( srcXor );
  3404.             FrameRect( &theFrame );
  3405.         }
  3406.         else if ( (inCellStruct->ele_attrmask & LO_ELE_SELECTED)
  3407.         || inCellStruct->ele_attrmask & LO_ELE_SELECTED_SPECIAL )
  3408.         {
  3409.             if ( iBorder < ED_SELECTION_BORDER )
  3410.                 InsetRect( &theFrame, 1, 1 );
  3411.  
  3412.             // don't have a color from table data so use highlight color from system
  3413.             RGBColor borderColor;
  3414.             ::LMGetHiliteRGB( &borderColor );
  3415.             if ( inCellStruct->ele_attrmask & LO_ELE_SELECTED_SPECIAL )
  3416.                 DisplayGrooveRidgeBorder( theFrame, borderColor, true, iBorder, iBorder, iBorder, iBorder );
  3417.             else if ( /* LO_ELE_SELECTED && */ iBorder < ED_SELECTION_BORDER )
  3418.                 // draw selection inside cell border if not enough room
  3419.                 DisplaySelectionFeedback( LO_ELE_SELECTED, theFrame );
  3420.             else    /* just LO_ELE_SELECTED */
  3421.                 DisplaySolidBorder( theFrame, borderColor, iBorder, iBorder, iBorder, iBorder );
  3422.         }
  3423.         else    /* non-empty, non-zero border, non-selected, non-"special" --> Everything else */
  3424.         {
  3425.             // Ñ╩this is really slow LAM
  3426.             for ( int i = 1; i <= inCellStruct->border_width; i++ )
  3427.             {
  3428.                 UGraphics::FrameRectShaded( theFrame, true );
  3429.                 ::InsetRect( &theFrame, 1, 1 );
  3430.             }
  3431.         }
  3432.     }
  3433. }
  3434.  
  3435.  
  3436. void CEditView::UpdateEnableStates()
  3437. {
  3438.     CPaneEnabler::UpdatePanes();
  3439. }
  3440.  
  3441.  
  3442. void CEditView::DisplayFeedback( int inLocation, LO_Element *inElement )
  3443. {
  3444. #pragma unused(inLocation)
  3445.  
  3446.     if (!FocusDraw() || (inElement == NULL))
  3447.         return;
  3448.  
  3449.     // we only know how to deal with images and tables and cells right now
  3450.     if ( inElement->lo_any.type != LO_IMAGE )
  3451.         return;
  3452.  
  3453.     LO_ImageStruct *image = (LO_ImageStruct *)inElement;
  3454.     
  3455.     // if it's not selected we are done
  3456.     if (( image->ele_attrmask & LO_ELE_SELECTED ) == 0 )
  3457.         return;
  3458.     
  3459.     int selectionBorder = 3;
  3460.     int32 layerOriginX, layerOriginY;
  3461.     SPoint32 topLeftImage;
  3462.     Point topLeft;
  3463.     Rect borderRect;
  3464.     
  3465.     if ( mCurrentDrawable != NULL )
  3466.         mCurrentDrawable->GetLayerOrigin(&layerOriginX, &layerOriginY);
  3467.     else
  3468.     {
  3469.         layerOriginX = mLayerOrigin.h;
  3470.         layerOriginY = mLayerOrigin.v;
  3471.     }
  3472.     
  3473.     topLeftImage.h = image->x + image->x_offset + layerOriginX;
  3474.     topLeftImage.v = image->y + image->y_offset + layerOriginY;
  3475.     ImageToLocalPoint(topLeftImage, topLeft);
  3476.  
  3477.     borderRect.left = topLeft.h;
  3478.     borderRect.top = topLeft.v;    
  3479.     borderRect.right = borderRect.left + image->width 
  3480.                         + (2 * image->border_width);
  3481.     borderRect.bottom = borderRect.top + image->height 
  3482.                         + (2 * image->border_width);
  3483.  
  3484.     ::PenSize( selectionBorder, selectionBorder );
  3485.     ::PenMode( patXor );
  3486.     ::PenPat( &qd.dkGray );
  3487.     
  3488.     ::FrameRect(&borderRect);
  3489.  
  3490.     // reset pen size, mode, and pattern
  3491.     ::PenNormal();
  3492. }
  3493.  
  3494.  
  3495. // this is not an FE_* call
  3496. void CEditView::DisplaySelectionFeedback( uint16 ele_attrmask, const Rect &inRect )
  3497. {
  3498.     Boolean isSelected = ele_attrmask & LO_ELE_SELECTED;
  3499.     if ( !isSelected )
  3500.         return;
  3501.     
  3502.     Rect portizedRect;
  3503.     SPoint32 updateUpperLeft, updateLowerRight;
  3504.     
  3505.     // Get the rect to update in image coordinates.
  3506.     updateUpperLeft.h = inRect.left;        // sorry to say, the horizontal will be ignored
  3507.     updateUpperLeft.v = inRect.top;            // later and set to the whole frame width
  3508.     updateLowerRight.h = inRect.right;
  3509.     updateLowerRight.v = inRect.bottom;
  3510.     
  3511.     // Convert from image to local coordinates...
  3512.     ImageToLocalPoint( updateUpperLeft, topLeft(portizedRect) );
  3513.     ImageToLocalPoint( updateLowerRight, botRight(portizedRect) );
  3514.  
  3515.     int32 rWidth = portizedRect.right - portizedRect.left;
  3516.     int32 rHeight = portizedRect.bottom - portizedRect.top;
  3517.     if ( rWidth <= (ED_SELECTION_BORDER*2) || rHeight <= (ED_SELECTION_BORDER*2) )
  3518.     {
  3519.         // Too narrow to draw frame. Draw solid.
  3520.         ::InvertRect( &portizedRect );
  3521.     }
  3522.     else
  3523.     {
  3524.         ::PenSize( ED_SELECTION_BORDER, ED_SELECTION_BORDER );
  3525.         ::PenMode( srcXor );
  3526.         ::FrameRect( &portizedRect );
  3527.         ::PenNormal();
  3528.     }
  3529. }
  3530.  
  3531.  
  3532. /* This should invalidate the entire table or cell rect to cause redrawing of backgrounds
  3533.  *  and all table or cell contents. Use to unselect table/cell selection feedback
  3534. */
  3535. void CEditView::InvalidateEntireTableOrCell( LO_Element* inElement )
  3536. {
  3537.     if ( !FocusDraw() )
  3538.         return;
  3539.  
  3540.     int32 iWidth, iHeight;
  3541.     if ( inElement->type == LO_TABLE )
  3542.     {
  3543.         iWidth = inElement->lo_table.width;
  3544.         iHeight = inElement->lo_table.height;
  3545.     }
  3546.     else if ( inElement->type == LO_CELL )
  3547.     {
  3548.         iWidth = inElement->lo_cell.width;
  3549.         iHeight = inElement->lo_cell.height;
  3550.     }
  3551.     else
  3552.         return; // Only Table and Cell types allowed
  3553.  
  3554.     Rect r;
  3555.     r.left = inElement->lo_any.x;
  3556.     r.top = inElement->lo_any.y;
  3557.     r.right = r.left + iWidth;
  3558.     r.bottom = r.top + iHeight;
  3559.  
  3560.     if ( inElement->type == LO_TABLE 
  3561.         && inElement->lo_table.border_left_width == 0
  3562.         && inElement->lo_table.border_right_width == 0
  3563.         && inElement->lo_table.border_top_width == 0
  3564.         && inElement->lo_table.border_bottom_width == 0 )
  3565.     {
  3566.         // We are displaying a "zero-width" table,
  3567.         //  increase rect by 1 pixel because that's
  3568.         //  where we drew the table's dotted-line border 
  3569.         ::InsetRect( &r, -1, -1 );
  3570.     }
  3571.     
  3572.     // Include the inter-cell spacing area also used for highlighting a cell
  3573.     int32 iExtraSpace;
  3574.     if ( inElement->type == LO_CELL 
  3575.         && inElement->lo_cell.border_width < eSelectionBorder
  3576.         && 0 < (iExtraSpace = inElement->lo_cell.inter_cell_space / 2) )
  3577.     {
  3578.         ::InsetRect( &r, -iExtraSpace, -iExtraSpace );
  3579.     }
  3580.  
  3581.     ::InvalRect( &r );
  3582. }
  3583.  
  3584.  
  3585. void CEditView::DisplayAddRowOrColBorder( XP_Rect* inRect, XP_Bool inDoErase )
  3586. {
  3587.     if ( !FocusDraw() )
  3588.         return;
  3589.  
  3590.     if ( inDoErase )
  3591.     {
  3592.         SPoint32 updateUL, updateLR;
  3593.         Point    ul, lr;
  3594.         
  3595.         // Get the rect to update in image coordinates.
  3596.         updateUL.h = inRect->left;        // sorry to say, the horizontal will be ignored later and set to the whole frame width
  3597.         updateUL.v = inRect->top;
  3598.         updateLR.h = inRect->right;
  3599.         updateLR.v = inRect->bottom;
  3600.         
  3601.         // Convert from image to local to port coordinates... we don't have to worry about the conversion because we've already been clipped to the frame
  3602.         ImageToLocalPoint( updateUL, ul );
  3603.         ImageToLocalPoint( updateLR, lr );
  3604.         LocalToPortPoint( ul );
  3605.         LocalToPortPoint( lr );
  3606.         
  3607.         Rect r;
  3608.         r.top = ul.v;
  3609.         r.left = ul.h;
  3610.         r.bottom = lr.v;
  3611.         r.right = lr.h;
  3612.  
  3613.         // if there is no line thickness
  3614.         if ( inRect->left == inRect->right )
  3615.             r.right++;
  3616.         else // we're working on rows (horizontal line)
  3617.         {
  3618.             // increment bottom to ensure it's a valid rect
  3619.             XP_ASSERT( inRect->top == inRect->bottom );
  3620.             r.bottom++;
  3621.         }
  3622.         
  3623.         ::InvalRect( &r );
  3624.         
  3625.         // force redraw in cases where dragging
  3626.         UpdatePort();
  3627.     }
  3628.     else
  3629.     {
  3630.         StColorPenState state;
  3631.         PenPat( &qd.gray );
  3632.         PenMode( srcXor );
  3633.         
  3634.         ::MoveTo( inRect->left, inRect->top );
  3635.         ::LineTo( inRect->right, inRect->bottom );
  3636.     }
  3637. }
  3638.  
  3639.  
  3640. void CEditView::DisplayHR( int inLocation, LO_HorizRuleStruct* hrule )
  3641. {
  3642.     if ( hrule->edit_offset != -1 || mDisplayParagraphMarks )
  3643.         CHTMLView::DisplayHR( inLocation, hrule );
  3644. }
  3645.  
  3646.  
  3647. void CEditView::HandleCut()
  3648. {
  3649.     char *ppText = NULL, *ppHtml = NULL;
  3650.     int32    pTextLen = 0, pHtmlLen = 0;
  3651.     
  3652.     if ( EDT_COP_OK != EDT_CutSelection( *GetContext(), &ppText, &pTextLen, &ppHtml, &pHtmlLen )  )
  3653.     {
  3654.         ErrorManager::PlainAlert( CUT_ACROSS_CELLS );
  3655.     }
  3656.  
  3657.     try {
  3658.         LClipboard::GetClipboard()->SetData( 'TEXT', ppText, pTextLen, true );
  3659.         LClipboard::GetClipboard()->SetData( 'EHTM', ppHtml, pHtmlLen, false );
  3660.     }
  3661.     catch(...)
  3662.     {}
  3663.     
  3664.     XP_FREEIF( ppText );
  3665.     XP_FREEIF( ppHtml );
  3666. }
  3667.  
  3668.  
  3669. void CEditView::HandleCopy()
  3670. {
  3671.     char *ppText = NULL, *ppHtml = NULL;
  3672.     int32 pTextLen = 0, pHtmlLen = 0;
  3673.     
  3674.     if ( EDT_COP_OK != EDT_CopySelection( *GetContext(), &ppText, &pTextLen, &ppHtml, &pHtmlLen ) )
  3675.     {
  3676.         ErrorManager::PlainAlert( CUT_ACROSS_CELLS );
  3677.     }
  3678.     
  3679.     try {
  3680.         LClipboard::GetClipboard()->SetData( 'TEXT', ppText, pTextLen, true );
  3681.         LClipboard::GetClipboard()->SetData( 'EHTM', ppHtml, pHtmlLen, false );
  3682.     }
  3683.     catch(...)
  3684.     {}
  3685.     
  3686.     XP_FREEIF( ppText );
  3687.     XP_FREEIF( ppHtml );
  3688. }
  3689.  
  3690.  
  3691. void CEditView::HandlePaste()
  3692. {
  3693.     int32 dataLength;
  3694.                 
  3695. /* internal format */
  3696.     dataLength = LClipboard::GetClipboard()->GetData( 'EHTM', NULL );
  3697.     if ( dataLength > 0 )
  3698.     {
  3699.         Handle htmlHandle = ::NewHandle( dataLength + 1 );
  3700.         if ( htmlHandle )
  3701.         {
  3702.             LClipboard::GetClipboard()->GetData( 'EHTM', htmlHandle );
  3703.             ::HLock( htmlHandle );
  3704.             (*htmlHandle)[ dataLength ] = '\0';
  3705.             int result = EDT_PasteHTML( *GetContext(), *htmlHandle );
  3706.             ::DisposeHandle( htmlHandle );
  3707.             return;
  3708.         }
  3709.     }
  3710.  
  3711. /* text */
  3712.     dataLength = LClipboard::GetClipboard()->GetData( 'TEXT', NULL );
  3713.     if ( dataLength > 0 )
  3714.     {
  3715.         Handle textHandle = ::NewHandle( dataLength + 1 );
  3716.         if ( textHandle )
  3717.         {
  3718.             LClipboard::GetClipboard()->GetData( 'TEXT', textHandle );
  3719.             ::HLock( textHandle );
  3720.             (*textHandle)[ dataLength ] = '\0';
  3721.             int result = EDT_PasteText( *GetContext(), *textHandle );
  3722.             ::DisposeHandle( textHandle );
  3723.             return;
  3724.         }
  3725.     }
  3726.  
  3727. /* The rest is all PICT (ugh!) */
  3728.     dataLength = LClipboard::GetClipboard()->GetData( 'PICT', NULL );
  3729.     if ( dataLength <= 0 )
  3730.         return;
  3731.     
  3732.     // check for quicktime and jpeg compressor
  3733.     Int32    response;
  3734.     if ( ::Gestalt( gestaltQuickTime, &response ) != noErr
  3735.     || ::Gestalt( gestaltCompressionMgr, &response ) != noErr )
  3736.         return;
  3737.     
  3738.     // get location where to save new jpeg file
  3739.     StandardFileReply sfReply;
  3740.     Str255 saveprompt;
  3741.     
  3742.     // Because resource changes are expensive (right now) for localization
  3743.     // this string was added to a "strange" place
  3744.     ::GetIndString( sfReply.sfFile.name, STRPOUND_EDITOR_MENUS, 18 );
  3745.     ::GetIndString( saveprompt, STRPOUND_EDITOR_MENUS, 19 );
  3746.  
  3747.     ::UDesktop::Deactivate();
  3748.     ::StandardPutFile( saveprompt[0] ? saveprompt : NULL, sfReply.sfFile.name, &sfReply );
  3749.     ::UDesktop::Activate();
  3750.  
  3751.     if ( !sfReply.sfGood )
  3752.         return;
  3753.     
  3754.     Handle pictDataHandle = ::NewHandle( dataLength );
  3755.     if ( pictDataHandle == NULL )
  3756.         return;
  3757.     ::HUnlock( pictDataHandle );
  3758.     
  3759.     LClipboard::GetClipboard()->GetData( 'PICT', pictDataHandle );
  3760.     
  3761.     OSErr err;
  3762.     if ( !sfReply.sfReplacing )
  3763.     {
  3764.         // create file
  3765.         err = FSpCreateCompat( &sfReply.sfFile, emSignature, 'JPEG', smSystemScript );
  3766.         if ( err )
  3767.         {
  3768.             ::DisposeHandle( pictDataHandle );
  3769.             return;
  3770.         }
  3771.     }
  3772.     
  3773.     // open file
  3774.     short refNum;
  3775.     err = ::FSpOpenDFCompat( &sfReply.sfFile, fsRdWrPerm, &refNum );
  3776.     if ( err )
  3777.     {
  3778.         if ( !sfReply.sfReplacing )
  3779.             FSpDeleteCompat( &sfReply.sfFile );
  3780.         ::DisposeHandle( pictDataHandle );
  3781.         return;
  3782.     }
  3783.     
  3784.     // write out header
  3785.     int zero = 0;
  3786.     long actualSizeWritten = sizeof( zero );
  3787.     for ( int count = 1; actualSizeWritten && (count <= (512 / actualSizeWritten)) && err == noErr; count++ )
  3788.         err = ::FSWrite( refNum, &actualSizeWritten, &zero );
  3789.     
  3790.     // write out data
  3791.     ::HLock( pictDataHandle );
  3792.     actualSizeWritten = dataLength;
  3793.     err = FSWriteVerify( refNum, &actualSizeWritten, *pictDataHandle );
  3794.     DisposeHandle( pictDataHandle );
  3795.     if ( err )
  3796.     {
  3797.         ::FSClose( refNum );
  3798.         FSpDeleteCompat( &sfReply.sfFile );
  3799.         return;
  3800.     }
  3801.     
  3802.     // overwrite file in place
  3803.     err = ::CompressPictureFile( refNum, refNum, codecNormalQuality, 'jpeg' );
  3804.     if ( err != noErr )
  3805.     {
  3806.         ::FSClose( refNum );
  3807.         FSpDeleteCompat( &sfReply.sfFile );
  3808.         return;
  3809.     }
  3810.     
  3811.     // re-write file as jpeg (not PICT)
  3812.     long totalSize, bytesToWrite;
  3813.     char buffer[512];
  3814.     char jfifMarker1[3] = { 0xFF, 0xD8, 0xFF };
  3815.     char jfifMarker2[4] = { 'J', 'F', 'I', 'F' };
  3816.     
  3817.     ::SetFPos( refNum, fsFromLEOF, 0 );
  3818.     ::GetFPos( refNum, &totalSize );
  3819.     ::SetFPos( refNum, fsFromStart, 512 );
  3820.     
  3821.     // skip over remainder of non-JFIF header
  3822.     // KNOWN BUG:  if JFIF header is split over two FSReads we'll miss it in the loop below
  3823.     Boolean headerFound = false;
  3824.     while ( err == noErr && !headerFound )
  3825.     {
  3826.         bytesToWrite = 512;
  3827.         err = ::FSRead( refNum, &bytesToWrite, buffer );
  3828.         if ( err == noErr )
  3829.         {
  3830.             int index = 0;
  3831.             for ( index = 0; index < bytesToWrite - sizeof( jfifMarker1 ); index++ )
  3832.             {
  3833.                 if ( 0 == memcmp( &buffer[ index ], jfifMarker1, sizeof(jfifMarker1) ) )
  3834.                 {
  3835.                     if ( index + 4 + 2 > bytesToWrite // assume it's there without checking
  3836.                     || 0 == memcmp( &buffer[ index + 6 ], jfifMarker2, sizeof(jfifMarker2) ) )
  3837.                     {
  3838.                         // move fpos back to the start of jfifMarker
  3839.                         err = ::SetFPos( refNum, fsFromMark, -( bytesToWrite - index) );
  3840.                         headerFound = true;
  3841.                         break;
  3842.                     }
  3843.                 }
  3844.             }
  3845.         }
  3846.     }
  3847.     
  3848.     if ( err )    // jfif header not found??
  3849.     {
  3850.         ::FSClose( refNum );
  3851.         FSpDeleteCompat( &sfReply.sfFile );
  3852.         return;
  3853.     }
  3854.     
  3855.     long fileOffset;
  3856.     ::GetFPos( refNum, &fileOffset );
  3857.  
  3858.     // write remainder (current fpos) as jfif to start of file
  3859.     Boolean doneReadingFile = false;
  3860.     actualSizeWritten = fileOffset;
  3861.     while ( actualSizeWritten < totalSize && err == noErr )
  3862.     {
  3863.         bytesToWrite = sizeof( buffer );
  3864.         err = ::FSRead( refNum, &bytesToWrite, buffer );
  3865.         
  3866.         // ignore eofErr if we have more bytesToWrite
  3867.         if ( err == eofErr && bytesToWrite )
  3868.             err = noErr;
  3869.         
  3870.         // move file pointer back to 512 bytes less than where we began read
  3871.         if ( err == noErr )
  3872.         {
  3873.             ::SetFPos( refNum, fsFromStart, actualSizeWritten - fileOffset );
  3874.         
  3875.             err = ::FSWrite( refNum, &bytesToWrite, buffer );
  3876.             
  3877.             actualSizeWritten += bytesToWrite;
  3878.             ::SetFPos( refNum, fsFromStart, actualSizeWritten );
  3879.         }
  3880.     }
  3881.     
  3882.     ::SetEOF( refNum, actualSizeWritten - fileOffset );
  3883.     
  3884.     ::FSClose( refNum );
  3885.     
  3886.     // create image link
  3887.     EDT_ImageData *image = EDT_NewImageData();
  3888.     if ( image == NULL )
  3889.         return;
  3890.     
  3891.     image->pSrc = CFileMgr::GetURLFromFileSpec( sfReply.sfFile );
  3892.     if ( image->pSrc )
  3893.         EDT_InsertImage( *GetContext(), image, true );
  3894.     EDT_FreeImageData( image );
  3895. }
  3896.  
  3897.  
  3898. void CEditView::AdjustCursorSelf( Point inPortPt, const EventRecord& inMacEvent )
  3899. {
  3900.     // if this page is tied-up, display a watch
  3901.     if (!IsDoneLoading() )
  3902.     {
  3903.         ::SafeSetCursor( watchCursor );
  3904.         return;
  3905.     }
  3906.  
  3907.     //  bail if we did not move, saves time and flickering
  3908.     if ( ( inPortPt.h == mOldPoint.h ) && ( inPortPt.v == mOldPoint.v ) )
  3909.         return;
  3910.  
  3911.     // store for the next time we get called
  3912.     mOldPoint.h = inPortPt.h;
  3913.     mOldPoint.v = inPortPt.v;
  3914.  
  3915.     // find the element the cursor is above
  3916.     PortToLocalPoint( inPortPt );
  3917.     
  3918.     SPoint32 firstP;
  3919.     LocalToImagePoint( inPortPt, firstP );
  3920.     FocusDraw();                                // Debugging only
  3921.         
  3922. #ifdef LAYERS
  3923.     LO_Element* element = LO_XYToElement( *GetContext(), firstP.h, firstP.v, 0 );
  3924. #else
  3925.     LO_Element* element = LO_XYToElement( *GetContext(), firstP.h, firstP.v );
  3926. #endif
  3927.     
  3928.     // The cursor is over an image or hrule
  3929.     if ( element && (element->type == LO_IMAGE || element->type == LO_HRULE) )
  3930.     {
  3931.         if ( mOldLastElementOver != -1 )
  3932.         {
  3933.             mOldLastElementOver = element->lo_any.ele_id;
  3934.             ::SetCursor( &UQDGlobals::GetQDGlobals()->arrow );
  3935.     //        mContext->Progress( CStr255::sEmptyString );
  3936.             return;
  3937.         }
  3938.     }
  3939.  
  3940.     ED_HitType iTableHit;
  3941.     iTableHit = EDT_GetTableHitRegion( *GetContext(), firstP.h, firstP.v, &element, 
  3942.                                         (inMacEvent.modifiers & cmdKey) == cmdKey );
  3943.     if ( element )
  3944.     {
  3945.         int specialElementID = element->lo_any.ele_id + (iTableHit * 0x01000000);
  3946.         if ( mOldLastElementOver != specialElementID )
  3947.         {
  3948.             mOldLastElementOver = specialElementID;
  3949.         //    mContext->Progress( CStr255::sEmptyString );
  3950.  
  3951.             switch ( iTableHit )
  3952.             {
  3953.                 case ED_HIT_SEL_ALL_CELLS:
  3954.                 case ED_HIT_SEL_TABLE:            ::SafeSetCursor( 12001 );    break;
  3955.                 case ED_HIT_SEL_COL:            ::SafeSetCursor( 12003 );    break;
  3956.                 case ED_HIT_SEL_ROW:            ::SafeSetCursor( 12002 );    break;
  3957.                 case ED_HIT_SEL_CELL:            ::SafeSetCursor( 12000 );    break;
  3958.                 case ED_HIT_SIZE_TABLE_WIDTH:    ::SafeSetCursor( 12005 );    break;
  3959.                 case ED_HIT_SIZE_TABLE_HEIGHT:    ::SafeSetCursor( 12004 );    break;
  3960.                 case ED_HIT_SIZE_COL:            ::SafeSetCursor( 130 );        break;
  3961.                 case ED_HIT_ADD_ROWS:            ::SafeSetCursor( 12006 );    break;
  3962.                 case ED_HIT_ADD_COLS:            ::SafeSetCursor( 12007 );    break;
  3963.                 default:        ::SafeSetCursor( iBeamCursor );
  3964.             }
  3965.         }
  3966.     }
  3967.     else
  3968.     {
  3969.         // The cursor is over blank space
  3970.         if ( mOldLastElementOver != -1 )
  3971.         {
  3972.             mOldLastElementOver = -1;
  3973.             ::SetCursor( &UQDGlobals::GetQDGlobals()->arrow );
  3974.         //    ::SafeSetCursor( iBeamCursor );        // not sure if I should do this if element is NULL
  3975.     //        mContext->Progress( CStr255::sEmptyString );
  3976.         }
  3977.         else
  3978.             ::SafeSetCursor( iBeamCursor );
  3979.     }
  3980.     
  3981. }
  3982.  
  3983. void CEditView::ListenToMessage( MessageT inMessage, void* ioParam )
  3984. {
  3985.     switch ( inMessage )
  3986.     {
  3987.         case cmd_Bold:
  3988.         case cmd_Italic:
  3989.         case cmd_Underline:
  3990.         case cmd_FontSmaller:
  3991.         case cmd_FontLarger:
  3992.         case cmd_Print:
  3993.         case cmd_Format_FontColor:
  3994.         case cmd_InsertEditImage:
  3995.         case cmd_InsertEditLink:
  3996.         case cmd_Insert_Table:
  3997.         case cmd_InsertEdit_Target:
  3998.         case cmd_Insert_Target:
  3999.         case cmd_Insert_Line:
  4000.         case msg_MakeNoList:
  4001.         case msg_MakeNumList:
  4002.         case msg_MakeUnumList:
  4003.         case cmd_Format_Paragraph_Indent:
  4004.         case cmd_Format_Paragraph_UnIndent:
  4005.         case cmd_JustifyLeft:
  4006.         
  4007.         case cmd_Cut:
  4008.         case cmd_Copy:
  4009.         case cmd_Paste:
  4010.             ObeyCommand( inMessage, ioParam );
  4011.             break;
  4012.  
  4013.         case cmd_FormatViewerFont:
  4014.         case cmd_FormatFixedFont:
  4015.             break;
  4016.         
  4017.         case msg_NSCPEditorRepaginate:
  4018.             // turn off repagination to avoid infinite loop when setting prefs
  4019.             Boolean isRepaginating = GetRepaginate();
  4020.             if ( isRepaginating )
  4021.                 SetRepaginate( false );
  4022.  
  4023.             NoteEditorRepagination();
  4024.  
  4025.             // turn off repagination to avoid infinite loop when setting prefs
  4026.             if ( isRepaginating )
  4027.                 SetRepaginate( true );
  4028.             break;    
  4029.  
  4030.         default:
  4031.             if (inMessage >= COLOR_POPUP_MENU_BASE && inMessage <= COLOR_POPUP_MENU_BASE_LAST)
  4032.                 ObeyCommand( inMessage, ioParam );
  4033.         break;
  4034.  
  4035.     }
  4036. }
  4037.  
  4038.  
  4039. Boolean CEditView::ObeyCommand( CommandT inCommand, void *ioParam )
  4040. {
  4041.     EDT_CharacterData* better;        // used by a bunch of cases.
  4042.     
  4043.     if (inCommand >= COLOR_POPUP_MENU_BASE && inCommand <= COLOR_POPUP_MENU_BASE_LAST)
  4044.     {
  4045.         FLUSH_JAPANESE_TEXT
  4046.         if ( mColorPopup && mColorPopup->IsEnabled() )
  4047.         {                        
  4048.             if ( CanUseCharFormatting() )
  4049.             {
  4050.                  better = EDT_GetCharacterData( *GetContext() );
  4051.                  if ( better )
  4052.                  {
  4053.                     RGBColor outColor;
  4054.                     LO_Color pColor = {0, 0, 0};
  4055.                     short    mItem;
  4056.                     
  4057.                     if ( !EDT_GetFontColor( *GetContext(), &pColor ) )
  4058.                     {    // still a perfectly respectable way to get the font color
  4059.                         // get default color
  4060.                         EDT_PageData *pagedata = EDT_GetPageData( *GetContext() );
  4061.                         if ( pagedata )
  4062.                         {
  4063.                             pColor = *pagedata->pColorText;
  4064.                             EDT_FreePageData( pagedata );
  4065.                         }
  4066.                     }
  4067.                     
  4068.                     mItem = inCommand - COLOR_POPUP_MENU_BASE + 1;
  4069.                     if ( mColorPopup->GetMenuItemRGBColor( mItem, &outColor ) == true )
  4070.                     {
  4071.                         pColor.red = (outColor.red >> 8);
  4072.                         pColor.green = (outColor.green >> 8);
  4073.                         pColor.blue = (outColor.blue >> 8);
  4074.                         
  4075.                         better->mask = TF_FONT_COLOR;
  4076.                         better->values = (mItem == CColorPopup::DEFAULT_COLOR_ITEM) ? 0 : TF_FONT_COLOR;
  4077.                                                                 // remove font color? or set font color?
  4078.                         better->pColor = &pColor;
  4079.                         EDT_BeginBatchChanges( *GetContext() );
  4080.                         EDT_SetCharacterData( *GetContext(), better );
  4081.                         EDT_SetFontColor( *GetContext(), &pColor );
  4082.                         EDT_EndBatchChanges( *GetContext() );
  4083.                         better->pColor = NULL;
  4084.                     }
  4085.                     
  4086.                     EDT_FreeCharacterData( better );
  4087.                 }
  4088.             }
  4089.         }
  4090.         
  4091.     }
  4092.  
  4093.     switch ( inCommand )
  4094.     {        
  4095.         case cmd_Publish:
  4096.             CEditDialog::Start( EDITDLG_PUBLISH, *GetContext(), 1 );
  4097.             break;
  4098.         
  4099.         case cmd_Refresh:
  4100.             EDT_RefreshLayout( *GetContext() );
  4101.             break;
  4102.         
  4103. #ifdef MOZ_MAIL_COMPOSE
  4104.         case cmd_MailDocument:
  4105.             FLUSH_JAPANESE_TEXT
  4106.             EDT_MailDocument( *GetContext() );
  4107.             break;
  4108. #endif
  4109.         
  4110.         case cmd_ViewSource:
  4111.             FLUSH_JAPANESE_TEXT
  4112.             EDT_DisplaySource( *GetContext() );
  4113.             break;
  4114.  
  4115.         case cmd_EditSource:
  4116.             FLUSH_JAPANESE_TEXT
  4117.             if (VerifySaveUpToDate())
  4118.             {
  4119.                 // Now that we have saved the document, lets get an FSSpec for it.
  4120.                 History_entry *hist_ent = SHIST_GetCurrent( &(((MWContext *)*GetContext())->hist) );
  4121.                 if ( hist_ent == NULL || hist_ent->address == NULL )
  4122.                     break;
  4123.                 
  4124.                 FSSpec    theDocument;
  4125.                 if ( noErr != CFileMgr::FSSpecFromLocalUnixPath( 
  4126.                                         hist_ent->address + XP_STRLEN("file://"), &theDocument, false ) )
  4127.                     break;
  4128.                 
  4129.                 // Get the FSSpec for the editor
  4130.                 FSSpec    theApplication;
  4131.                 XP_Bool hasEditor = false;
  4132.                 PREF_GetBoolPref( "editor.use_html_editor", &hasEditor );
  4133.                 if ( hasEditor )
  4134.                     theApplication = CPrefs::GetFolderSpec(CPrefs::HTMLEditor);
  4135.                 
  4136.                 // Oops, the user has not picked an app in the preferences yet.
  4137.                 if ( !hasEditor || (theApplication.vRefNum == -1 && theApplication.parID == -1) )
  4138.                 {
  4139.                     ErrorManager::PlainAlert( NO_SRC_EDITOR_PREF_SET );
  4140.                     CPrefsDialog::EditPrefs( CPrefsDialog::eExpandEditor, 
  4141.                                                     PrefPaneID::eEditor_Main );
  4142.                     break;
  4143.                 }
  4144.                 else            
  4145.                     StartDocInApp( theDocument, theApplication );
  4146.             }
  4147.             break;
  4148.         
  4149.         case cmd_Reload:
  4150.             FLUSH_JAPANESE_TEXT
  4151.             if ( !EDT_IS_NEW_DOCUMENT( ((MWContext *)*GetContext()) ) )
  4152.                 if ( VerifySaveUpToDate() )
  4153.                     DoReload();
  4154.             break;
  4155.         
  4156.         case cmd_Remove_Links:
  4157.             FLUSH_JAPANESE_TEXT
  4158.             EDT_SetHREF( *GetContext(), NULL );
  4159.             break;
  4160.         
  4161. #if 0
  4162.         case cmd_DisplayTables:
  4163.             EDT_SetDisplayTables( *GetContext(), 
  4164.                                 !EDT_GetDisplayTables( *GetContext() ) );
  4165.             break;
  4166. #endif
  4167.         
  4168.         case cmd_Format_Target:
  4169.             CEditDialog::Start( EDITDLG_TARGET, *GetContext(), 0, false );
  4170.             break;
  4171.         
  4172.         case cmd_Format_Unknown_Tag:
  4173.             CEditDialog::Start( EDITDLG_UNKNOWN_TAG, *GetContext() );
  4174.             break;
  4175.         
  4176.         case cmd_Format_DefaultFontColor:
  4177.             FLUSH_JAPANESE_TEXT
  4178.             EDT_SetFontColor( *GetContext(), NULL );
  4179.             break;
  4180.         
  4181.         case cmd_DisplayParagraphMarks:
  4182.             // update the whole view
  4183.             mDisplayParagraphMarks = !mDisplayParagraphMarks;
  4184.             if ( IsDoneLoading() )
  4185.                 EDT_RefreshLayout( *GetContext() );
  4186.             break;
  4187.  
  4188. // File/Edit Toolbar
  4189.         case cmd_Save:
  4190.             FLUSH_JAPANESE_TEXT
  4191.             SaveDocument();
  4192.             break;
  4193.         
  4194.         case cmd_SaveAs:
  4195.             SaveDocumentAs();
  4196.             break;
  4197.         
  4198.         case cmd_BrowseDocument:
  4199.             FLUSH_JAPANESE_TEXT
  4200.             if ( VerifySaveUpToDate() )
  4201.             {
  4202.                 History_entry* current = SHIST_GetCurrent( &(((MWContext *)*GetContext())->hist) );
  4203.                 if ( !current )
  4204.                     break;
  4205.                 
  4206.                 URL_Struct * nurl = NULL;
  4207.                 if ( current && current->address )
  4208.                     nurl = NET_CreateURLStruct( current->address, NET_DONT_RELOAD );
  4209.  
  4210.                 if ( !nurl )
  4211.                     break;
  4212.  
  4213.                 try
  4214.                 {
  4215.                     CURLDispatcher::DispatchURL( nurl, NULL );
  4216.                 }
  4217.                 catch(...) { }
  4218.             }
  4219.             break;
  4220.         
  4221.         case cmd_Cut:
  4222.             FLUSH_JAPANESE_TEXT
  4223.             HandleCut();
  4224.             break;
  4225.         
  4226.         case cmd_Copy:
  4227.             FLUSH_JAPANESE_TEXT
  4228.             HandleCopy();
  4229.             break;
  4230.         
  4231.         case cmd_Paste:
  4232.             FLUSH_JAPANESE_TEXT
  4233.             HandlePaste();
  4234.             break;
  4235.         
  4236.         case cmd_Clear:
  4237.             FLUSH_JAPANESE_TEXT
  4238.             if ( EDT_CanCut( *GetContext(), true ) == EDT_COP_OK )
  4239.                 EDT_DeletePreviousChar( *GetContext() );
  4240.             break;
  4241.  
  4242.         case cmd_SelectAll:
  4243.             FLUSH_JAPANESE_TEXT
  4244.             EDT_SelectAll( *GetContext() );
  4245.             break;
  4246.  
  4247.         case cmd_Print:
  4248.         case cmd_PrintOne:
  4249.             FLUSH_JAPANESE_TEXT
  4250.             DoPrintCommand( inCommand );
  4251.             break;
  4252.         
  4253. // Character Toolbar
  4254.         case cmd_FontSmaller:
  4255.             FLUSH_JAPANESE_TEXT
  4256.             if ( CanUseCharFormatting() )
  4257.                 EDT_SetFontSize( *GetContext(), 
  4258.                                     EDT_GetFontSize( *GetContext()) - 1 );
  4259.             break;
  4260.         
  4261.         case cmd_FontLarger:
  4262.             FLUSH_JAPANESE_TEXT
  4263.             if ( CanUseCharFormatting() )
  4264.                 EDT_SetFontSize( *GetContext(), 
  4265.                                     EDT_GetFontSize( *GetContext()) + 1 );
  4266.             break;
  4267.         
  4268.         case cmd_Bold:
  4269.             FLUSH_JAPANESE_TEXT
  4270.             if ( CanUseCharFormatting() )
  4271.             {
  4272.                 better = EDT_GetCharacterData( *GetContext() );
  4273.                 if ( better )
  4274.                 {
  4275.                     better->mask = TF_BOLD;
  4276.                     better->values ^= TF_BOLD;
  4277.                     EDT_SetCharacterData( *GetContext(), better );
  4278.                     EDT_FreeCharacterData( better );
  4279.                 }
  4280.             }
  4281.             break;
  4282.         
  4283.         case cmd_Italic:
  4284.             FLUSH_JAPANESE_TEXT
  4285.             if ( CanUseCharFormatting() )
  4286.             {
  4287.                 better = EDT_GetCharacterData( *GetContext() );
  4288.                 if ( better )
  4289.                 {
  4290.                     better->mask = TF_ITALIC;
  4291.                     better->values ^= TF_ITALIC;
  4292.                     EDT_SetCharacterData( *GetContext(), better );
  4293.                     EDT_FreeCharacterData( better );
  4294.                 }
  4295.             }
  4296.             break;
  4297.  
  4298.         case cmd_Underline:
  4299.             FLUSH_JAPANESE_TEXT
  4300.             if ( CanUseCharFormatting() )
  4301.             {
  4302.                 better = EDT_GetCharacterData( *GetContext() );
  4303.                 if ( better )
  4304.                 {
  4305.                     better->mask = TF_UNDERLINE;
  4306.                     better->values ^= TF_UNDERLINE;
  4307.                     EDT_SetCharacterData( *GetContext(), better );
  4308.                     EDT_FreeCharacterData( better );
  4309.                 }
  4310.             }
  4311.             break;
  4312.         
  4313.         case cmd_Format_Character_Strikeout:
  4314.             FLUSH_JAPANESE_TEXT
  4315.             if ( CanUseCharFormatting() )
  4316.             {
  4317.                 better = EDT_GetCharacterData( *GetContext() );
  4318.                 if ( better )
  4319.                 {
  4320.                     better->mask = TF_STRIKEOUT;
  4321.                     better->values ^= TF_STRIKEOUT;
  4322.                     EDT_SetCharacterData( *GetContext(), better );
  4323.                     EDT_FreeCharacterData( better );
  4324.                 }
  4325.             }
  4326.             break;
  4327.         
  4328.         case cmd_Format_FontColor:
  4329.             FLUSH_JAPANESE_TEXT
  4330.             if ( CanUseCharFormatting() )
  4331.             {
  4332.                  better = EDT_GetCharacterData( *GetContext() );
  4333.                  if ( better )
  4334.                  {
  4335.                     Point where;
  4336.                     where.h = where.v = 0;
  4337.                     RGBColor inColor;
  4338.                     RGBColor outColor;
  4339.                     LO_Color pColor = {0, 0, 0};
  4340.                     
  4341.                     if ( !EDT_GetFontColor( *GetContext(), &pColor ) )
  4342.                     {        // still a perfectly respectable way to get the font color....
  4343.                             // get default color
  4344.                         EDT_PageData *pagedata = EDT_GetPageData( *GetContext() );
  4345.                         pColor = *pagedata->pColorText;
  4346.                         EDT_FreePageData( pagedata );
  4347.                     }
  4348.                     
  4349.                     inColor.red = (pColor.red << 8);
  4350.                     inColor.green = (pColor.green << 8);
  4351.                     inColor.blue = (pColor.blue << 8);
  4352.                     
  4353.                     if ( ::GetColor( where, (unsigned char *)*GetString(PICK_COLOR_RESID),
  4354.                                             &inColor, &outColor ) )
  4355.                     {
  4356.                         pColor.red = (outColor.red >> 8);
  4357.                         pColor.green = (outColor.green >> 8);
  4358.                         pColor.blue = (outColor.blue >> 8);
  4359.                         
  4360.                         better->mask = TF_FONT_COLOR;
  4361.                         better->values = TF_FONT_COLOR;
  4362.                         better->pColor = &pColor;
  4363.                         EDT_BeginBatchChanges( *GetContext() );
  4364.                         EDT_SetCharacterData( *GetContext(), better );
  4365.                         EDT_SetFontColor( *GetContext(), &pColor );
  4366.                         EDT_EndBatchChanges( *GetContext() );
  4367.                         better->pColor = NULL;
  4368.                         
  4369.                         // set control to the color that just got picked
  4370.                         Str255 colorstr;
  4371.                         XP_SPRINTF( (char *)&colorstr[2], "%02X%02X%02X", pColor.red, pColor.green, pColor.blue);
  4372.                         colorstr[1] = CColorPopup::CURRENT_COLOR_CHAR;    // put in leading character
  4373.                         colorstr[0] = strlen( (char *)&colorstr[1] );
  4374.                         mColorPopup->SetDescriptor( colorstr );
  4375.                         ::SetMenuItemText( mColorPopup->GetMenu()->GetMacMenuH(), 
  4376.                                             CColorPopup::CURRENT_COLOR_ITEM, 
  4377.                                             (unsigned char *)&colorstr );
  4378.                     }
  4379.                     EDT_FreeCharacterData( better );
  4380.                 }
  4381.             }
  4382.             break;
  4383.  
  4384.         case cmd_Format_Character_ClearAll:
  4385.             FLUSH_JAPANESE_TEXT
  4386.             if ( CanUseCharFormatting() )
  4387.                 if ( !EDT_IsSelected( *GetContext() )
  4388.                 || !EDT_SelectionContainsLink( *GetContext() )        // Detect if any links are included and warn user
  4389.                 || HandleModalDialog( EDITDLG_CONFIRM_OBLITERATE_LINK, NULL,  NULL) == ok )
  4390.                     EDT_FormatCharacter( *GetContext(), TF_NONE );
  4391.             break;
  4392.         
  4393.         case cmd_InsertEdit_Target:
  4394.             CEditDialog::Start( EDITDLG_TARGET, *GetContext(), 0, 
  4395.                                 EDT_GetCurrentElementType( *GetContext() ) != ED_ELEMENT_TARGET );
  4396.             break;
  4397.         
  4398.         case cmd_Format_Text:
  4399.             if ( CanUseCharFormatting() )
  4400.             {
  4401.                 if ( EDT_CanSetHREF( *GetContext() ) && EDT_GetHREF( *GetContext() ) )
  4402.                     CEditDialog::Start( EDITDLG_TEXT_AND_LINK, *GetContext(), 2 );
  4403.                 else
  4404.                     CEditDialog::Start( EDITDLG_TEXT_STYLE, *GetContext(), 1 );
  4405.             }
  4406.             else 
  4407.             {
  4408.                 ED_ElementType edtElemType = EDT_GetCurrentElementType( *GetContext() );
  4409.                 if ( ED_ELEMENT_IMAGE == edtElemType )
  4410.                     CEditDialog::Start( EDITDLG_IMAGE, *GetContext(), 1 );
  4411.                 else if ( ED_ELEMENT_HRULE == edtElemType )
  4412.                     CEditDialog::Start( EDITDLG_LINE_FORMAT, *GetContext() );
  4413.                 else if ( ED_ELEMENT_UNKNOWN_TAG == edtElemType )
  4414.                     CEditDialog::Start( EDITDLG_UNKNOWN_TAG, *GetContext() );
  4415.                 else if ( ED_ELEMENT_TARGET == edtElemType )
  4416.                     CEditDialog::Start( EDITDLG_TARGET, *GetContext() );         
  4417.             }
  4418.             break;
  4419.  
  4420. // Paragraph Toolbar
  4421.         case msg_MakeNoList:
  4422.             ToFromList( 0, ED_LIST_TYPE_DEFAULT );
  4423.             break;
  4424.         
  4425.         case msg_MakeNumList:
  4426.             ToFromList( P_NUM_LIST, ED_LIST_TYPE_DIGIT );
  4427.             break;
  4428.         
  4429.         case msg_MakeUnumList:
  4430.             ToFromList( P_UNUM_LIST, ED_LIST_TYPE_DEFAULT );
  4431.             break;
  4432.         
  4433.         case cmd_CheckSpelling:
  4434.             FLUSH_JAPANESE_TEXT
  4435.             do_spellcheck( *GetContext(), this, NULL );
  4436.             break;
  4437.         
  4438.         case cmd_Format_Paragraph_Indent:
  4439.             EDT_Indent( *GetContext() );
  4440.             break;
  4441.         
  4442.         case cmd_Format_Paragraph_UnIndent:
  4443.             EDT_Outdent( *GetContext() );
  4444.             break;
  4445.         
  4446.         case cmd_JustifyLeft:
  4447.             if ( EDT_GetCurrentElementType( *GetContext() ) == ED_ELEMENT_HRULE )
  4448.             {
  4449.                 EDT_HorizRuleData *fData = EDT_GetHorizRuleData( *GetContext() );
  4450.                 if ( fData )
  4451.                 {
  4452.                     fData->align = ED_ALIGN_LEFT;
  4453.                     EDT_SetHorizRuleData( *GetContext(), fData );
  4454.                     EDT_FreeHorizRuleData( fData );
  4455.                 }
  4456.             }
  4457.             else
  4458.                 EDT_SetParagraphAlign( *GetContext(), ED_ALIGN_LEFT );
  4459.             break;
  4460.  
  4461.         case cmd_JustifyCenter:
  4462.             if ( EDT_GetCurrentElementType( *GetContext() ) == ED_ELEMENT_HRULE )
  4463.             {
  4464.                 EDT_HorizRuleData *fData = EDT_GetHorizRuleData( *GetContext() );
  4465.                 if ( fData )
  4466.                 {
  4467.                     fData->align = ED_ALIGN_DEFAULT;
  4468.                     EDT_SetHorizRuleData( *GetContext(), fData );
  4469.                     EDT_FreeHorizRuleData( fData );
  4470.                 }
  4471.  
  4472.             }
  4473.             else
  4474.                 EDT_SetParagraphAlign( *GetContext(), ED_ALIGN_CENTER );
  4475.             break;
  4476.         
  4477.         case cmd_JustifyRight:
  4478.             if ( EDT_GetCurrentElementType( *GetContext() ) == ED_ELEMENT_HRULE )
  4479.             {
  4480.                 EDT_HorizRuleData *fData = EDT_GetHorizRuleData( *GetContext() );
  4481.                 if ( fData )
  4482.                 {
  4483.                     fData->align = ED_ALIGN_RIGHT;
  4484.                     EDT_SetHorizRuleData( *GetContext(), fData );
  4485.                     EDT_FreeHorizRuleData( fData );
  4486.                 }
  4487.             }
  4488.             else
  4489.                 EDT_SetParagraphAlign( *GetContext(), ED_ALIGN_RIGHT );
  4490.             break;
  4491.         
  4492. // Edit Menu
  4493.         case cmd_Undo:
  4494.             FLUSH_JAPANESE_TEXT
  4495.             EDT_Undo( *GetContext() );
  4496.             SetMenuCommandAndString( inCommand, cmd_Redo, STRPOUND_EDITOR_MENUS, EDITOR_MENU_REDO, NULL );
  4497.             break;
  4498.         
  4499.         case cmd_Redo:
  4500.             FLUSH_JAPANESE_TEXT
  4501.             EDT_Redo( *GetContext() );
  4502.             SetMenuCommandAndString( inCommand, cmd_Undo, STRPOUND_EDITOR_MENUS, EDITOR_MENU_UNDO, NULL );
  4503.             break;
  4504.         
  4505. // Insert Menu
  4506.         case cmd_Insert_Target:
  4507.             CEditDialog::Start( EDITDLG_TARGET, *GetContext(), 0, true );
  4508.             break;
  4509.  
  4510.         case cmd_Insert_Unknown_Tag:
  4511.             CEditDialog::Start( EDITDLG_UNKNOWN_TAG, *GetContext(), 0, true );
  4512.             break;
  4513.         
  4514.         case cmd_Insert_Link:
  4515.             CEditDialog::Start( EDITDLG_TEXT_AND_LINK, *GetContext(), 2, true );
  4516.             break;
  4517.  
  4518.         case cmd_InsertEditLink:
  4519.             if ( EDT_CanSetHREF( *GetContext() ) )
  4520.             {
  4521.                 if ( EDT_GetCurrentElementType( *GetContext() ) == ED_ELEMENT_IMAGE )
  4522.                     CEditDialog::Start( EDITDLG_IMAGE, *GetContext(), 2 );
  4523.                 else 
  4524.                 {
  4525.                     if ( EDT_IsSelected( *GetContext() ) )
  4526.                         CEditDialog::Start( EDITDLG_TEXT_AND_LINK, *GetContext(), 2 );
  4527.                     else
  4528.                         CEditDialog::Start( EDITDLG_TEXT_AND_LINK, *GetContext(), 2, true );
  4529.                 }
  4530.             } else
  4531.                 CEditDialog::Start( EDITDLG_TEXT_AND_LINK, *GetContext(), 2, true );
  4532.             break;
  4533.         
  4534.         case cmd_Insert_Image:
  4535.             CEditDialog::Start( EDITDLG_IMAGE, *GetContext(), 1, true );
  4536.             break;
  4537.         
  4538.         case cmd_InsertEditImage:
  4539.             if ( EDT_GetCurrentElementType( *GetContext() ) == ED_ELEMENT_IMAGE )
  4540.                 CEditDialog::Start( EDITDLG_IMAGE, *GetContext(), 1, false );
  4541.             else
  4542.                 CEditDialog::Start( EDITDLG_IMAGE, *GetContext(), 1, true );
  4543.             break;
  4544.         
  4545.         case cmd_Insert_Line:
  4546.             FLUSH_JAPANESE_TEXT
  4547.             InsertDefaultLine();
  4548.             break;
  4549.         
  4550.         case cmd_InsertEditLine:
  4551.             FLUSH_JAPANESE_TEXT
  4552.             if ( EDT_GetCurrentElementType( *GetContext() ) == ED_ELEMENT_HRULE )
  4553.                 CEditDialog::Start( EDITDLG_LINE_FORMAT, *GetContext() );
  4554.             else
  4555.                 InsertDefaultLine();
  4556.             break;
  4557.  
  4558.         case cmd_Insert_LineBreak:
  4559.             FLUSH_JAPANESE_TEXT
  4560.             EDT_InsertBreak( *GetContext(), ED_BREAK_NORMAL );
  4561.             break;
  4562.         
  4563.         case cmd_Insert_BreakBelowImage:
  4564.             FLUSH_JAPANESE_TEXT
  4565.             EDT_InsertBreak( *GetContext(), ED_BREAK_RIGHT );
  4566.             break;
  4567.         
  4568. #if 0
  4569.         case cmd_Insert_NonbreakingSpace:
  4570.             FLUSH_JAPANESE_TEXT
  4571.             EDT_InsertNonbreakingSpace( *GetContext() );
  4572.             break;
  4573. #endif
  4574.         
  4575. // Format Menu
  4576.         case cmd_Format_Document:
  4577.             CEditDialog::Start( EDITDLG_DOC_INFO, *GetContext(), 2 );
  4578.             break;
  4579.         
  4580.         case cmd_Format_PageTitle:
  4581.             CEditDialog::Start( EDITDLG_DOC_INFO, *GetContext(), 1 );
  4582.             break;
  4583.         
  4584. // Format Character Menu        
  4585.         case cmd_Format_Character_Nonbreaking:
  4586.             FLUSH_JAPANESE_TEXT
  4587.             if ( CanUseCharFormatting() )
  4588.             {
  4589.                 better = EDT_GetCharacterData( *GetContext() );
  4590.                 if ( better )
  4591.                 {
  4592.                     better->mask = TF_NOBREAK;
  4593.                     better->values ^= TF_NOBREAK;
  4594.                     EDT_SetCharacterData( *GetContext(), better );
  4595.                     EDT_FreeCharacterData( better );
  4596.                 }
  4597.             }
  4598.             break;
  4599.         
  4600.         case cmd_Format_Character_Superscript:
  4601.             FLUSH_JAPANESE_TEXT
  4602.             if ( CanUseCharFormatting() )
  4603.             {
  4604.                 better = EDT_GetCharacterData( *GetContext() );
  4605.                 if ( better )
  4606.                 {
  4607.                     better->mask = TF_SUPER | TF_SUB;
  4608.                     better->values ^= TF_SUPER;
  4609.                     if (better->values & TF_SUB)
  4610.                         better->values ^= TF_SUB;
  4611.                     EDT_SetCharacterData( *GetContext(), better );
  4612.                     EDT_FreeCharacterData( better );
  4613.                 }
  4614.             }
  4615.             break;
  4616.         
  4617.         case cmd_Format_Character_Subscript:
  4618.             FLUSH_JAPANESE_TEXT
  4619.             if ( CanUseCharFormatting() )
  4620.             {
  4621.                 better = EDT_GetCharacterData( *GetContext() );
  4622.                 if ( better )
  4623.                 {
  4624.                     better->mask = TF_SUB | TF_SUPER;
  4625.                     better->values ^= TF_SUB;
  4626.                     if ( better->values & TF_SUPER )
  4627.                         better->values ^= TF_SUPER;
  4628.                     EDT_SetCharacterData( *GetContext(), better );
  4629.                     EDT_FreeCharacterData( better );
  4630.                 }
  4631.             }
  4632.             break;
  4633.         
  4634.         case cmd_Format_Character_Blink:
  4635.             FLUSH_JAPANESE_TEXT
  4636.             if ( CanUseCharFormatting() )
  4637.             {
  4638.                 better = EDT_GetCharacterData( *GetContext() );
  4639.                 if ( better )
  4640.                 {
  4641.                     better->mask = TF_BLINK;
  4642.                     better->values ^= TF_BLINK;
  4643.                     EDT_SetCharacterData( *GetContext(), better );
  4644.                     EDT_FreeCharacterData( better );
  4645.                 }
  4646.             }
  4647.             break;
  4648.         
  4649. // Format Paragraph Menu        
  4650.         case cmd_Format_Paragraph_Normal:
  4651.             EDT_MorphContainer( *GetContext(), P_NSDT );
  4652.             break;
  4653.         
  4654.         case cmd_Format_Paragraph_Head1:
  4655.         case cmd_Format_Paragraph_Head2:
  4656.         case cmd_Format_Paragraph_Head3:
  4657.         case cmd_Format_Paragraph_Head4:
  4658.         case cmd_Format_Paragraph_Head5:
  4659.         case cmd_Format_Paragraph_Head6:
  4660.             EDT_MorphContainer( *GetContext(), inCommand - cmd_Format_Paragraph_Head1 + P_HEADER_1 );
  4661.             break;
  4662.         
  4663.         case cmd_Format_Paragraph_Address:
  4664.             EDT_MorphContainer( *GetContext(), P_ADDRESS );
  4665.             break;
  4666.         
  4667.         case cmd_Format_Paragraph_Formatted:
  4668.             EDT_MorphContainer( *GetContext(), P_PREFORMAT );
  4669.             break;
  4670.         
  4671.         case cmd_Format_Paragraph_List_Item:
  4672.             EDT_MorphContainer( *GetContext(), P_LIST_ITEM );
  4673.             break;
  4674.         
  4675.         case cmd_Format_Paragraph_Desc_Title:
  4676.             EDT_MorphContainer( *GetContext(), P_DESC_TITLE );
  4677.             break;
  4678.         
  4679.         case cmd_Format_Paragraph_Desc_Text:
  4680.             EDT_MorphContainer( *GetContext(), P_DESC_TEXT );
  4681.             break;
  4682.         
  4683. // Format Font Size Menu        
  4684.         case cmd_Format_Font_Size_N2:
  4685.         case cmd_Format_Font_Size_N1:
  4686.         case cmd_Format_Font_Size_0:
  4687.         case cmd_Format_Font_Size_P1:
  4688.         case cmd_Format_Font_Size_P2:
  4689.         case cmd_Format_Font_Size_P3:
  4690.         case cmd_Format_Font_Size_P4:
  4691.             FLUSH_JAPANESE_TEXT
  4692.             if ( CanUseCharFormatting() )
  4693.                 EDT_SetFontSize( *GetContext(), inCommand - cmd_Format_Font_Size_N2 + 1 );
  4694.             break;
  4695.  
  4696. // Format Table Menu
  4697.         case cmd_Insert_Table:
  4698.             CEditDialog::Start( EDITDLG_TABLE, *GetContext(), 0, true );
  4699.             break;
  4700.         
  4701.         case cmd_Delete_Table:
  4702.             FLUSH_JAPANESE_TEXT
  4703.             EDT_DeleteTable( *GetContext() );
  4704.             break;
  4705.         
  4706.         case cmd_Select_Table:
  4707.             FLUSH_JAPANESE_TEXT
  4708.             EDT_SelectTable( *GetContext() );
  4709.             break;
  4710.         
  4711.         case cmd_Format_Table:
  4712.             Boolean acrossCells = ( EDT_COP_SELECTION_CROSSES_TABLE_DATA_CELL == 
  4713.                                     EDT_CanCut( *GetContext(), true ));
  4714.  
  4715.             if ( !acrossCells && EDT_IsInsertPointInTableCell( *GetContext() ))
  4716.                 CEditDialog::Start( EDITDLG_TABLE_INFO, *GetContext(), 3 );
  4717.             
  4718.             else if ( EDT_IsInsertPointInTableRow( *GetContext() ))
  4719.                 CEditDialog::Start( EDITDLG_TABLE_INFO, *GetContext(), 2 );
  4720.             
  4721.             else if ( EDT_IsInsertPointInTable( *GetContext() ))
  4722.                 CEditDialog::Start( EDITDLG_TABLE_INFO, *GetContext(), 1 );
  4723.             break;
  4724.         
  4725.         case cmd_Insert_Row:
  4726.             FLUSH_JAPANESE_TEXT
  4727.             {
  4728.             EDT_TableRowData *pData = EDT_NewTableRowData();
  4729.             if ( pData )
  4730.             {
  4731.                 pData->align = ED_ALIGN_DEFAULT;
  4732.                 pData->valign = ED_ALIGN_DEFAULT;
  4733.                 EDT_InsertTableRows( *GetContext(), pData, true, 1 );
  4734.                 EDT_FreeTableRowData( pData );
  4735.             }
  4736.             }
  4737.             break;
  4738.         
  4739.         case cmd_Delete_Row:
  4740.             FLUSH_JAPANESE_TEXT
  4741.             EDT_DeleteTableRows( *GetContext(), 1 );
  4742.             break;
  4743.         
  4744.         case cmd_Format_Row:
  4745.             CEditDialog::Start( EDITDLG_TABLE_INFO, *GetContext(), 2 );
  4746.             break;
  4747.         
  4748.         case cmd_Insert_Col:
  4749.             FLUSH_JAPANESE_TEXT
  4750.             {
  4751.             EDT_TableCellData* pData = EDT_GetTableCellData( *GetContext() );
  4752.             if ( pData )
  4753.             {
  4754.                 EDT_InsertTableColumns( *GetContext(), pData, true, 1 );
  4755.                 EDT_FreeTableCellData( pData );
  4756.             }
  4757.             }
  4758.             break;
  4759.         
  4760.         case cmd_Delete_Col:
  4761.             FLUSH_JAPANESE_TEXT
  4762.             EDT_DeleteTableColumns( *GetContext(), 1 );
  4763.             break;
  4764.         
  4765.         case cmd_Insert_Cell:
  4766.             FLUSH_JAPANESE_TEXT
  4767.             {
  4768.             EDT_TableCellData* pData = EDT_GetTableCellData( *GetContext() );
  4769.             if ( pData )
  4770.             {
  4771.                 EDT_InsertTableCells( *GetContext(), pData, true, 1 );
  4772.                 EDT_FreeTableCellData( pData );
  4773.             }
  4774.             }
  4775.             break;
  4776.  
  4777.         case cmd_Delete_Cell:
  4778.             FLUSH_JAPANESE_TEXT
  4779.             EDT_DeleteTableCells( *GetContext(), 1 );
  4780.             break;
  4781.         
  4782.         case cmd_Format_Cell:
  4783.             CEditDialog::Start( EDITDLG_TABLE_INFO, *GetContext(), 3 );
  4784.             break;
  4785.                     
  4786. #if 0
  4787.         case cmd_DisplayTableBoundaries:
  4788.             Boolean doDisplayTableBorders;
  4789.             // toggle the current state and reset editor view
  4790.             doDisplayTableBorders = !EDT_GetDisplayTables( *GetContext() );
  4791.             EDT_SetDisplayTables( *GetContext(), doDisplayTableBorders );
  4792.         break;
  4793. #endif
  4794.  
  4795.         case msg_TabSelect:
  4796.             FLUSH_JAPANESE_TEXT
  4797.             mCaretActive = true;
  4798.             return true;    // yes, we'll take a tab so we can be the active field!
  4799.             break;
  4800.  
  4801.         case cmd_FormatColorsAndImage:
  4802.             CEditDialog::Start( EDITDLG_BKGD_AND_COLORS, *GetContext() );
  4803.             break;
  4804.         
  4805.         case cmd_DocumentInfo:
  4806.             if ( IsDoneLoading() && !EDT_IS_NEW_DOCUMENT( ((MWContext *)*GetContext()) ) )
  4807.                 return CHTMLView::ObeyCommand( inCommand, ioParam );
  4808.             break;
  4809.  
  4810.         default:
  4811.             return CHTMLView::ObeyCommand (inCommand, ioParam);
  4812.         }
  4813.     
  4814.     return true;
  4815. }
  4816.  
  4817.  
  4818. Boolean CEditView::SetDefaultCSID(Int16 prefCSID)
  4819. {
  4820.     int oldCSID = mContext->GetDefaultCSID();
  4821.  
  4822.     if ( prefCSID != oldCSID )
  4823.     {
  4824.         FLUSH_JAPANESE_TEXT
  4825.  
  4826.         mContext->SetDefaultCSID( prefCSID );
  4827.         mContext->SetWinCSID(INTL_DocToWinCharSetID( prefCSID ));
  4828.  
  4829.         if ( !EDT_SetEncoding( *GetContext(), prefCSID ))
  4830.         {
  4831.             // revert back!
  4832.             mContext->SetDefaultCSID( oldCSID );
  4833.             mContext->SetWinCSID( INTL_DocToWinCharSetID( oldCSID ) );
  4834.             return false;
  4835.         }
  4836.         
  4837.         EDT_RefreshLayout( *GetContext() );
  4838.     }
  4839.     return true;
  4840. }
  4841.  
  4842.  
  4843. void FE_DocumentChanged( MWContext * context, int32 iStartY, int32 iHeight )
  4844. {
  4845.     ((CEditView *)ExtractHyperView(context))->DocumentChanged( iStartY, iHeight );
  4846. }
  4847.  
  4848.  
  4849. Boolean GetCaretPosition(MWContext *context, LO_Element * element, int32 caretPos, 
  4850.                                     int32* caretX, int32* caretYLow, int32* caretYHigh )
  4851. {
  4852.     if (!context || !element )
  4853.         return false;
  4854.  
  4855.     int32 xVal = element->lo_any.x + element->lo_any.x_offset;
  4856.     int32 yVal = element->lo_any.y + element->lo_any.y_offset;
  4857.     int32 yValHigh = yVal + element->lo_any.height;
  4858.  
  4859.     switch ( element->type )
  4860.     {
  4861.         case LO_TEXT:
  4862.         {
  4863.             LO_TextStruct *text_data = & element->lo_text;
  4864.             CCharSet     charSet = ExtractHyperView(context)->GetCharSet();
  4865.             
  4866.             XP_FAIL_ASSERT( text_data->text_attr );
  4867.                 
  4868.             GrafPtr theSavePort = NULL;    
  4869.             if ( ExtractHyperView(context)->GetCachedPort() != qd.thePort )
  4870.             {
  4871.                 theSavePort = qd.thePort;
  4872.                 ::SetPort( ExtractHyperView(context)->GetCachedPort() );
  4873.             }
  4874.  
  4875.             HyperStyle style( context, &charSet, text_data->text_attr, true );
  4876.         
  4877.             style.Apply();
  4878.             
  4879.             // **** Don't know why this was here...
  4880.             //style.GetFontInfo();
  4881.             
  4882.             // Ñ╩measure the text
  4883.             char *textPtr;
  4884.             PA_LOCK( textPtr, char*, text_data->text );
  4885.  
  4886.             xVal += style.TextWidth( textPtr, 0, caretPos ) - 1;
  4887.  
  4888.             PA_UNLOCK( text_data->text );
  4889.             
  4890.             if ( theSavePort != NULL )
  4891.                 ::SetPort( theSavePort );
  4892.         }
  4893.         break;
  4894.  
  4895.         case LO_IMAGE:
  4896.         {
  4897.             LO_ImageStruct *pLoImage = &element->lo_image;
  4898.             if ( caretPos == 0 )
  4899.                 xVal -= 1;
  4900.             else
  4901.                 xVal += pLoImage->width + 2 * pLoImage->border_width;
  4902.         }
  4903.         break;
  4904.  
  4905.         default:
  4906.         {
  4907.             LO_Any *any = &element->lo_any;
  4908.             if ( caretPos == 0 )
  4909.                 xVal -= 1;
  4910.             else
  4911.                 xVal += any->width;
  4912.         }
  4913.         break;
  4914.     }
  4915.  
  4916.     *caretX = xVal;
  4917.     *caretYLow = yVal;
  4918.     *caretYHigh = yValHigh;
  4919.  
  4920.    return true;
  4921. }
  4922.  
  4923.  
  4924. static void DisplayCaretAnyElement( MWContext *context, LO_Element *element, int caretPos )
  4925. {
  4926.     CEditView *myView = (CEditView *)ExtractHyperView(context);
  4927.     if ( (myView == NULL) || !(myView->FocusDraw()) )
  4928.         return;
  4929.  
  4930.     int32 xVal, yVal, yValHigh;
  4931.  
  4932.     Boolean gotPosition;
  4933.     gotPosition = GetCaretPosition( context, element, caretPos, &xVal, &yVal, &yValHigh );
  4934.     if ( gotPosition && context->is_editor )
  4935.         myView->PlaceCaret( xVal, yVal, yValHigh );    
  4936. }
  4937.  
  4938.  
  4939. void FE_DisplayGenericCaret( MWContext * context, LO_Any * pLoAny, ED_CaretObjectPosition caretPos )
  4940. {
  4941.     DisplayCaretAnyElement( context, (LO_Element *)pLoAny, caretPos );
  4942. }
  4943.  
  4944. void FE_DisplayTextCaret( MWContext * context, int /*loc*/, LO_TextStruct * text_data, int char_offset )
  4945. {
  4946.     DisplayCaretAnyElement( context, (LO_Element *)text_data, char_offset );
  4947. }
  4948.  
  4949. void FE_DisplayImageCaret(MWContext * context, LO_ImageStruct * pImageData, ED_CaretObjectPosition caretPos )
  4950. {
  4951.     DisplayCaretAnyElement( context, (LO_Element *)pImageData, caretPos );
  4952. }
  4953.  
  4954.  
  4955. Bool FE_GetCaretPosition(MWContext *context, LO_Position* where, int32* caretX, int32* caretYLow, int32* caretYHigh)
  4956. {
  4957.     return GetCaretPosition( context, where->element, where->position, caretX, caretYLow, caretYHigh );
  4958. }
  4959.  
  4960.  
  4961. void FE_DestroyCaret( MWContext *pContext )
  4962. {
  4963.     if ( pContext->is_editor )
  4964.         ((CEditView *)ExtractHyperView(pContext))->RemoveCaret();    
  4965. }
  4966.  
  4967. void FE_GetDocAndWindowPosition( MWContext * context, int32 *pX, int32 *pY, int32 *pWidth, int32 *pHeight )
  4968. {
  4969.     SPoint32        frameLocation;
  4970.     SPoint32        imageLocation;
  4971.     SDimension16    frameSize;
  4972.  
  4973.     ((CEditView *)ExtractHyperView(context))->GetDocAndWindowPosition( frameLocation, imageLocation, frameSize );
  4974.         
  4975.     *pX = frameLocation.h - imageLocation.h;
  4976.     *pY = frameLocation.v - imageLocation.v;
  4977.     *pWidth = frameSize.width;
  4978.     *pHeight = frameSize.height;
  4979. }
  4980.