home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Framewrk / FWViews / FWEdView.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  28.6 KB  |  999 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWEdView.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFrameW.hpp"
  11.  
  12. #ifndef FWEDVIEW_H
  13. #include "FWEdView.h"
  14. #endif
  15.  
  16. #ifndef FWFRAME_H
  17. #include "FWFrame.h"
  18. #endif
  19.  
  20. #ifndef FWPART_H
  21. #include "FWPart.h"
  22. #endif
  23.  
  24. #ifndef FWDIALOG_H
  25. #include "FWDialog.h"
  26. #endif
  27.  
  28. #ifndef FWEVENT_H
  29. #include "FWEvent.h"
  30. #endif
  31.  
  32. #ifndef FWMNUBAR_H
  33. #include "FWMnuBar.h"
  34. #endif
  35.  
  36. #ifndef FWRECSHP_H
  37. #include "FWRecShp.h"
  38. #endif
  39.  
  40. #ifndef FWSELECT_H
  41. #include "FWSelect.h"
  42. #endif
  43.  
  44. #ifndef FWODGEOM_H
  45. #include "FWODGeom.h"
  46. #endif
  47.  
  48. #ifndef FWWINDOW_H
  49. #include "FWWindow.h"
  50. #endif
  51.  
  52. #ifndef FWCURSOR_H
  53. #include "FWCursor.h"
  54. #endif
  55.  
  56. #ifndef FWFONT_H
  57. #include "FWFont.h"
  58. #endif
  59.  
  60. #ifndef FWEVEDEF_H
  61. #include "FWEveDef.h"
  62. #endif
  63.  
  64. #ifndef FWCONTXT_H
  65. #include "FWContxt.h"
  66. #endif
  67.  
  68. #ifndef FWMEMORY_H
  69. #include "FWMemory.h"
  70. #endif
  71.  
  72. #ifndef SOM_ODFrame_xh
  73. #include <Frame.xh>
  74. #endif
  75.  
  76. #ifndef SOM_ODShape_xh
  77. #include <Shape.xh>
  78. #endif
  79.  
  80. #ifndef SLMIXOS_H
  81. #include <SLMixOS.h>    // for FW_Beep
  82. #endif
  83.  
  84. #ifndef SOM_Module_OpenDoc_Errors_defined
  85. #include <ErrorDef.xh>
  86. #endif
  87.  
  88. #ifdef FW_BUILD_MAC
  89. #include <scrap.h>
  90. #endif
  91.  
  92. #if defined(FW_BUILD_MAC) && !defined(__SCRIPT__)
  93. #include <Script.h>
  94. #endif
  95.  
  96. //========================================================================================
  97. // Runtime Information
  98. //========================================================================================
  99.  
  100. #ifdef FW_BUILD_MAC
  101. #pragma segment fwgadgts
  102. #endif
  103.  
  104. FW_DEFINE_CLASS_M2(FW_CEditView, FW_CView, FW_MNotifier)
  105. FW_DEFINE_AUTO(FW_CEditView)
  106.  
  107. //========================================================================================
  108. // Utilities
  109. //========================================================================================
  110.  
  111. inline Rect& operator+= (Rect & r, Point p)
  112. {
  113.     r.top += p.v;
  114.     r.left += p.h;
  115.     r.bottom += p.v;
  116.     r.right += p.h;
  117.     return r;
  118. }
  119.  
  120. #define FW_ISBACKSPACE(c)    (c == 0x08)
  121. #define FW_ISFWDDELETE(c)    (c == 0x7f)
  122. #define FW_ISARROWKEY(c)    (c == 0x1c || c == 0x1d || c == 0x1e || c == 0x1f)
  123. #define FW_ISINPUTCHAR(c)     !FW_ISBACKSPACE(c) && !FW_ISFWDDELETE(c) && !FW_ISARROWKEY(c)
  124.  
  125. //========================================================================================
  126. // CLASS FW_CEditView
  127. //========================================================================================
  128.  
  129. //----------------------------------------------------------------------------------------
  130. // FW_CEditView::FW_CEditView
  131. //----------------------------------------------------------------------------------------
  132.  
  133. FW_CEditView::FW_CEditView (Environment* ev, 
  134.                             FW_CSuperView* container, 
  135.                             const FW_CRect& bounds,
  136.                             ODID viewID, 
  137.                             const FW_CString& str, 
  138.                             const FW_CFont& font,
  139.                             short maxChars, 
  140.                             unsigned short attributes) 
  141.     : FW_CView (ev, container, bounds, viewID),
  142.     fMacTEHandle (nil),
  143.     fMaxChars(maxChars),
  144.     fEditAttributes (attributes)
  145. {
  146.     Initialize(ev, str, font);
  147.     
  148.     FW_END_CONSTRUCTOR
  149. }
  150.  
  151. //----------------------------------------------------------------------------------------
  152. // FW_CEditView::FW_CEditView
  153. //----------------------------------------------------------------------------------------
  154.  
  155. FW_CEditView::FW_CEditView (Environment* ev, 
  156.                             FW_CSuperView* container, 
  157.                             const FW_CRect& bounds,
  158.                             ODID viewID)
  159.     : FW_CView (ev, container, bounds, viewID),
  160.     FW_MNotifier(),
  161.     fMacTEHandle (nil),
  162.     fMaxChars(FW_MAXINT16),
  163.     fEditAttributes (FW_CEditView::kDrawBox + FW_CEditView::kAutoScroll)
  164. {
  165.     Initialize(ev, FW_CString(), FW_kNormalFont);
  166.     
  167.     FW_END_CONSTRUCTOR
  168. }
  169.  
  170. //----------------------------------------------------------------------------------------
  171. // FW_CEditView::FW_CEditView
  172. //----------------------------------------------------------------------------------------
  173.  
  174. FW_CEditView::FW_CEditView (Environment* ev) 
  175.     : FW_CView (ev),
  176.     FW_MNotifier(),
  177.     fMacTEHandle (nil),
  178.     fMaxChars(0),
  179.     fEditAttributes(0)
  180. {
  181.     FW_END_CONSTRUCTOR
  182. }
  183.  
  184. //----------------------------------------------------------------------------------------
  185. // FW_CEditView::InitEditView
  186. //----------------------------------------------------------------------------------------
  187.  
  188. void FW_CEditView::Initialize(Environment* ev, const FW_CString& text, const FW_CFont& font)
  189. {
  190.     // Set up the current port for the TE record  - [LSD] OK to use active facet?
  191.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  192.     FW_ASSERT(facet);
  193.     FW_CPlatformGraphicContext gc (ev, facet);
  194.     
  195.     FW_CPlatformRect pBounds;
  196.     fMacTEHandle = ::TENew (&pBounds, &pBounds);
  197.     if (!fMacTEHandle) 
  198.         FW_Failure (kODErrOutOfMemory);
  199.     
  200.     SetFont(ev, font);    
  201.  
  202.     // Set TE feature flags
  203.     ::TEFeatureFlag(teFAutoScr, (fEditAttributes & FW_CEditView::kAutoScroll) ?
  204.                 teBitSet : teBitClear, fMacTEHandle);
  205.     ::TEFeatureFlag(teFTextBuffering, (fEditAttributes & FW_CEditView::kTextBuffering) ?
  206.                 teBitSet : teBitClear, fMacTEHandle);
  207.     ::TEFeatureFlag(teFOutlineHilite, (fEditAttributes & FW_CEditView::kOutlineHilite) ?
  208.                 teBitSet : teBitClear, fMacTEHandle);
  209.     ::TEFeatureFlag(teFInlineInput, (fEditAttributes & FW_CEditView::kInlineInput) ?
  210.                 teBitSet : teBitClear, fMacTEHandle);
  211.     ::TEFeatureFlag(teFUseTextServices, (fEditAttributes & FW_CEditView::kTextServices) ?
  212.                 teBitSet : teBitClear, fMacTEHandle);
  213.  
  214.     // Mac TextEdit is limited to 32K
  215.     if (fMaxChars <= 0 || fMaxChars > FW_MAXINT16)  
  216.         fMaxChars = FW_MAXINT16;
  217.  
  218.     // Access the string buffer directly to pass the char* to TEInsert
  219.     FW_ByteCount bufLen = text.GetByteLength();
  220.     if (bufLen > 0)
  221.     {
  222.         if (bufLen > fMaxChars)
  223.             bufLen = fMaxChars;
  224.             
  225.         const char* buf = text.RevealBuffer();    
  226.         ::TESetText(buf, bufLen, fMacTEHandle);    
  227.     }
  228.     
  229.     // Update TE rects and recompute text layout
  230.     MacSetRects(ev);
  231.     
  232. }
  233.  
  234. //----------------------------------------------------------------------------------------
  235. // FW_CEditView::~FW_CEditView
  236. //----------------------------------------------------------------------------------------
  237.  
  238. FW_CEditView::~FW_CEditView ()
  239. {
  240.     FW_START_DESTRUCTOR
  241.     if (fMacTEHandle)
  242.     {
  243.         // XXX need to test disposing when the window is still up
  244.         ::TEDispose (fMacTEHandle);
  245.     }
  246. }
  247.  
  248. #pragma mark -
  249. //----------------------------------------------------------------------------------------
  250. // FW_CEditView::GetTextLength
  251. //----------------------------------------------------------------------------------------
  252.  
  253. FW_ByteCount FW_CEditView::GetTextLength (Environment* ev) const
  254. {
  255. FW_UNUSED(ev);
  256.  
  257. #if defined(FW_BUILD_MAC)
  258.     return (FW_ByteCount)(*MacTE())->teLength;    
  259. #endif
  260. }
  261.  
  262. //----------------------------------------------------------------------------------------
  263. // FW_CEditView::GetText
  264. //----------------------------------------------------------------------------------------
  265.  
  266. FW_CString FW_CEditView::GetText (Environment* ev) const
  267. {
  268. FW_UNUSED(ev);
  269.  
  270. #if defined(FW_BUILD_MAC)
  271.     Handle handleText = (*MacTE())->hText;
  272.     FW_Locale locale;
  273.     GetLocale(ev, locale);
  274.  
  275.     FW_CAcquireLockedSystemHandle locked (handleText);
  276.     return FW_CString(*handleText, (FW_ByteCount)(*MacTE())->teLength, locale);
  277. #endif
  278. }
  279.  
  280. //----------------------------------------------------------------------------------------
  281. // FW_CEditView::GetSelectedText
  282. //----------------------------------------------------------------------------------------
  283.  
  284. FW_CString FW_CEditView::GetSelectedText (Environment* ev) const
  285. {
  286. FW_UNUSED(ev);
  287.  
  288. #if defined(FW_BUILD_MAC)
  289.     short startOffset = (*MacTE())->selStart;
  290.     FW_ByteCount byteCount = (*MacTE())->selEnd - startOffset;
  291.     FW_Locale locale;
  292.     GetLocale(ev, locale);
  293.  
  294.     if (byteCount <= 0)        // empty selection
  295.     {
  296.         FW_CString emptyString;
  297.         emptyString.SetEmpty(locale);
  298.         return FW_CString(emptyString);
  299.     }
  300.  
  301.     Handle handleText = (*MacTE())->hText;
  302.     FW_CAcquireLockedSystemHandle locked (handleText);
  303.     return FW_CString(*handleText + startOffset, byteCount, locale);    
  304. #endif
  305. }
  306.  
  307. //----------------------------------------------------------------------------------------
  308. // FW_CEditView::GetSelectionRange
  309. //----------------------------------------------------------------------------------------
  310.  
  311. void FW_CEditView::GetSelectionRange (Environment* ev, short& startOffset, short& endOffset) const
  312. {
  313. FW_UNUSED(ev);
  314.  
  315. #if defined(FW_BUILD_MAC)
  316.     startOffset = (*MacTE())->selStart;
  317.     endOffset = (*MacTE())->selEnd;
  318. #endif
  319. }
  320.  
  321. //----------------------------------------------------------------------------------------
  322. // FW_CEditView::ClearText
  323. //----------------------------------------------------------------------------------------
  324.  
  325. void FW_CEditView::ClearText (Environment* ev)
  326. {
  327.     SetText (ev, FW_CString());
  328. }
  329.  
  330. //----------------------------------------------------------------------------------------
  331. // FW_CEditView::SetText
  332. //----------------------------------------------------------------------------------------
  333.  
  334. void FW_CEditView::SetText (Environment* ev, const FW_CString& str)
  335. {
  336. #if defined(FW_BUILD_MAC)
  337.     // Access the string buffer directly to pass the char* to TEInsert
  338.     FW_ByteCount bufLen = str.GetByteLength();
  339.     if (bufLen > fMaxChars) 
  340.         bufLen = fMaxChars;
  341.     const char* buf = str.RevealBuffer();
  342.  
  343.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  344.     if (facet == NULL)
  345.         return;        // frame is in limbo
  346.         
  347.     FW_CViewContext gc(ev, this, facet);
  348.     MacAdjustRects(ev, gc);
  349.  
  350.     PrivSelectAll();
  351.     ::TEDelete (fMacTEHandle);
  352.     ::TEInsert (buf, bufLen, fMacTEHandle);    
  353. #endif
  354.     Notify(ev, FW_kChangedMsg);
  355. }
  356.  
  357. //----------------------------------------------------------------------------------------
  358. // FW_CEditView::SetSelectedText
  359. //----------------------------------------------------------------------------------------
  360.  
  361. void FW_CEditView::SetSelectedText(Environment* ev, const FW_CString& newText)
  362. {
  363. #if defined(FW_BUILD_MAC)
  364.     FW_ByteCount bufLen = newText.GetByteLength();
  365.     const char* buf = newText.RevealBuffer();
  366.  
  367.     // Don't insert more characters than allowed
  368.     FW_ByteCount notSelectedChars = (*MacTE())->teLength - ((*MacTE())->selEnd - (*MacTE())->selStart);
  369.  
  370.     if (notSelectedChars >= fMaxChars) 
  371.         return;
  372.     if ((bufLen + notSelectedChars) > fMaxChars) 
  373.         bufLen = fMaxChars - notSelectedChars;
  374.  
  375.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  376.     if (facet == NULL)
  377.         return;        // frame is in limbo
  378.  
  379.     FW_CViewContext gc(ev, this, facet);
  380.     MacAdjustRects(ev, gc);
  381.  
  382.     ::TEDelete (fMacTEHandle);                    // delete selected text
  383.     ::TEInsert (buf, bufLen, fMacTEHandle);        // insert new text
  384. #endif
  385.     Notify(ev, FW_kChangedMsg);
  386. }
  387.  
  388. //----------------------------------------------------------------------------------------
  389. // FW_CEditView::InsertText
  390. //----------------------------------------------------------------------------------------
  391.  
  392. void FW_CEditView::InsertText(Environment* ev, const FW_CString& textToInsert, short offset)
  393. {
  394. #ifdef FW_BUILD_MAC
  395.  
  396.     FW_ByteCount bufLen = textToInsert.GetByteLength();
  397.     const char* buf = textToInsert.RevealBuffer();
  398.  
  399.     // Don't insert more characters than allowed
  400.     FW_ByteCount curLength = (*MacTE())->teLength;
  401.     if (curLength >= fMaxChars) 
  402.         return;
  403.     if ((bufLen + curLength) > fMaxChars) 
  404.         bufLen = fMaxChars - curLength;
  405.  
  406.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  407.     if (facet == NULL) 
  408.         return;        // frame is in limbo
  409.  
  410.     FW_CViewContext gc(ev, this, facet);
  411.     MacAdjustRects(ev, gc);
  412.  
  413.     ::TESetSelect(offset, offset, fMacTEHandle);
  414.     ::TEInsert(buf, bufLen, fMacTEHandle);
  415. #endif
  416.     Notify(ev, FW_kChangedMsg);
  417. }
  418.  
  419. //----------------------------------------------------------------------------------------
  420. // FW_CEditView::SelectText
  421. //----------------------------------------------------------------------------------------
  422.  
  423. void FW_CEditView::SelectText(Environment* ev, short startOffset, short endOffset)
  424. {
  425. #ifdef FW_BUILD_MAC
  426.     short offset = startOffset;
  427.     if (startOffset > endOffset)
  428.     {
  429.         startOffset = endOffset;
  430.         endOffset = offset;
  431.     }
  432.         
  433.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  434.     if (facet == NULL)
  435.         return;        // frame is in limbo
  436.     
  437.     FW_CViewContext gc(ev, this, facet);
  438.     MacAdjustRects(ev, gc);
  439.  
  440.     ::TESetSelect(startOffset, endOffset, fMacTEHandle);
  441. #endif
  442.     Notify(ev, FW_kChangedMsg);
  443. }
  444.  
  445. //----------------------------------------------------------------------------------------
  446. // FW_CEditView::PrivSelectAll
  447. //----------------------------------------------------------------------------------------
  448. // Used internally when we don't need to create a view context
  449.  
  450. void  FW_CEditView::PrivSelectAll()
  451. {
  452. #ifdef FW_BUILD_MAC
  453.     ::TESetSelect (0, FW_MAXINT16, fMacTEHandle);
  454. #endif
  455. }
  456.  
  457. //----------------------------------------------------------------------------------------
  458. // FW_CEditView::PrivCheckMaxChars
  459. //----------------------------------------------------------------------------------------
  460.  
  461. FW_Boolean  FW_CEditView::PrivCheckMaxChars(long numChars)
  462. {
  463.     // checks if we are trying to add too many chars
  464. #ifdef FW_BUILD_MAC
  465.     long numSelectedChars = (*MacTE())->selEnd - (*MacTE())->selStart;
  466.     
  467.     return (((*MacTE())->teLength + numChars - numSelectedChars) > fMaxChars);
  468. #endif
  469. }
  470.  
  471. //----------------------------------------------------------------------------------------
  472. // FW_CEditView::SetFont
  473. //----------------------------------------------------------------------------------------
  474.  
  475. void FW_CEditView::SetFont (Environment* ev, const FW_CFont &font)
  476. {
  477. FW_UNUSED(ev);    
  478. #ifdef FW_BUILD_MAC
  479.     // if textSize is less than zero, we've somehow gotten
  480.     // a styled text record, which we don't expect.
  481.     FW_ASSERT((*MacTE())->txSize >= 0);
  482.     
  483.     (*MacTE())->txFont = font.MacGetFontID();
  484.     (*MacTE())->txFace = font.MacGetFontStyle();
  485.     (*MacTE())->txSize = FW_FixedToInt(font.GetFontSize());
  486. //    (*MacTE())->txMode = scrOr;
  487.     
  488.     FMInput    fontSpecs;
  489.     fontSpecs.family    = (*MacTE())->txFont;
  490.     fontSpecs.size        = (*MacTE())->txSize;
  491.     fontSpecs.face        = (*MacTE())->txFace;
  492.     fontSpecs.needBits    = false;
  493.     fontSpecs.device    = 0;
  494.     fontSpecs.numer.h    = 1;
  495.     fontSpecs.numer.v    = 1;
  496.     fontSpecs.denom.h    = 1;
  497.     fontSpecs.denom.v    = 1; 
  498.     
  499.     FMOutPtr fontInfo = ::FMSwapFont(&fontSpecs);    
  500.     (*MacTE())->lineHeight = fontInfo->ascent + fontInfo->descent + fontInfo->leading;
  501.     (*MacTE())->fontAscent = fontInfo->ascent;    
  502.     ::TECalText(fMacTEHandle);    
  503.             
  504. #endif
  505.     Notify(ev, FW_kChangedMsg);
  506. }
  507.  
  508. //----------------------------------------------------------------------------------------
  509. // FW_CEditView::GetFont
  510. //----------------------------------------------------------------------------------------
  511.  
  512. FW_CFont FW_CEditView::GetFont(Environment* ev) const
  513. {
  514. FW_UNUSED(ev);
  515. #ifdef FW_BUILD_MAC
  516.     FW_CFont font;
  517.     
  518.     font.SetFontStyle(FW_CFont::PlatformToODFFontStyle((*MacTE())->txFace));
  519.     font.MacSetFontID((*MacTE())->txFont);
  520.     font.SetFontSize(FW_IntToFixed((*MacTE())->txSize));
  521.     
  522.     return font;
  523. #endif
  524. }
  525.  
  526. #pragma mark -
  527. //----------------------------------------------------------------------------------------
  528. // FW_CEditView::SetVisible
  529. //----------------------------------------------------------------------------------------
  530.  
  531. void FW_CEditView::SetVisible(Environment* ev, FW_Boolean visible, FW_Boolean propagate)
  532. {
  533.     FW_CView::SetVisible(ev, visible, propagate);
  534.     
  535.     if (!visible)
  536.     {
  537.         // Will stop idling if this edit view was active
  538.         ResignTarget(ev);    
  539.     }
  540. }
  541.  
  542. //----------------------------------------------------------------------------------------
  543. // FW_CEditView::WantsToBeTarget
  544. //----------------------------------------------------------------------------------------
  545.  
  546. FW_Boolean FW_CEditView::WantsToBeTarget(Environment* ev)
  547. {
  548.     // Let visible edit views process keys and menu commands
  549.     if (IsVisible(ev))
  550.         return TRUE;
  551.     else
  552.         return FALSE;
  553. }
  554.  
  555. //----------------------------------------------------------------------------------------
  556. // FW_CEditView::ActivateTarget
  557. //----------------------------------------------------------------------------------------
  558.  
  559. void FW_CEditView::ActivateTarget(Environment* ev, FW_Boolean tabSelection)
  560. {
  561. FW_UNUSED(ev);
  562.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  563.     FW_ASSERT(facet);
  564.     
  565.     FW_CViewContext gc(ev, this, facet);
  566.     MacAdjustRects(ev, gc);
  567.  
  568.     if (tabSelection)     
  569.         PrivSelectAll();
  570.     
  571.     ::TEActivate (fMacTEHandle);
  572. }
  573.  
  574. //----------------------------------------------------------------------------------------
  575. // FW_CEditView::DeactivateTarget
  576. //----------------------------------------------------------------------------------------
  577.  
  578. void FW_CEditView::DeactivateTarget (Environment* ev)
  579. {
  580.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);        
  581.     if (facet)
  582.     {
  583.         FW_CViewContext gc(ev, this, facet);
  584.         MacAdjustRects(ev, gc);
  585.  
  586.         ::TEDeactivate(fMacTEHandle);
  587.     }
  588.     
  589.     PrivEnableEditMenu(ev, false);
  590. }
  591.  
  592. //----------------------------------------------------------------------------------------
  593. // FW_CEditView::PrivEnableEditMenu
  594. //----------------------------------------------------------------------------------------
  595.  
  596. void FW_CEditView::PrivEnableEditMenu(Environment *ev, FW_Boolean enable)
  597. {
  598.     // Check if this edit-view belongs to a Modal Dialog before enabling the Edit menu
  599.     FW_CFrame* frame = GetFrame(ev);
  600.     if (GetFrame(ev)->HasModalFocus(ev))
  601.         frame->GetPart(ev)->GetMenuBar(ev)->EnableCommand(ev, kODCommandEditMenu, enable);
  602. }
  603.  
  604. //----------------------------------------------------------------------------------------
  605. // FW_CEditView::DoIdle
  606. //----------------------------------------------------------------------------------------
  607.  
  608. FW_Handled FW_CEditView::DoIdle (Environment* ev, const FW_CNullEvent& event)
  609. {
  610. FW_UNUSED(event);
  611.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  612.     
  613.     // facet is NULL when frame is in limbo
  614.     if (facet)    
  615.     {
  616.         FW_CViewContext gc(ev, this, facet);
  617.         MacAdjustRects(ev, gc);
  618.             
  619. #if defined(FW_BUILD_MAC)
  620.         ::TEIdle (fMacTEHandle);
  621. #endif
  622.     }
  623.     
  624.     return FW_kNotHandled; 
  625. }
  626.  
  627. //----------------------------------------------------------------------------------------
  628. // FW_CEditView::DoMouseDown
  629. //----------------------------------------------------------------------------------------
  630.  
  631. FW_Handled FW_CEditView::DoMouseDown (Environment* ev, const FW_CMouseEvent& event)
  632. {
  633.     FW_CViewContext gc(ev, this, event.GetFacet(ev));
  634.     MacAdjustRects(ev, gc);
  635.  
  636.     FW_CPoint where = event.GetMousePosition (ev, FW_CMouseEvent::kFrame);
  637.     FrameToViewContent (ev, where);
  638.     FW_CPlatformPoint pWhere;
  639.     pWhere = gc.LogicalToDevice (where);
  640.     
  641.     ::TEClick (pWhere, event.IsExtendModifier(ev), fMacTEHandle);
  642.     
  643.     return FW_kHandled;
  644. }
  645.  
  646. //----------------------------------------------------------------------------------------
  647. // FW_CEditView::DoVirtualKey
  648. //----------------------------------------------------------------------------------------
  649.  
  650. FW_Handled FW_CEditView::DoVirtualKey (Environment* ev, const FW_CVirtualKeyEvent & event)
  651. {
  652.     FW_Handled keyHandled = FW_kNotHandled;
  653.     short    keyCode = event.GetKeyCode(ev);
  654.         
  655.     if (keyCode == FW_kVKHome || keyCode == FW_kVKEnd) 
  656.     {
  657.         keyHandled = FW_kHandled;
  658.         
  659.         FW_CViewContext gc(ev, this, GetFrame(ev)->GetActiveFacet(ev));
  660.         MacAdjustRects(ev, gc);
  661.  
  662.         if(keyCode == FW_kVKHome)
  663.             ::TESetSelect(0, 0, fMacTEHandle);                        // Go to the top
  664.         else
  665.             ::TESetSelect(FW_MAXINT16, FW_MAXINT16, fMacTEHandle); // Go to the end
  666.     }
  667.     
  668.     return keyHandled;    // if false key will be handled in DoCharKey
  669. }
  670.  
  671. //----------------------------------------------------------------------------------------
  672. // FW_CEditView::DoCharKey
  673. //----------------------------------------------------------------------------------------
  674.  
  675. FW_Handled FW_CEditView::DoCharKey (Environment* ev, const FW_CCharKeyEvent & event)
  676. {
  677.     // Ignore Command-characters which are not associated to menu commands
  678.     if (event.GetPlatformModifiers(ev) & cmdKey)
  679.         return FW_kNotHandled;
  680.         
  681.     return InputCharKey(ev, event.GetChar(ev));
  682. }
  683.  
  684. //----------------------------------------------------------------------------------------
  685. // FW_CEditView::InputCharKey
  686. //----------------------------------------------------------------------------------------
  687.  
  688. FW_Handled FW_CEditView::InputCharKey (Environment* ev, char c)
  689. {
  690.     FW_CViewContext gc(ev, this, GetFrame(ev)->GetActiveFacet(ev));
  691.     MacAdjustRects(ev, gc);
  692.     
  693. #if defined(FW_BUILD_MAC)
  694.     if (FW_ISINPUTCHAR(c) && PrivCheckMaxChars(1) == true)
  695.         FW_Beep();
  696.     else
  697.     {
  698.         ::TEKey (c, fMacTEHandle);
  699.         Notify(ev, FW_kChangedMsg);
  700.     }
  701.         
  702. #endif
  703.     
  704.     return FW_kHandled;
  705. }
  706.  
  707. //----------------------------------------------------------------------------------------
  708. // FW_CEditView::DoAdjustMenus
  709. //----------------------------------------------------------------------------------------
  710.  
  711. FW_Handled FW_CEditView::DoAdjustMenus (Environment *ev, FW_CMenuBar* menuBar, 
  712.                         FW_Boolean hasMenuFocus, FW_Boolean isRoot)
  713. {
  714. FW_UNUSED(isRoot);
  715.  
  716.     if (hasMenuFocus)
  717.     {
  718.         // Must adjust edit menu for modal dialogs first
  719.         PrivEnableEditMenu(ev, true);
  720.     
  721.         long offset;
  722.         FW_Boolean hasSelection = ((*MacTE())->selStart != (*MacTE())->selEnd);
  723.         FW_Boolean hasCharacters = ((*MacTE())->teLength > 0);
  724.         FW_Boolean hasClipboard = (::GetScrap(0, 'TEXT', &offset) > 0);
  725.  
  726.         menuBar->EnableCommand (ev, kODCommandCut, hasSelection);
  727.         menuBar->EnableCommand (ev, kODCommandCopy, hasSelection);
  728.         menuBar->EnableCommand (ev, kODCommandPaste, hasClipboard);
  729.         menuBar->EnableCommand (ev, kODCommandClear, hasSelection);
  730.         menuBar->EnableCommand (ev, kODCommandSelectAll, hasCharacters);
  731.     }
  732.     
  733.     return FW_kNotHandled;    // let parent views adjust their menus
  734. }
  735.  
  736. //----------------------------------------------------------------------------------------
  737. // FW_CEditView::DoTECommand
  738. //----------------------------------------------------------------------------------------
  739.  
  740. void FW_CEditView::DoTECommand (Environment* ev, ODCommandID id, FW_Boolean useScrap)
  741. {
  742.     // DoTECommand can be called by subclasses with useScrap = false when implementing
  743.     // support for ODF Data Interchange (see the Form example) 
  744.  
  745.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  746.     FW_ASSERT(facet);
  747.     FW_CViewContext gc(ev, this, facet);
  748.     MacAdjustRects(ev, gc);
  749.     
  750.     switch (id) 
  751.     {
  752.         case kODCommandCut:
  753.             ::TECut (fMacTEHandle);
  754.             if (useScrap)
  755.             {
  756.                 ::ZeroScrap();
  757.                 ::TEToScrap();
  758.             }
  759.             break;
  760.  
  761.         case kODCommandCopy: 
  762.             ::TECopy (fMacTEHandle);
  763.             if (useScrap)
  764.             {
  765.                 ::ZeroScrap();
  766.                 ::TEToScrap();
  767.             }
  768.             break;
  769.  
  770.         case kODCommandPaste: 
  771.             if (useScrap)
  772.             {
  773.                 long offset;
  774.                 long scrapLength = ::GetScrap(0, 'TEXT', &offset);
  775.                 if (PrivCheckMaxChars(scrapLength))
  776.                 {
  777.                     FW_Beep();        // can't paste that many characters
  778.                     break;
  779.                 }
  780.                 ::TEFromScrap();
  781.             }
  782.             ::TEPaste (fMacTEHandle);
  783.             Notify(ev, FW_kChangedMsg);
  784.             break;
  785.  
  786.         case kODCommandClear: 
  787.             Notify(ev, FW_kChangedMsg);
  788.             ::TEDelete (fMacTEHandle);
  789.             break;
  790.  
  791.         case kODCommandSelectAll: 
  792.             PrivSelectAll();
  793.             break;
  794.     }
  795. }
  796.  
  797. //----------------------------------------------------------------------------------------
  798. // FW_CEditView::DoMenu
  799. //----------------------------------------------------------------------------------------
  800.  
  801. FW_Handled FW_CEditView::DoMenu (Environment* ev, const FW_CMenuEvent& event)
  802. {
  803.     ODCommandID id = event.GetCommandID(ev);
  804.     
  805.     switch (id) 
  806.     {
  807.         case kODCommandCut: 
  808.         case kODCommandCopy: 
  809.         case kODCommandPaste: 
  810.         case kODCommandClear: 
  811.         case kODCommandSelectAll: 
  812.             DoTECommand(ev, id, true);
  813.             break;
  814.  
  815.         default:
  816.             return FW_CView::DoMenu (ev, event);
  817.     }
  818.     return FW_kHandled;
  819. }
  820.  
  821. //----------------------------------------------------------------------------------------
  822. // FW_CEditView::Draw
  823. //----------------------------------------------------------------------------------------
  824.  
  825. void FW_CEditView::Draw (Environment *ev, ODFacet* facet, ODShape* invalidShape)
  826. {
  827. FW_UNUSED(invalidShape);
  828.     if (HasBox()) {
  829.         // don't use a platform context for the adorners
  830.         FW_CViewContext gc (ev, this, facet); 
  831.         FW_CRect bounds(FW_kZeroPoint, GetSize(ev));
  832.         FW_CRectShape::RenderRect (gc, bounds, FW_kFrame, FW_CInk(FW_kRGBBlack));
  833.         
  834.         // [LSD] Need this? 
  835.         bounds.Inset (FW_kFixedPos1, FW_kFixedPos1);
  836.         FW_CRectShape::RenderRect (gc, bounds, FW_kFill, FW_kWhiteEraseInk);
  837.     }
  838.     FW_CViewContext gc(ev, this, facet);
  839.     MacAdjustRects(ev, gc);
  840.     FW_CPlatformRect pBounds = gc.LogicalToDevice (GetTextBounds(ev));
  841.     
  842. #if defined(FW_BUILD_MAC)
  843.     ::TEUpdate (&pBounds, fMacTEHandle);
  844. #endif
  845. }
  846.  
  847. //----------------------------------------------------------------------------------------
  848. // FW_CEditView::AdjustCursor
  849. //----------------------------------------------------------------------------------------
  850.  
  851. FW_Handled FW_CEditView::AdjustCursor(Environment *ev, ODFacet* odFacet, const FW_CPoint& where, ODEventInfo* eventInfo)
  852. {
  853. FW_UNUSED(odFacet);
  854. FW_UNUSED(where);
  855. FW_UNUSED(eventInfo);
  856.  
  857.     if (GetFrame(ev)->HasSelectionFocus(ev) == FALSE)            
  858.         return FW_kNotHandled;
  859.     
  860.     FW_gIBeamCursor.Select();
  861.     return FW_kHandled;
  862. }
  863.  
  864. //----------------------------------------------------------------------------------------
  865. // FW_CEditView::LocationChanged
  866. //----------------------------------------------------------------------------------------
  867.  
  868. void FW_CEditView::LocationChanged(Environment* ev, const FW_CPoint& oldLocation)
  869. {
  870.     FW_CView::LocationChanged(ev, oldLocation);
  871.  
  872.     // call MacAdjustRects() instead of MacSetRects() since size didn't change
  873.     FW_CViewContext gc(ev, this, GetFrame(ev)->GetActiveFacet(ev));
  874.     MacAdjustRects(ev, gc);
  875. }
  876.  
  877. //----------------------------------------------------------------------------------------
  878. // FW_CEditView::SizeChanged
  879. //----------------------------------------------------------------------------------------
  880.  
  881. void FW_CEditView::SizeChanged(Environment* ev, const FW_CPoint& oldSize)
  882. {
  883.     FW_CView::SizeChanged(ev, oldSize);
  884.  
  885.     MacSetRects (ev);
  886. }
  887.  
  888. #pragma mark -
  889. //----------------------------------------------------------------------------------------
  890. // FW_CEditView::GetTextBounds
  891. //----------------------------------------------------------------------------------------
  892.  
  893. FW_CRect FW_CEditView::GetTextBounds (Environment* ev)
  894. {
  895.     // Get view bounds
  896.     FW_CRect bounds (FW_kZeroPoint, GetSize(ev));
  897.     
  898.     // shrink by 2 pixels if the edit view has a box
  899.     if (HasBox())
  900.         bounds.Inset(FW_IntToFixed(2), FW_IntToFixed(2));
  901.  
  902.     return bounds;
  903. }
  904.  
  905. //----------------------------------------------------------------------------------------
  906. // FW_CEditView::MacAdjustRects
  907. //----------------------------------------------------------------------------------------
  908. // MacAdjustRects aligns the TEhandle's rect fields to the view (which may have
  909. // scrolled, etc.).  Don't need to call TECalText here, rect sizes are not
  910. // changed.
  911.  
  912. void FW_CEditView::MacAdjustRects (Environment* ev, FW_CGraphicContext & gc)
  913. {
  914.     FW_CPlatformRect pBounds = gc.LogicalToDevice (GetTextBounds(ev));
  915.     
  916.     if (pBounds != (*MacTE())->viewRect) {
  917.         FW_CPlatformPoint moving (pBounds.left - (*MacTE())->viewRect.left, pBounds.top - (*MacTE())->viewRect.top);
  918.         (*MacTE())->viewRect += moving;
  919.         (*MacTE())->destRect += moving;
  920.         (*MacTE())->selRect += moving;
  921.     }
  922. }
  923.  
  924. //----------------------------------------------------------------------------------------
  925. // FW_CEditView::MacSetRects
  926. //----------------------------------------------------------------------------------------
  927. // MacSetRects resets the TEhandle's rect field at init time or after the view
  928. // has been resized.
  929.  
  930. void FW_CEditView::MacSetRects (Environment* ev)
  931. {
  932.     FW_CViewContext gc (ev, this, GetFrame(ev)->GetActiveFacet(ev));
  933.     FW_CPlatformRect pBounds = gc.LogicalToDevice (GetTextBounds(ev));
  934.     
  935.     (*MacTE())->viewRect = pBounds;
  936.     (*MacTE())->destRect = pBounds;    
  937.     
  938.     // extend the destination rectangle far to the right to avoid word wrapping
  939.     // [LSD] this doesn't work with center or right justification
  940.     if (HasWordWrap() == false)
  941.         (*MacTE())->destRect.right += 2000;
  942.     
  943.     // Let text-edit adjust line breaks
  944.     ::TECalText (fMacTEHandle);
  945. }
  946.  
  947. //----------------------------------------------------------------------------------------
  948. // FW_CEditView::Flatten
  949. //----------------------------------------------------------------------------------------
  950.  
  951. void FW_CEditView::Flatten(Environment* ev, FW_CWritableStream& stream) const
  952. {
  953.     FW_CView::Flatten(ev, stream);
  954.     
  955.     stream << fMaxChars;    
  956.     stream << fEditAttributes;
  957.     stream << GetFont(ev);
  958.     stream << GetText(ev);
  959. }
  960.  
  961. //----------------------------------------------------------------------------------------
  962. // FW_CEditView::InitializeFromStream
  963. //----------------------------------------------------------------------------------------
  964.  
  965. void FW_CEditView::InitializeFromStream(Environment* ev, FW_CReadableStream& stream)
  966. {
  967.     FW_CView::InitializeFromStream(ev, stream);
  968.     
  969.     FW_CString text;
  970.     FW_CFont font;
  971.  
  972.     stream >> fMaxChars;    
  973.     stream >> fEditAttributes;
  974.     stream >> font;
  975.     stream >> text;    
  976.     
  977.     Initialize(ev, text, font);
  978. }
  979.     
  980. //----------------------------------------------------------------------------------------
  981. // FW_CEditView::GetLocale
  982. //----------------------------------------------------------------------------------------
  983. void FW_CEditView::GetLocale(Environment* ev, FW_Locale& locale) const
  984. {
  985. FW_UNUSED(ev);
  986.  
  987. #ifdef FW_BUILD_MAC
  988.     short fontNumber = (*MacTE())->txFont;
  989.     locale.fScriptCode = ::FontToScript(fontNumber);    // Get the script from the font
  990.     locale.fLangCode = ::GetScriptVariable(locale.fScriptCode, smScriptLang);    // Get the language from the script
  991. #endif
  992.  
  993. #ifdef FW_BUILD_WIN
  994.     // Not yet implemented
  995.     locale.fScriptCode = 0;
  996.     locale.fLangCode = 0;
  997. #endif
  998. }
  999.