home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / Tool Chest / Development Platforms / AppsToGo / AppsToGo.src / DTS.Lib / =Using TextEditControl.c < prev    next >
Encoding:
Text File  |  1993-06-18  |  21.2 KB  |  419 lines  |  [TEXT/MPS ]

  1. ***** TextEditControl.c usage documentation *****/
  2.  
  3. Purpose:  To simplify TextEdit handling within a window.
  4.  
  5. Implementing a TextEdit control does the following:
  6.  
  7. 1) Makes using TextEdit in a non-dialog window easy.
  8. 2) The TERecord is automatically associated with the window, since
  9.    it is in the window's control list.
  10. 3) The TextEdit control can have scrollbars associated with it, and these
  11.    are also kept in the window's control list, and also associated with
  12.    the TextEdit control.
  13. 4) Updating of the TERecord is much simpler, since all that is
  14.    necessary is to draw the control (or all the window's controls with
  15.    a DrawControls call).
  16. 5) What isn't handled automatically by tracking the control can be handled
  17.    with a direct call.  There are simple calls to handle TextEdit events.
  18. 6) Undo is already supported.
  19. 7) A TERecord length can be specified.  This length will not be exceeded
  20.    when editing the TERecord.
  21. 8) When you close the window, the TERecord is disposed of.
  22.    (This automatic disposal can easily be defeated.)
  23.  
  24.  
  25. To create a TextEdit control, you only need a single call.  For example:
  26.  
  27.     mode = cteVScrollLessGrow;    /* TERecord read-write, with vertical scroll         */
  28.                                 /* that leaves space for grow box.                     */
  29.  
  30.     CTENew(rViewCtl,            /* Resource ID of view control for TextEdit control. */
  31.            window,                /* Window to hold TERecord.                             */
  32.            true,                /* Initially visible.                                 */
  33.            &teHndl,                /* Return handle for TERecord.                         */
  34.            &ctlRect,            /* Rect for TextEdit view control.                     */
  35.            &destRect,            /* destRect for TERecord                             */
  36.            &viewRect,            /* viewRect for TERecord                             */
  37.            &brdrRect,            /* Used to frame a border.                             */
  38.            32000,                /* Max size for TERecord text.                         */
  39.            mode);
  40.  
  41. The various choices for the TextEdit control are defined as follows:
  42.  
  43. #define cteReadOnly            0x0001
  44. #define cteHScroll            0x0002
  45. #define cteHScrollLessGrow    0x0006
  46. #define cteVScroll            0x0008
  47. #define cteVScrollLessGrow    0x0018
  48. #define cteActive            0x0020
  49. #define cteNoBorder            0x0040
  50. #define cteShowActive        0x0080
  51. #define cteTabSelectAll        0x0100
  52. #define cteTwoStep            0x0200
  53. #define cteScrollFullLines    0x0400
  54. #define cteStyledTE            0x0800
  55. #define cteCenterJustify    0x1000
  56. #define cteRightJustify        0x2000
  57. #define cteNoFastKeys        0x4000
  58.  
  59. cteReadOnly:        Don't allow editing.  When selected, don't blink a caret.
  60.                     Allow text selection and copy-to-clipboard.
  61. cteHScroll:            Create and manage a horizontal scrollbar for the TextEdit control.
  62. cteHScrollLessGrow:    Create and manage a horizontal scrollbar for the TextEdit control,
  63.                     but leave space for a growIcon on the right end of the scrollbar.
  64. cteVScroll:            Create and manage a vertical scrollbar for the TextEdit control.
  65. cteVScrollLessGrow:    Create and manage a vertical scrollbar for the TextEdit control,
  66.                     but leave space for a growIcon on the bottom end of the scrollbar.
  67. cteActive:            Make this the initially active control for the window.
  68. cteNoBorder:        By default, you get a border around the TextEdit control.  To turn this
  69.                     off, set this bit.
  70. cteShowActive:        When the control is active, show that it is by drawing a selection
  71.                     border around the control.  This is the new 7.0 human-interface
  72.                     method of showing which control is active.  (This can be an important
  73.                     indicator because if you have readOnly TextEdit controls, they don't
  74.                     have a blinking caret.  If they also don't have any text selected,
  75.                     there will be no indication that it is the active control.
  76. cteTabSelectAll:    When using IsCtlEvent() (discussed under "! using CtlHandler.c"),
  77.                     tab changes the active TextEdit (or List) control.  When a TextEdit
  78.                     control is made active, sometimes it is desirable to initially select
  79.                     all of the text for the user.  Setting this bit accomplishes this.
  80. cteTwoStep:            When using IsCtlEvent(), you may want the initial click on a TextEdit
  81.                     control to just select the control, or you may wish the click to start
  82.                     tracking in addition to selecting the control.  The tracking is
  83.                     considered the second step, so by setting this bit, you will get
  84.                     tracking of the control on the initial click.
  85. cteScrollFullLines:    This does as it sounds, but only if the TextEdit control isn't styled.
  86. cteStyledTE:        If you don't need styles for this TextEdit control, leave this bit off.
  87. cteCenterJustify:    As it sounds.
  88. cteRightJustify:    As it sounds.
  89. cteNoFastKeys:        The fast-keys feature allows the TextEdit control to check the OSEvent queue
  90.                     to see if there is another key event.  If there is, it will handle it
  91.                     before returning control to the application.  This local event processing
  92.                     allows a great speed increase in TextEdit performance, especially on
  93.                     slower Macs.  Some applications will want to inhibit this behavior.  Set
  94.                     this bit if you do.
  95.  
  96. Simply initialize ctlRect, destRect, viewRect, and brdrRect appropriately, and
  97. then call CTENew (which stands for Control TENew).  If teHndl is returned
  98. nil, then CTENew failed.  Otherwise, you now have a TextEdit control in the
  99. window.  If it fails, it also returns an error stating why it failed
  100. (memFullErr or resNotFound).
  101.  
  102. NOTE: There is a TextEdit bug (no way!!) such that you may need to set the
  103.       viewRect right edge 2 bigger than the right edge of destRect.  If you
  104.       do not do this, then there will be some clipping on the right edge in
  105.       some cases.  Of course, you may want this.  You may want horizontal
  106.       scrolling, and therefore you would want the destRect substantially
  107.       larger than the viewRect.  If you don't want horizontal scrolling,
  108.       then you probably don't want any clipping horizontally, and therefore
  109.       you will need to set destRect.right 2 less than viewRect.right.
  110.  
  111.  
  112. If the CTENew call succeeds, you then have a TextEdit control in your
  113. window.  It will be automatically disposed of when you close the window.
  114. If you don't waht this to happen, then you can detach it from the
  115. view control which owns it.  To do this, you would to the following:
  116.  
  117.     viewCtl = CTEViewFromTE(theTextEditHndl);
  118.     if (viewCtl) SetCRefCon(viewCtl, nil);
  119.  
  120. The view control keeps a reference to the TERecord in the refCon.
  121. If the refCon is cleared, then the view control does nothing.  So, all that
  122. is needed to detach a TERecord from a view control is to set the
  123. view control's refCon nil.  Now if you close the window, you will still
  124. have the TERecord.
  125.  
  126.  
  127. To remove a TextEdit control completely from a window, you make one call:
  128.  
  129.     CTEDispose(theTextEditHndl);
  130.  
  131. This disposes of the TERecord, the view control, and any scrollbar
  132. controls that were created when the TextEdit control was created with
  133. the call CTENew.
  134.  
  135.  
  136. Events for TERecord are handled nearly automatically.  You can
  137. make one of 3 calls:
  138.  
  139.     CTEClick(window, eventPtr, &action);
  140.     CTEEvent(window, eventPtr, &action);
  141.     CTEKey(window, eventPtr);
  142.  
  143. In each case, if the event was handled, non-zero is returned.  CTEEvent simply
  144. calls either CTEClick or CTEKey, whichever is appropriate.
  145.  
  146. Another call you will want to use is CTEEditMenu.  This is used to set the
  147. state of cut/copy/paste/clear for TextEdit controls.  It checks the active
  148. control to see if text is selected, if the control is read-only, etc.
  149. Based on this information, it sets cut/copy/paste/clear either active
  150. or inactive.  If any menu items are set active, it returns true.
  151.  
  152.  
  153. One more high-level call is CTEUndo().  In response to an undo menu item
  154. being selected by the user, just call CTEUndo(), and the edits the user
  155. has made will be undone.  (This includes undoing an undo.)
  156.  
  157.  
  158. The last high-level call for managing the edit menu is CTEClipboard.  Call it
  159. when you want to do a cut/copy/paste/clear for the active TextEdit control.
  160. The value to pass is as follows:
  161.  
  162.  2: cut
  163.  3: copy
  164.  4: paste
  165.  5: clear
  166.  
  167. These are the same values you would pass to a DA for these actions.
  168.  
  169.  
  170.  
  171. Here is a list of the functions and a description as to their purpose:
  172.  
  173. void            CTEActivate(Boolean active, TEHandle teHndl);
  174.     /* Activate this TextEdit record.  If another is currently active, deactivate
  175.     ** that one.  The view control for this TextEdit record is also flagged to
  176.     ** indicate which was the last active one for this window.  If the previous
  177.     ** active TextEdit record was in the same window, then flag the old one off
  178.     ** for this window.  The whole point for this per-window flagging is so that
  179.     ** activate events can reactivate the correct TextEdit control per window. */
  180.  
  181. Boolean            CTEClick(WindowPtr window, EventRecord *event, short *action);
  182.     /* This is called when a mouseDown occurs in the content of a window.  It
  183.     ** returns true if the mouseDown caused a TextEdit action to occur.  Events
  184.     ** that are handled include if the user clicks on a scrollbar that is
  185.     ** associated with a TextEdit control.
  186.     **
  187.     ** if CTEClick returns false, action is 0
  188.     ** if CTEClick returns true,  action is:
  189.     **      -1 if control was activated by clicking on the TextEdit control or related scrollbar.
  190.     **       0 if control that was clicked on was already active. */
  191.  
  192.  
  193. void            CTEClipboard(short menuID);
  194.     /* Do the cut/copy/paste/clear operations for the currently active
  195.     ** TextEdit control.  Caller assumes appropriateness of the call.  Typically,
  196.     ** this routine won't be called at an inappropriate time, since the menu
  197.     ** item should be enabled or disabled correctly.
  198.     ** Use CTEEditMenu to set the menu items undo/cut/copy/paste/clear correctly
  199.     ** for the active TextEdit control.  Since undo isn't currently supported,
  200.     ** all that CTEEditMenu does for the undo case is to deactivate it right now. */
  201.  
  202. void            CTEConvertClipboard(Boolean convertClipboard, Boolean becomingActive);
  203.     /* Call this for activate events to manage importing and exporting the TextEdit local scrap. */
  204.  
  205.  
  206. ControlHandle    CTECtlHit(void);
  207.     /* The TextEdit control that was hit by calling FindControl is saved in a
  208.     ** global variable, since the CDEF has no way of returning what kind it was.
  209.     ** To determine that it was a TextEdit control that was hit, first call this
  210.     ** function.  The first call returns the old value in the global variable,
  211.     ** plus it resets the global to nil.  Then call FindControl(), and then
  212.     ** call this function again.  If it returns nil, then a TextEdit control
  213.     ** wasn't hit.  If it returns non-nil, then it was a TextEdit control that
  214.     ** was hit, and specifically the one returned. */
  215.  
  216. void            CTEDispose(TEHandle teHndl);
  217.     /* Disposes of the TERecord, TextEdit control, and any related scrollbars. */
  218.  
  219. TEHandle        CTEDisposeView(ControlHandle viewCtl);
  220.     /* Dispose of the view control and related scrollbars.  This function also
  221.     ** returns the handle to the TextEdit record, since it was just orphaned.
  222.     ** Use this function if you want to get rid of a TextEdit control, but you
  223.     ** want to keep the TextEdit record. */
  224.  
  225. short            CTEDocHeight(TEHandle teHndl);
  226.     /* Returns the full document height. */
  227.  
  228. Boolean            CTEEditMenu(Boolean *activeItem, short editMenu, short undoID, short cutID);
  229.     /* Enable or disable edit menu items based on the active TextEdit control.
  230.     ** You pass the menu ID of the undo item in undoID, and the menu ID of the
  231.     ** cut item in cutID.  If undoID or cutID is non-zero, then some action is
  232.     ** performed.  If you pass a non-zero value for cutID, then the other menu
  233.     ** items cut/copy/paste/clear are updated to reflect the status of the
  234.     ** active TextEdit control. */
  235.  
  236. Boolean            CTEEvent(WindowPtr window, EventRecord *event, short *action);
  237.     /* Handle the event if it applies to the active TextEdit control.  If some
  238.     ** action occured due to the event, return true.
  239.     **
  240.     ** if event not handled, false is returned and action is 0
  241.     ** if event handled, true is returned and action is:
  242.     **      -1: an inactive control was clicked on and it was made active.
  243.     **       0: an active control was clicked on and tracked.
  244.     **       1: the control took the keypress, but no change occured to the TERecord.
  245.     **       2: the control took the keypress and the TERecord changed. */
  246.  
  247. TEHandle        CTEFindActive(WindowPtr window);
  248.     /* Returns the active TextEdit control, if any.  If nil is passed in, then
  249.     ** the return value represents whatever TextEdit control is active, independent
  250.     ** of what window it is in.  If a window is passed in, then it returns a
  251.     ** TextEdit control only if the active control is in the specified window.
  252.     ** If the active TextEdit control is in some other window, then nil is returned. */
  253.  
  254. Boolean            CTEFindCtl(WindowPtr window, EventRecord *event, TEHandle *teHndl, ControlHandle *ctlHit);
  255.     /* This determines if a TextEdit control was clicked on directly.  This does
  256.     ** not determine if a related scrollbar was clicked on.  If a TextEdit
  257.     ** control was clicked on, then true is returned, as well as the TextEdit
  258.     ** handle and the handle to the view control. */
  259.  
  260. TEHandle        CTEFromScroll(ControlHandle scrollCtl, ControlHandle *retCtl);
  261.     /* Find the TextEdit record that is related to the indicated scrollbar. */
  262.  
  263. void            CTEHide(TEHandle teHndl);
  264.     /* Hide the designated TextEdit control and related scrollbars. */
  265.  
  266. void            CTEIdle(void);
  267.     /* Blink the caret in the active TextEdit control.  The active TextEdit
  268.     ** control may be read-only, in which case the caret does not blink. */
  269.  
  270. short            CTEKey(WindowPtr window, EventRecord *event);
  271.     /* See if the keypress event applies to the TextEdit control, and if it does,
  272.     ** handle it and return non-zero.
  273.     **
  274.     ** if CTEKey returns 0, TextEdit control didn't handle the event.
  275.     ** if CTEKey returns 1, TextEdit control did handle the event, but the TERecord didn't change.
  276.     ** if CTEKey returns 2, TextEdit control did handle the event, and the TERecord changed.
  277.  
  278. void            CTEMove(TEHandle teHndl, short newH, short newV);
  279.     /* This function is used to move a TextEdit control.  Pass it the TextEdit
  280.     ** record to move, plus the new position.  It will move the TextEdit control,
  281.     ** along with any scrollbars the control may have.  All areas that need
  282.     ** updating are cleared and invalidated. */
  283.  
  284. OSErr            CTENew(short viewID, Boolean vis, WindowPtr window, TEHandle *teHndl, Rect *cRect,
  285.                        Rect *dRect, Rect *vRect, Rect *bRect, short maxTextLen, short mode);
  286.     /* Create a new TextEdit control.  See the comments at the beginning of this
  287.     ** file for more information. */
  288.  
  289. void            CTENewUndo(ControlHandle viewCtl, Boolean alwaysNewUndo);
  290.     /* Save the data (if appropriate) so that user can undo. */
  291.  
  292. ControlHandle    CTENext(WindowPtr window, TEHandle *teHndl, ControlHandle ctl, short dir, Boolean justActive);
  293.     /* Get the next TextEdit control in the window.  You pass it a control handle
  294.     ** for the view control, or nil to start at the beginning of the window.
  295.     ** It returns both a TextEdit handle and the view control handle for that
  296.     ** TextEdit record.  If none is found, nil is returned.  This allows you to
  297.     ** repeatedly call this function and walk through all the TextEdit controls
  298.     ** in a window. */
  299.  
  300. short            CTENumTextLines(TEHandle teHndl);
  301.     /* Return the number of lines of text.  This is because there is a bug in
  302.     ** TextEdit where the number of lines returned is incorrect if the text
  303.     ** ends with a c/r.  This function adjusts for this bug. */
  304.  
  305. OSErr            CTEPrint(TEHandle teHndl, short *offset, Rect *rct);
  306.     /* Use this function to print the contents of a TextEdit record.  Pass it a
  307.     ** TextEdit handle, a pointer to a text offset, and a pointer to a rect to
  308.     ** print the text in.  The offset should be initialized to what character
  309.     ** in the TextEdit record you wish to start printing at (most likely 0).
  310.     ** The print function prints as much text as will fit in the rect, and
  311.     ** then updates the offset to tell you what is the first character that didn't
  312.     ** print.  You can then call the print function again with another rect with
  313.     ** this new offset, and it will print the text starting at the new offset.
  314.     ** This method is very useful when a single TextEdit record is longer than a
  315.     ** single page, and you wish the text to break at the end of the page.
  316.     ** The bottom of rect is also updated, along with the offset.  The bottom edge
  317.     ** of the rect is changed to reflect the actual bottom of the text printed.
  318.     ** This is useful because the rect passed in didn't necessarily hold an
  319.     ** integer number of lines of text.  The bottom of the rect is adjusted so
  320.     ** it exactly holds complete lines of text.
  321.     ** It is also possible that the rect could hold substantially more lines of
  322.     ** text than there are remaining.  Again, in this situation, the bottom of
  323.     ** rect is adjusted so that the rect tightly bounds the text printed.
  324.     ** The remaining piece of information passed back is an indicator that the
  325.     ** text through the end of the TextEdit record was printed.  When the end
  326.     ** of the text is reached, the offset for the next text to be printed is
  327.     ** returned as -1.  This indicates that processing of the TextEdit record
  328.     ** is complete. */
  329.  
  330. Boolean            CTEReadOnly(TEHandle teHndl);
  331.     /* Return if the TextEdit control is read/write (true) or read-only (false). */
  332.  
  333. ControlHandle    CTEScrollFromTE(TEHandle teHndl, Boolean vertScroll);
  334.     /* Return the control handle for the TextEdit control's scrollbar, either
  335.     ** vertical or horizontal.  If the scrollbar doesn't, nil is returned. */
  336.  
  337. ControlHandle    CTEScrollFromView(ControlHandle viewCtl, Boolean vertScroll);
  338.     /* Return the control handle for the scrollbar related to the view control,
  339.     ** either horizontal or vertical.  If the scrollbar doesn't exist, return nil. */
  340.  
  341. void            CTESetKeyFilter(TEHandle teHndl, CTEKeyFilterProcPtr proc);
  342.     /* A TextEdit control can have an optional key filter, which is called whenever
  343.     ** CTEKey() is called.  If you pass in nil, then the filtering is turned off.
  344.     ** This allows individual TextEdit controls to handle their own filtering.
  345.     ** The filter procedure is of the form:
  346.     **     Boolean (*CTEKeyFilterProcPtr)(TEHandle teHndl, EventRecord *event, Boolean *handled);
  347.     ** If true is returned, then CTEKey() is aborted, and the value in "handled" is
  348.     ** returned.  By having a separate abort value and return value, you can determine
  349.     ** if processing of the event should be continued or not, independent of whether
  350.     ** or not you aborted CTEKey(). */
  351.  
  352. void            CTESetFastKeys(TEHandle teHndl, CTEFastKeysProcPtr proc);
  353.     /* Set your own fast-keys procedure.  The fast-keys procedure returns whether or not
  354.     ** the particular keypress can be handled without returning to the application. */
  355.  
  356. void            CTESetSelect(short start, short end, TEHandle teHndl);
  357.     /* Select a range of text.  TESetSelect can't be used alone because it doesn't
  358.     ** update the scrollbars.  This function calls TESetSelect, and then fixes up
  359.     ** the scrollbars. */
  360.  
  361. void            CTEShow(TEHandle teHndl);
  362.     /* Show the designated TextEdit control and related scrollbars. */
  363.  
  364. void            CTESize(TEHandle teHndl, short dx, short dy, Boolean newDest);
  365.     /* This function is used to resize a TextEdit control.  Pass it the TextEdit
  366.     ** record to resize, plus the new horizontal and vertical size.  It will
  367.     ** resize the TextEdit control, realign the text, if necessary, plus it will
  368.     ** resize and adjust any scrollbars the TextEdit control may have.  All areas
  369.     ** that need updating are cleared and invalidated. */
  370.  
  371. Handle            CTESwapText(TEHandle teHndl, Handle newText, StScrpHandle styl, Boolean update);
  372.     /* Swap the TextEdit text handle with the text handle passed in.  If a non-nil styl
  373.     ** value is passed in, apply the style scrap to the new text. */
  374.  
  375. WindowPtr        CTETargetInfo(TEHandle *teHndl, Rect *teView);
  376.     /* Return information for the currently active TextEdit control.  The currently
  377.     ** active TextEdit control is stored in gActiveTEHndl, and can be accessed
  378.     ** directly.  If gActiveTEHndl is nil, then there is no currently active one.
  379.     ** The information that we return is the viewRect and window of the active
  380.     ** TextEdit control.  This is information that could be gotten directly, but
  381.     ** this call makes it a little more convenient. */
  382.  
  383. void            CTEUndo(void);
  384.     /* Perform an undo function for the TextEdit control. */
  385.  
  386. void            CTEUpdate(TEHandle teHndl, ControlHandle ctl, Boolean justShowActive);
  387.     /* Draw the TextEdit control and frame. */
  388.  
  389. ControlHandle    CTEViewFromTE(TEHandle teHndl);
  390.     /* Return the control handle for the view control that owns the TextEdit
  391.     ** record.  Use this to find the view to do customizations such as changing
  392.     ** the update procedure for this TextEdit control. */
  393.  
  394. TEHandle        CTEWindActivate(WindowPtr window, Boolean displayIt);
  395.     /* Call this when a window with TextEdit controls is being activated.  This
  396.     ** will make the TextEdit control that was last active in this window the
  397.     ** active TextEdit control again.  If it can't find one that was the last
  398.     ** active control, it makes the first one it finds the active control. */
  399.  
  400. void            CTEAdjustTEBottom(TEHandle teHndl);
  401.     /* This function is called after an edit to make sure that there is no extra
  402.     ** white space at the bottom of the viewRect.  If there are blank lines at
  403.     ** the bottom of the viewRect, and there is text scrolled off the top of the
  404.     ** viewRect, then the TextEdit control is scrolled to fill this space, or as
  405.     ** much of it as possible. */
  406.  
  407. void            CTEAdjustScrollValues(TEHandle teHndl);
  408.     /* Bring the scrollbar values up to date with the current document position
  409.     ** and length. */
  410.  
  411. StScrpHandle    CTEGetFullStylScrap(TEHandle teHndl);
  412.     /* This function gets the style scrap for the entire TextEdit control.  It doesn't
  413.     ** matter what the current selection range is.  The TextEdit control is left unaffected. */
  414.  
  415. void            CTESetStylScrap(short begRng, short endRng, StScrpHandle styles, TEHandle teHndl);
  416.     /* This function applies the style scrap to the TextEdit record.  This function works better
  417.     ** than the toolbox function TESetStylScrap(). */
  418.  
  419.