home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / edctl1.zip / entryfld.c < prev    next >
C/C++ Source or Header  |  1994-07-05  |  144KB  |  4,019 lines

  1. #pragma    title("Entry Field Replacement  --  Version 1.0 -- (EntryFld.C)")
  2. #pragma    subtitle("   Entry Field Control - Interface Definitions")
  3.  
  4. /* Program name: Listbox.C    Title: A Entry Field Replacement        */
  5. /*                                    */
  6. /* OS/2    Developer Magazine, Issue:  July '94 GUI Corner                 */
  7. /* Author:  Mark Benge       IBM Corp.                    */
  8. /*        Matt Smith       Prominare Inc.                */
  9. /* Description:     Replacement for OS/2 List Box,    third of a series.    */
  10. /*                                    */
  11. /* Program Requirements:  OS/2 2.x                    */
  12. /*              IBM C    Set/2                    */
  13. /*              WATCOM C 386/9.0                */
  14. /*              Borland C++ for OS/2                */
  15. /*              OS/2 Toolkit                    */
  16.  
  17. /* Copyright ╕ International Business Machines Corp. 1991-1994        */
  18. /* Copyright ╕ 1989-1994  Prominare Inc.  All Rights Reserved.        */
  19.  
  20.  
  21. /************************************************************************/
  22. /************************************************************************/
  23. /*                 SPECIAL NOTE                */
  24. /************************************************************************/
  25. /************************************************************************/
  26. /*     The behaviour of    this control is    similar    to that    provided    */
  27. /*     by OS/2 PM.  Although it    may be based on    documentation        */
  28. /*     describing programming interfaces and techniques, it should    */
  29. /*     not be misconstrued that    this sample code is an official        */
  30. /*     release of the OS/2 PM control and is supported as such.        */
  31. /************************************************************************/
  32. /************************************************************************/
  33.  
  34. /************************************************************************/
  35. /************************************************************************/
  36. /*               DISCLAIMER OF WARRANTIES.            */
  37. /************************************************************************/
  38. /************************************************************************/
  39. /*     The following [enclosed]    code is    source code created by the    */
  40. /*     authors.     This source code is  provided to you solely        */
  41. /*     for the purpose of assisting you    in the development of your    */
  42. /*     applications.  The code is provided "AS IS", without        */
  43. /*     warranty    of any kind.  The authors shall    not be liable        */
  44. /*     for any damages arising out of your use of the source code,    */
  45. /*     even if they have been advised of the possibility of such    */
  46. /*     damages.     It is provided    purely for instructional and        */
  47. /*     illustrative purposes.                        */
  48. /************************************************************************/
  49. /************************************************************************/
  50.  
  51. #pragma    info(noext)
  52. #pragma    strings(readonly)
  53.  
  54. #define    INCL_DOS           /* Include OS/2 DOS Kernal        */
  55. #define    INCL_GPI           /* Include OS/2 PM GPI Interface    */
  56. #define    INCL_WIN           /* Include OS/2 PM Windows Interface    */
  57.  
  58. #include <os2.h>
  59. #include <setjmp.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62.  
  63. #include "entryfld.h"
  64.  
  65. /* This    module contains    the common routines used by the    Entry Field    */
  66. /* along with the window procedure for the Entry Field.            */
  67. /*                                    */
  68. /* Equivalent command line invocation of each module using the        */
  69. /* IBM C Set++ Compiler    Version    2.0 is:                    */
  70. /*                                    */
  71. /*     Icc -G3e- -O+ -Rn -C -W3    -FoEntryfld Entryfld.C            */
  72.  
  73. /* Filename:   Entryfld.C                        */
  74.  
  75. /*  Version:   1.0                            */
  76. /*  Created:   1994-03-03                        */
  77. /*  Revised:   1994-07-03                        */
  78.  
  79. /* Routines:   static LONG lGetPresParam(HWND hWnd, ULONG ulID1,    */
  80. /*                     ULONG ulID2, LONG lDefault);    */
  81. /*           static VOID SizeEntryField(PENTRYFWIN pefw);        */
  82. /*           static VOID QueryCharPoints(PENTRYFWIN pefw);        */
  83. /*           static LONG lFindCharacterIndex(PENTRYFWIN pefw,        */
  84. /*                           LONG xClick);        */
  85. /*           static LONG lCalcDisplayPoint(PENTRYFWIN    pefw,        */
  86. /*                         LONG iChar);        */
  87. /*           static BOOL fScrollRight(PENTRYFWIN pefw);        */
  88. /*           static VOID ShowCursor(PENTRYFWIN pefw, LONG iSel);    */
  89. /*           static VOID DrawOvertype(PENTRYFWIN pefw);        */
  90. /*           static VOID DrawTextString(PENTRYFWIN pefw, LONG    iStart,    */
  91. /*                      LONG iEnd, BOOL fHighlighted);*/
  92. /*           static VOID DrawText(PENTRYFWIN pefw);            */
  93. /*           static VOID DrawSubText(PENTRYFWIN pefw,    LONG iStart,    */
  94. /*                       LONG iEnd);            */
  95. /*           static VOID DrawOvertypeText(PENTRYFWIN pefw,        */
  96. /*                        BOOL fMoveRight);        */
  97. /*           static VOID SelectText(PENTRYFWIN pefw, LONG iAnchor,    */
  98. /*                      LONG iSelected);            */
  99. /*           static VOID RefreshMetrics(PENTRYFWIN pefw);        */
  100. /*           static VOID DecodeCtlData(PENTRYFWIN pefw, MPARAM mp1);    */
  101. /*           MRESULT EXPENTRY    mrBaseFieldHandler(HWND    hWnd, ULONG msg,*/
  102. /*                           MPARAM mp1,        */
  103. /*                           MPARAM mp2);        */
  104. /*           APIRET APIENTRY EntryFieldExceptionHandler(        */
  105. /*                   PEXCEPTIONREPORTRECORD pxcptrepr,    */
  106. /*                   PEXCEPTIONREGISTRATIONRECORD pxcptregr,    */
  107. /*                   PCONTEXTRECORD pcr, PVOID sysinfo);    */
  108. /*           static VOID DeleteText(PENTRYFWIN pefw, LONG iSelStart,    */
  109. /*                      LONG iSelEnd, BOOL fRedraw);    */
  110. /*           static PSZ pszCopyText(PENTRYFWIN pefw, PSZ pszBuffer,    */
  111. /*                      LONG iSelStart, LONG iSelEnd);    */
  112. /*           static VOID PasteText(PENTRYFWIN    pefw, PSZ pszInsText,    */
  113. /*                     LONG cLen);            */
  114. /*           BOOL EXPENTRY fRegisterEntryField(HAB hAB);        */
  115. /*           MRESULT EXPENTRY    EntryWndProc(HWND hWnd,    ULONG msg,    */
  116. /*                         MPARAM mp1, MPARAM    mp2);    */
  117.  
  118.  
  119. /* --------------------------------------------------------------------    */
  120.  
  121. /************************************************************************/
  122. /*                                    */
  123. /* Standard Entry Field    Styles                        */
  124. /*                                    */
  125. /*     ES_LEFT              0x00000000L                */
  126. /*     ES_CENTER          0x00000001L                */
  127. /*     ES_RIGHT              0x00000002L                */
  128. /*     ES_AUTOSCROLL          0x00000004L                */
  129. /*     ES_MARGIN          0x00000008L                */
  130. /*     ES_AUTOTAB          0x00000010L                */
  131. /*     ES_READONLY          0x00000020L                */
  132. /*     ES_COMMAND          0x00000040L                */
  133. /*     ES_UNREADABLE          0x00000080L                */
  134. /*     ES_AUTOSIZE          0x00000200L                */
  135. /*     ES_ANY              0x00000000L                */
  136. /*     ES_SBCS              0x00001000L                */
  137. /*     ES_DBCS              0x00002000L                */
  138. /*     ES_MIXED              0x00003000L                */
  139. /*                                    */
  140. /* Standard Entry Field    notification messages                */
  141. /*                                    */
  142. /*     EN_SETFOCUS          0x0001                */
  143. /*     EN_KILLFOCUS          0x0002                */
  144. /*     EN_CHANGE          0x0004                */
  145. /*     EN_SCROLL          0x0008                */
  146. /*     EN_MEMERROR          0x0010                */
  147. /*     EN_OVERFLOW          0x0020                */
  148. /*     EN_INSERTMODETOGGLE      0x0040                */
  149. /*                                    */
  150. /* Standard Entry Field    messages                    */
  151. /*                                    */
  152. /*     EM_QUERYCHANGED          0x0140                */
  153. /*     EM_QUERYSEL          0x0141                */
  154. /*     EM_SETSEL          0x0142                */
  155. /*     EM_SETTEXTLIMIT          0x0143                */
  156. /*     EM_CUT              0x0144                */
  157. /*     EM_COPY              0x0145                */
  158. /*     EM_CLEAR              0x0146                */
  159. /*     EM_PASTE              0x0147                */
  160. /*     EM_QUERYFIRSTCHAR      0x0148                */
  161. /*     EM_SETFIRSTCHAR          0x0149                */
  162. /*     EM_QUERYREADONLY          0x014a                */
  163. /*     EM_SETREADONLY          0x014b                */
  164. /*     EM_SETINSERTMODE          0x014c                */
  165.  
  166. jmp_buf    jBuf;               /* Jump Buffer            */
  167.  
  168. /************************************************************************/
  169. /*                                    */
  170. /* Module Prototype Definitions                        */
  171. /*                                    */
  172. /************************************************************************/
  173.  
  174. static LONG lGetPresParam(HWND hWnd, ULONG ulID1, ULONG    ulID2, LONG lDefault);
  175. static VOID SizeEntryField(PENTRYFWIN pefw);
  176. static VOID QueryCharPoints(PENTRYFWIN pefw);
  177. static LONG lFindCharacterIndex(PENTRYFWIN pefw, LONG xClick);
  178. static LONG lCalcDisplayPoint(PENTRYFWIN pefw, LONG iChar);
  179. static BOOL fScrollRight(PENTRYFWIN pefw);
  180. static VOID ShowCursor(PENTRYFWIN pefw,    LONG iSel);
  181. static VOID DrawOvertype(PENTRYFWIN pefw);
  182. static VOID DrawTextString(PENTRYFWIN pefw, LONG iStart, LONG iEnd, BOOL fHighlighted);
  183. static VOID DrawText(PENTRYFWIN    pefw);
  184. static VOID DrawSubText(PENTRYFWIN pefw, LONG iStart, LONG iEnd);
  185. static VOID DrawOvertypeText(PENTRYFWIN    pefw, BOOL fMoveRight);
  186. static VOID SelectText(PENTRYFWIN pefw,    LONG iAnchor, LONG iSelected);
  187. static VOID RefreshMetrics(PENTRYFWIN pefw);
  188. static VOID DecodeCtlData(PENTRYFWIN pefw, MPARAM mp1);
  189. MRESULT    EXPENTRY mrBaseFieldHandler(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  190. APIRET    APIENTRY EntryFieldExceptionHandler(PEXCEPTIONREPORTRECORD pxcptrepr,
  191.                         PEXCEPTIONREGISTRATIONRECORD pxcptregr,
  192.                         PCONTEXTRECORD pcr,    PVOID sysinfo);
  193. static VOID DeleteText(PENTRYFWIN pefw,    LONG iSelStart,    LONG iSelEnd, BOOL fRedraw);
  194. static PSZ  pszCopyText(PENTRYFWIN pefw, PSZ pszBuffer,    LONG iSelStart,    LONG iSelEnd);
  195. static VOID PasteText(PENTRYFWIN pefw, PSZ pszBuffer, LONG cLen);
  196.  
  197. /************************************************************************/
  198. /************************************************************************/
  199. /*                                    */
  200. /* Module Private Functions                        */
  201. /*                                    */
  202. /************************************************************************/
  203. /************************************************************************/
  204.  
  205. #pragma    subtitle("   Entry Field Control - Presentation Parameter Retrieve Procedure")
  206. #pragma    page( )
  207.  
  208. /* --- lGetPresParam ----------------------------------    [ Private } ---    */
  209. /*                                    */
  210. /*     This function is    used to    retrieve a presentation    parameter    */
  211. /*     that may    be present.  If    the presentation parameter is not,    */
  212. /*     the default colour passed to the    function will be used.    All    */
  213. /*     colours queried for are RGB or their RGB    equivalents.        */
  214. /*                                    */
  215. /*     Upon Entry:                            */
  216. /*                                    */
  217. /*     HWND  hWnd;     = Window    Handle                    */
  218. /*     ULONG ulID1;    = Presentation Parameter    1 ID (RGB)        */
  219. /*     ULONG ulID2;    = Presentation Parameter    2 ID (Index)        */
  220. /*     LONG  lDefault; = Default Colour                    */
  221. /*                                    */
  222. /*     Upon Exit:                            */
  223. /*                                    */
  224. /*     lGetPresParam = Colour to Use (RGB)                */
  225. /*                                    */
  226. /* --------------------------------------------------------------------    */
  227.  
  228. static LONG lGetPresParam(HWND hWnd, ULONG ulID1, ULONG    ulID2, LONG lDefault)
  229.  
  230. {
  231. HPS   hPS;               /* Presentation Space Handle        */
  232. LONG  lClr;               /* Presentation Parameter Colour    */
  233. ULONG ulID;               /* Presentation Parameter ID        */
  234.  
  235.                /* First    try to determine if any    presentation    */
  236.                /* parameters are set for the area requested.    */
  237.                /* The first ID is RGB index and    the second ID    */
  238.                /* is colour index.                */
  239.  
  240. if ( WinQueryPresParam(hWnd, ulID1, ulID2, &ulID, sizeof(LONG),    (PVOID)&lClr,
  241.                QPF_NOINHERIT | QPF_ID2COLORINDEX | QPF_PURERGBCOLOR) )
  242.  
  243.                /* Presentation parameter set for the area,    */
  244.                /* return the RGB colour                */
  245.    return(lClr);
  246. else
  247.                /* No presentation parameters set, check    to see    */
  248.                /* if the default is a system colour in which    */
  249.                /* only need to query the index for the RGB    */
  250.                /* value                        */
  251.  
  252.    if (    (lDefault >= SYSCLR_SHADOWHILITEBGND) &&
  253.     (lDefault <= SYSCLR_HELPHILITE)    )
  254.        return(WinQuerySysColor(HWND_DESKTOP, lDefault, 0L));
  255.    else
  256.                /* Standard colour index, get the RGB equivalent    */
  257.                /* for the index                    */
  258.  
  259.        if ( (hPS = WinGetPS(hWnd)) != (HPS)NULL    )
  260.        if (    (lClr =    GpiQueryRGBColor(hPS, LCOLOPT_REALIZED,    lDefault)) == GPI_ALTERROR )
  261.            {
  262.                /* Colour was not found,    return white as    colour    */
  263.  
  264.            WinReleasePS(hPS);
  265.            return(RGB_WHITE);
  266.            }
  267.        else
  268.            {
  269.                /* Colour found,    return the RGB value        */
  270.  
  271.            WinReleasePS(hPS);
  272.            return(lClr);
  273.            }
  274.        else
  275.        return(RGB_WHITE);
  276. }
  277. #pragma    subtitle("   Entry Field Control - Entry Field Sizing Procedure")
  278. #pragma    page( )
  279.  
  280. /* --- SizeEntryField ---------------------------------    [ Private } ---    */
  281. /*                                    */
  282. /*     This function is    used to    calculate the display points and    */
  283. /*     rectangles for the entry    field when it has changed in size.    */
  284. /*                                    */
  285. /*     Upon Entry:                            */
  286. /*                                    */
  287. /*     PENTRYFWIN pefw;    = Entry    Field Data Pointer            */
  288. /*                                    */
  289. /*     Upon Exit:                            */
  290. /*                                    */
  291. /*     Nothing                                */
  292. /*                                    */
  293. /* --------------------------------------------------------------------    */
  294.  
  295. static VOID SizeEntryField(PENTRYFWIN pefw)
  296.  
  297. {
  298.                /* Form the bounding rectangle for the control    */
  299.  
  300. pefw->rcl.xLeft    = pefw->rcl.yBottom = 0L;
  301. pefw->rcl.xRight = --pefw->cx;
  302. pefw->rcl.yTop     = --pefw->cy;
  303.  
  304.                /* Save this rectangle within the bounding    */
  305.                /* rectangle of the text.  Also,    adjust the text    */
  306.                /* boundaries to    allow for a little "white"    */
  307.                /* space    at the margins.                */
  308.  
  309. pefw->rclText =    pefw->rcl;
  310.  
  311. pefw->rclText.xLeft   += EFMARGIN_LEFT;
  312. pefw->rclText.xRight  -= EFMARGIN_RIGHT;
  313. pefw->rclText.yBottom += EFMARGIN_BOTTOM;
  314. pefw->rclText.yTop    -= EFMARGIN_TOP;
  315.  
  316. pefw->rclDraw =    pefw->rclText;
  317.  
  318.                /* Calculate the    scrolling shift    count in    */
  319.                /* characters.  The formula used    here is    to take    */
  320.                /* the width of the control and find its    1/3    */
  321.                /* point.  Using    this 1/3 width,    now calculate    */
  322.                /* the average number of    characters that    would    */
  323.                /* fit in the space.                */
  324.  
  325. pefw->cScroll =    (pefw->xScrollLimit = pefw->rcl.xRight / 3L) / pefw->cxChar;
  326.  
  327.                /* Set the baseline for the text    as being the    */
  328.                /* descender size plus the "white"space margin    */
  329.  
  330. pefw->ptlDraw.y    = pefw->yBaseline = EFMARGIN_BOTTOM + pefw->yDesc;
  331.  
  332.                /* Calculate the    border margin outside points    */
  333.                /* which    is the dark rectangle            */
  334.  
  335. pefw->aptlOutside[0].x = 0L;
  336. pefw->aptlOutside[0].y = 1L;
  337. pefw->aptlOutside[1].x = 0L;
  338. pefw->aptlOutside[1].y = pefw->cy;
  339. pefw->aptlOutside[2].x = pefw->cx - 1L;
  340. pefw->aptlOutside[2].y = pefw->cy;
  341. pefw->aptlOutside[3].x = pefw->cx - 1L;
  342. pefw->aptlOutside[3].y = 1L;
  343. pefw->aptlOutside[4].x = 0L;
  344. pefw->aptlOutside[4].y = 1L;
  345.  
  346.                /* Calculate the    border margin inside points    */
  347.                /* which    is the light rectangle            */
  348.  
  349. pefw->aptlInside[0].x =    1L;
  350. pefw->aptlInside[0].y =    0L;
  351. pefw->aptlInside[1].x =    1L;
  352. pefw->aptlInside[1].y =    pefw->cy - 1L;
  353. pefw->aptlInside[2].x =    pefw->cx;
  354. pefw->aptlInside[2].y =    pefw->cy - 1L;
  355. pefw->aptlInside[3].x =    pefw->cx;
  356. pefw->aptlInside[3].y =    0L;
  357. pefw->aptlInside[4].x =    1L;
  358. pefw->aptlInside[4].y =    0L;
  359.  
  360. }
  361. #pragma    subtitle("   Entry Field Control - Text Character Position Procedure")
  362. #pragma    page( )
  363.  
  364. /* --- QueryCharPoints --------------------------------    [ Private } ---    */
  365. /*                                    */
  366. /*     This function is    used to    build the point    array which contains    */
  367. /*     the starting position of    each character in the text of the    */
  368. /*     entry field.  This function should only be called when the    */
  369. /*     text within the control has changed.                */
  370. /*                                    */
  371. /*     Upon Entry:                            */
  372. /*                                    */
  373. /*     PENTRYFWIN pefw;    = Entry    Field Data Pointer            */
  374. /*                                    */
  375. /*     Upon Exit:                            */
  376. /*                                    */
  377. /*     Nothing                                */
  378. /*                                    */
  379. /* --------------------------------------------------------------------    */
  380.  
  381. static VOID QueryCharPoints(PENTRYFWIN pefw)
  382.  
  383. {
  384. POINTL    rgptl[TXTBOX_COUNT];       /* Text Box Point Array        */
  385.  
  386.                /* Check    to see if a previous array defined and    */
  387.                /* if the case, release the array while clearing    */
  388.                /* the pointer to make sure that    an empty entry    */
  389.                /* field    is handled properly            */
  390. if ( pefw->aptl    )
  391.    {
  392.    HeapFree(pefw->hHeap, pefw->aptl);
  393.    pefw->aptl =    (PPOINTL)NULL;
  394.    }
  395.                /* Check    to see if any text contained within the    */
  396.                /* entry    field and if the case, begin the    */
  397.                /* process of building the point    array        */
  398. if ( pefw->cText )
  399.    {
  400.                /* When the entry field is defined as being    */
  401.                /* unreadable, the base text holder will    contain    */
  402.                /* asterisks (*)    instead    of the actual text.    */
  403.                /* This is done to prevent the input from being    */
  404.                /* displayed.  A    second input buffer is used to    */
  405.                /* hold the actual text and the standard    text    */
  406.                /* buffer is filled with    asterisks.        */
  407.  
  408.    if (    pefw->flStyle &    ES_UNREADABLE )
  409.        {
  410.        memcpy(pefw->szPassword,    pefw->szText, (UINT)pefw->cText);
  411.        memset(pefw->szText, '*', (UINT)pefw->cText);
  412.        pefw->szText[pefw->cText] = 0;
  413.        }
  414.                /* Allocate the point holders for the text and    */
  415.                /* query    the points.  Make sure that there is    */
  416.                /* one additional point holder for the right    */
  417.                /* edge of the last character.            */
  418.  
  419.    GpiQueryCharStringPos(pefw->hPS, 0UL, pefw->cText, pefw->szText, (PLONG)NULL,
  420.              pefw->aptl = (PPOINTL)HeapMalloc(pefw->hHeap,
  421.                               (ULONG)(sizeof(POINTL) * (pefw->cText    + 1))));
  422.  
  423.                /* Determine the    actual text box    bounding    */
  424.                /* rectangle                    */
  425.  
  426.    GpiQueryTextBox(pefw->hPS, pefw->cText, pefw->szText, 5L, rgptl);
  427.  
  428.                /* Save the right edge of the last character    */
  429.                /* in the last point holder.  This will allow    */
  430.                /* to a fast lookup of mouse clicks since all    */
  431.                /* characters edges are horizontally defined.    */
  432.  
  433.    pefw->aptl[pefw->cText].x = rgptl[TXTBOX_CONCAT].x -    rgptl[TXTBOX_BOTTOMLEFT].x;
  434.    }
  435. else
  436.    pefw->iOffset = 0L;
  437.                /* Set the change flag to reflect the new text    */
  438.                /* entered                    */
  439. pefw->fChanged = TRUE;
  440.  
  441. }
  442. #pragma    subtitle("   Entry Field Control - Text Character Position Procedure")
  443. #pragma    page( )
  444.  
  445. /* --- lFindCharacterIndex ----------------------------    [ Private } ---    */
  446. /*                                    */
  447. /*     This function is    used to    determine where    the mouse pointer    */
  448. /*     has clicked in terms of the characters that compose the text    */
  449. /*     of the entry field.  The    method used is a binary    search on    */
  450. /*     the character point array that has been cached internally with    */
  451. /*     the private control data.  Further selection is performed for    */
  452. /*     the selection point depending on    whether    the point is in    the    */
  453. /*     front half of the character box or the later half.  When    the    */
  454. /*     point is    in the front half, the character index for the        */
  455. /*     found character box is used otherwise if    it is in the later    */
  456. /*     half, the next character    is used.                */
  457. /*                                    */
  458. /*     Upon Entry:                            */
  459. /*                                    */
  460. /*     PENTRYFWIN pefw;      = Entry Field    Data Pointer            */
  461. /*     LONG      xClick; = Horizontal Mouse Click Point        */
  462. /*                                    */
  463. /*     Upon Exit:                            */
  464. /*                                    */
  465. /*     lFindCharacterIndex = Character Index                */
  466. /*                                    */
  467. /* --------------------------------------------------------------------    */
  468.  
  469. static LONG lFindCharacterIndex(PENTRYFWIN pefw, LONG xClick)
  470.  
  471. {
  472. LONG iHigh;               /* High Index            */
  473. LONG iLow;               /* Low Index                */
  474. register LONG i;           /* Index Positions            */
  475.  
  476.                /* Check    to see if the mouse click is past the    */
  477.                /* right-most character in the entry field text    */
  478.                /* in which case    indicate the text position as    */
  479.                /* being    just after the last character        */
  480.  
  481. if ( (xClick +=    (pefw->aptl[pefw->iOffset].x - EFMARGIN_LEFT)) >= pefw->aptl[pefw->cText].x )
  482.    return(pefw->cText);
  483. else
  484.                /* Check    to make    sure that the relative position    */
  485.                /* does not extend to the left of the left    */
  486.                /* margin                    */
  487.    if (    xClick > 0L )
  488.        {
  489.                /* Have determined that the mouse click is    */
  490.                /* with the current text    limit.    Initialize the    */
  491.                /* the high and low points for the binary search    */
  492.                /* as being the shift offset as the low starting    */
  493.                /* boundary and the length of the text as the    */
  494.                /* high ending boundary.                */
  495.  
  496.        iLow  = i = pefw->iOffset;
  497.        iHigh = pefw->cText - 1L;
  498.  
  499.                /* Loop through the point array to see which    */
  500.                /* cell falls under the mouse click        */
  501.  
  502.        while( iLow <= iHigh )
  503.        if (    xClick < pefw->aptl[i =    (iLow +    iHigh) / 2L].x )
  504.            iHigh = i - 1L;
  505.        else
  506.            if ( xClick >= pefw->aptl[i + 1L].x )
  507.            iLow    = i + 1L;
  508.            else
  509.                /* Have found the cell where the    mouse was    */
  510.                /* clicked over.     Now have to further refine the    */
  511.                /* selection.  When the mouse has been clicked    */
  512.                /* in the left half of the cell,    that cell is    */
  513.                /* deemed as being the character    cell selected.    */
  514.                /* When the mouse has been clicked in the right    */
  515.                /* half of the cell, the    next character is    */
  516.                /* deemed as being selected.            */
  517.  
  518.            if (    xClick > ((pefw->aptl[i    + 1L].x    - pefw->aptl[i].x) / 2L) + pefw->aptl[i].x)
  519.                return(i    + 1L);
  520.            else
  521.                return(i);
  522.  
  523.        return(i);
  524.        }
  525.  
  526. return(0L);
  527. }
  528. #pragma    subtitle("   Entry Field Control - Text Character Position Procedure")
  529. #pragma    page( )
  530.  
  531. /* --- lCalcDisplayPoint ------------------------------    [ Private } ---    */
  532. /*                                    */
  533. /*     This function is    used to    determine the left edge    of a selected    */
  534. /*     character cell.    The display point is rationalized to be        */
  535. /*     contained within    the boundary rectangle for the text.  What    */
  536. /*     this means is that when the display point is beyond the right    */
  537. /*     margin of the bounding rectangle, the point is rationalized to    */
  538. /*     be that margin.                            */
  539. /*                                    */
  540. /*     Upon Entry:                            */
  541. /*                                    */
  542. /*     PENTRYFWIN pefw;     = Entry Field Data Pointer            */
  543. /*     LONG      iChar; = Character Index                */
  544. /*                                    */
  545. /*     Upon Exit:                            */
  546. /*                                    */
  547. /*     lCalcDisplayPoint = Character Display Point            */
  548. /*                                    */
  549. /* --------------------------------------------------------------------    */
  550.  
  551. static LONG lCalcDisplayPoint(PENTRYFWIN pefw, LONG iChar)
  552.  
  553. {
  554. LONG xPoint;               /* Point Position            */
  555.  
  556.                /* Check    to see if there    is a shifting offset    */
  557.                /* indicating that the text has been scrolled    */
  558.                /* such that portions of    the text have been    */
  559.                /* scrolled off to the left of the entry    field.    */
  560.                /* When this is the case, the point needs to be    */
  561.                /* adjusted for this shift.  The    method used is    */
  562.                /* to subtract the starting point for the first    */
  563.                /* visible character from the desired character.    */
  564.                /* If not the case, the actual display point is    */
  565.                /* used.                        */
  566. if ( pefw->iOffset )
  567.                /* Make sure that the character requested is not    */
  568.                /* in front of the shifting offset which    if the    */
  569.                /* case,    use the    offset as the bounding edge    */
  570.  
  571.    if (    pefw->iOffset >    iChar )
  572.        xPoint =    pefw->aptl[pefw->iOffset].x + EFMARGIN_LEFT;
  573.    else
  574.        xPoint =    pefw->aptl[iChar].x - pefw->aptl[pefw->iOffset].x + EFMARGIN_LEFT;
  575. else
  576.    xPoint = pefw->aptl[iChar].x    + EFMARGIN_LEFT;
  577.  
  578.                /* Make sure that the point within the text    */
  579.                /* bounding rectangle on    the right edge        */
  580.  
  581. return((xPoint < pefw->rclText.xRight) ? xPoint    : pefw->rclText.xRight);
  582. }
  583. #pragma    subtitle("   Entry Field Control - Scroll Right Determination Procedure")
  584. #pragma    page( )
  585.  
  586. /* --- fScrollRight -----------------------------------    [ Private } ---    */
  587. /*                                    */
  588. /*     This function is    used to    determine if the entry field should    */
  589. /*     be scrolled right depending on the position of the current    */
  590. /*     selection such that if it is at the right margin    and less than    */
  591. /*     half an average character from the edge,    scrolling to the    */
  592. /*     right should occur.                        */
  593. /*                                    */
  594. /*     Upon Entry:                            */
  595. /*                                    */
  596. /*     PENTRYFWIN pefw;    = Entry    Field Data Pointer            */
  597. /*                                    */
  598. /*     Upon Exit:                            */
  599. /*                                    */
  600. /*     fScrollRight =  TRUE : Scrolling    to Right Should    Occur        */
  601. /*            = FALSE : No Scrolling Should Occur
  602. /*                                    */
  603. /* --------------------------------------------------------------------    */
  604.  
  605. static BOOL fScrollRight(PENTRYFWIN pefw)
  606.  
  607. {
  608.                /* Check    to see if the character    selection point    */
  609.                /* is within the    right margin area        */
  610.  
  611. if ( (pefw->aptl[pefw->iSel].x - pefw->aptl[pefw->iOffset].x) >
  612.      (pefw->rclText.xRight - pefw->cxMargin) )
  613.  
  614.                /* Current selection point within the margin    */
  615.                /* area,    check to see if    scrolling should    */
  616.                /* occur                        */
  617.  
  618.    if (    (pefw->aptl[pefw->cText].x - pefw->aptl[pefw->iOffset].x) < (pefw->rclText.xRight / 3L)    )
  619.  
  620.                /* Scrolling not    required since the end of the    */
  621.                /* displayed text is fully visible within the    */
  622.                /* entry    field                    */
  623.        return(FALSE);
  624.    else
  625.                /* Scrolling permissible, return    with the    */
  626.                /* scroll flag                    */
  627.        return(TRUE);
  628. else
  629.                /* Not within the margin    area, return with the    */
  630.                /* no scroll flag                */
  631.    return(FALSE);
  632. }
  633. #pragma    subtitle("   Entry Field Control - Cursor Management Procedure")
  634. #pragma    page( )
  635.  
  636. /* --- ShowCursor -------------------------------------    [ Private } ---    */
  637. /*                                    */
  638. /*     This function is    used to    determine if the cursor    location    */
  639. /*     calculated for the current insertion point is visible and when    */
  640. /*     the case    to display it in that location otherwise it is not    */
  641. /*     shown.                                */
  642. /*                                    */
  643. /*     Upon Entry:                            */
  644. /*                                    */
  645. /*     PENTRYFWIN pefw;    = Entry    Field Data Pointer            */
  646. /*     LONG      iSel;    = Selection Point                */
  647. /*                                    */
  648. /*     Upon Exit:                            */
  649. /*                                    */
  650. /*     Nothing                                */
  651. /*                                    */
  652. /* --------------------------------------------------------------------    */
  653.  
  654. static VOID ShowCursor(PENTRYFWIN pefw,    LONG iSel)
  655.  
  656. {
  657. LONG xCursor;               /* New Cursor Location        */
  658.  
  659. if ( pefw->aptl    )
  660.    xCursor = pefw->aptl[iSel].x    - pefw->aptl[pefw->iOffset].x +    EFMARGIN_LEFT;
  661. else
  662.    xCursor = EFMARGIN_LEFT;
  663.  
  664.                /* Calculate the    new position of    the cursor and    */
  665.                /* if it    is different from the previous location    */
  666.                /* determine if it should be shown and        */
  667.                /* repositioned                    */
  668.  
  669. if ( pefw->xCursor != xCursor )
  670.    {
  671.                /* New cursor location calculated, save the new    */
  672.                /* location internally within the private    */
  673.                /* control data                    */
  674.  
  675.    pefw->xCursor = xCursor;
  676.  
  677.                /* Check    to see if the new cursor location is    */
  678.                /* within the bounding text rectangle of    the    */
  679.                /* entry    field                    */
  680.  
  681.    if (    (pefw->xCursor >= pefw->rclText.xLeft) &&
  682.     (pefw->xCursor <= pefw->rclText.xRight)    )
  683.        {
  684.                /* Place    the cursor in its new position        */
  685.  
  686.        WinCreateCursor(pefw->hWnd, pefw->xCursor, pefw->yCursor,
  687.                0L, 0L, CURSOR_SETPOS, NULL);
  688.  
  689.                /* Cursor is within the rectangle, check    to see    */
  690.                /* if it    was previously hidden and if the case,    */
  691.                /* make it visible                */
  692.  
  693.        if ( !pefw->fCursorShown    )
  694.        WinShowCursor(pefw->hWnd, pefw->fCursorShown    = TRUE);
  695.        }
  696.    else
  697.                /* Cursor is not    visible    within the bounding    */
  698.                /* text rectangle.  Check to see    if the it is    */
  699.                /* currently visible and    if the case, hide it.    */
  700.  
  701.        if ( pefw->fCursorShown )
  702.        WinShowCursor(pefw->hWnd, pefw->fCursorShown    = FALSE);
  703.    }
  704. }
  705. #pragma    subtitle("   Entry Field Control - Overtype Character Drawing Procedure")
  706. #pragma    page( )
  707.  
  708. /* --- DrawOvertype -----------------------------------    [ Private } ---    */
  709. /*                                    */
  710. /*     This function is    used to    draw the selected overtype character.    */
  711. /*                                    */
  712. /*     Upon Entry:                            */
  713. /*                                    */
  714. /*     PENTRYFWIN pefw;    = Entry    Field Data Pointer            */
  715. /*                                    */
  716. /*     Upon Exit:                            */
  717. /*                                    */
  718. /*     Nothing                                */
  719. /*                                    */
  720. /* --------------------------------------------------------------------    */
  721.  
  722. static VOID DrawOvertype(PENTRYFWIN pefw)
  723.  
  724. {
  725.                /* Determine the    left edge of the drawing area    */
  726.  
  727. pefw->ptlDraw.x    = pefw->rclDraw.xLeft =    lCalcDisplayPoint(pefw,    pefw->iSel);
  728.  
  729.                /* Determine the    right edge of the drawing area    */
  730.  
  731. pefw->rclDraw.xRight = lCalcDisplayPoint(pefw, pefw->iSel + 1);
  732.  
  733.                /* Set the foreground and background colour for    */
  734.                /* the text to be drawn.     This is the highlight    */
  735.                /* text drawing colour.                */
  736.  
  737. GpiSetColor(pefw->hPS, pefw->lClrHilite);
  738. WinFillRect(pefw->hPS, &pefw->rclDraw, pefw->lClrHiliteBackground);
  739.  
  740.                /* Draw the one character that is to be high-    */
  741.                /* lighted                    */
  742.  
  743. GpiCharStringPosAt(pefw->hPS, &pefw->ptlDraw, &pefw->rclDraw, CHS_CLIP,
  744.            1L, &pefw->szText[pefw->iSel], NULL);
  745. }
  746. #pragma    subtitle("   Entry Field Control - Text Drawing Procedure")
  747. #pragma    page( )
  748.  
  749. /* --- DrawTextString ---------------------------------    [ Private } ---    */
  750. /*                                    */
  751. /*     This function is    used to    draw the text string using range    */
  752. /*     provided    either in normal or highlighted    mode.            */
  753. /*                                    */
  754. /*     Upon Entry:                            */
  755. /*                                    */
  756. /*     PENTRYFWIN pefw;        = Entry    Field Data Pointer        */
  757. /*     LONG      iStart;    = Starting Point            */
  758. /*     LONG      iEnd;        = Ending Point                */
  759. /*     BOOL      fHighlighted;    = Highlighting Required    Flag        */
  760. /*                                    */
  761. /*     Upon Exit:                            */
  762. /*                                    */
  763. /*     Nothing                                */
  764. /*                                    */
  765. /* --------------------------------------------------------------------    */
  766.  
  767. static VOID DrawTextString(PENTRYFWIN pefw, LONG iStart, LONG iEnd,
  768.                BOOL    fHighlighted)
  769.  
  770. {
  771.                /* Determine the    left edge of the drawing area    */
  772.  
  773. pefw->ptlDraw.x    = pefw->rclDraw.xLeft =    lCalcDisplayPoint(pefw,    iStart);
  774.  
  775.                /* Determine the    right edge of the drawing area    */
  776.  
  777. pefw->rclDraw.xRight = lCalcDisplayPoint(pefw, iEnd);
  778.  
  779.                /* Set the foreground and background colour for    */
  780.                /* the text to be drawn.     This is the highlight    */
  781.                /* text drawing colour.                */
  782.  
  783. GpiSetColor(pefw->hPS, fHighlighted ? pefw->lClrHilite : pefw->lClrText);
  784. WinFillRect(pefw->hPS, &pefw->rclDraw, fHighlighted ?
  785.                        pefw->lClrHiliteBackground :
  786.                        pefw->lClrBackground);
  787.  
  788.                /* Draw the desired text    in the location        */
  789.                /* calculated                    */
  790.  
  791. GpiCharStringPosAt(pefw->hPS, &pefw->ptlDraw, &pefw->rclDraw, CHS_CLIP,
  792.            iEnd    - iStart, &pefw->szText[iStart], NULL);
  793. }
  794. #pragma    subtitle("   Entry Field Control - Text Character Position Procedure")
  795. #pragma    page( )
  796.  
  797. /* --- DrawText    ---------------------------------------    [ Private } ---    */
  798. /*                                    */
  799. /*     This function is    used to    determine where    the mouse pointer    */
  800. /*     has clicked in terms of the characters that compose the text    */
  801. /*     of the entry field.                        */
  802. /*                                    */
  803. /*     Upon Entry:                            */
  804. /*                                    */
  805. /*     PENTRYFWIN pefw;    = Entry    Field Data Pointer            */
  806. /*                                    */
  807. /*     Upon Exit:                            */
  808. /*                                    */
  809. /*     Nothing                                */
  810. /*                                    */
  811. /* --------------------------------------------------------------------    */
  812.  
  813. static VOID DrawText(PENTRYFWIN    pefw)
  814.  
  815. {
  816.                /* Check    to see if the cursor is    being shown and    */
  817.                /* if so, hide it before    drawing            */
  818.  
  819. if ( pefw->fCursorShown    )
  820.    WinShowCursor(pefw->hWnd, pefw->fCursorShown    = FALSE);
  821.  
  822.                /* Check    to see if there    is no selected text or    */
  823.                /* that the control has lost its    focus which    */
  824.                /* causes the highlighted text to be dehigh-    */
  825.                /* lighted.  Also check for a special case where    */
  826.                /* the shift offset is greater than the end of    */
  827.                /* the selected text.                */
  828.  
  829. if ( (pefw->iSelStart == pefw->iSelEnd)    || !pefw->fFocus ||
  830.      (pefw->iOffset > pefw->iSelEnd) )
  831.    {
  832.                /* Draw the text    starting from the shift    offset    */
  833.                /* point                        */
  834.  
  835.    DrawTextString(pefw,    pefw->iOffset, pefw->cText, EFDISPLAY_NORMAL);
  836.  
  837.                /* Check    to see if in overtype mode which means    */
  838.                /* that the character immediately to the    right    */
  839.                /* of the insertion point should    be highlighted.    */
  840.                /* This will only occur if a character is indeed    */
  841.                /* adjacent to the cursor and the left mouse    */
  842.                /* button is not    currently being    pressed.    */
  843.  
  844.    if (    pefw->fOvertype    && (pefw->iSelStart == pefw->iSelEnd) &&
  845.     pefw->fFocus &&    (pefw->iSel != pefw->cText) && !pefw->fBtnDown )
  846.        DrawOvertype(pefw);
  847.    }
  848. else
  849.                /* Check    to see if the shift offset is after the    */
  850.                /* selection starting point            */
  851.  
  852.    if (    pefw->iOffset >    pefw->iSelStart    )
  853.        {
  854.                /* Draw the text    starting from the shift    offset    */
  855.                /* point                        */
  856.  
  857.        DrawTextString(pefw, pefw->iOffset, pefw->iSelEnd, EFDISPLAY_HIGHLIGHT);
  858.  
  859.                /* Check    to see if any text is to be drawn to    */
  860.                /* the right of the selected text and if    the    */
  861.                /* case,    draw it                    */
  862.  
  863.        if ( (pefw->iSelEnd < pefw->cText) &&
  864.         (pefw->rclDraw.xRight < pefw->rclText.xRight) )
  865.  
  866.                /* Draw the text    starting from the highlighted    */
  867.                /* point                        */
  868.  
  869.        DrawTextString(pefw,    pefw->iSelEnd, pefw->cText, EFDISPLAY_NORMAL);
  870.        else
  871.                /* No text to the right of the highlighted text,    */
  872.                /* erase    the remaining portion of the rectangle    */
  873.        {
  874.        pefw->rclDraw.xLeft = pefw->rclDraw.xRight;
  875.        pefw->rclDraw.xRight    = pefw->rclText.xRight;
  876.        WinFillRect(pefw->hPS, &pefw->rclDraw, pefw->lClrBackground);
  877.        }
  878.        }
  879.    else
  880.                /* Check    to see if the selection    point is not    */
  881.                /* starting at the begining of the text of the    */
  882.                /* entry    field which means that the displayed    */
  883.                /* text needs to    be displayed normally before    */
  884.                /* the highlighted text is drawn            */
  885.        {
  886.        if ( pefw->iSelStart && (pefw->iOffset <    pefw->iSelStart) )
  887.  
  888.                /* Draw the text    starting from the shift    offset    */
  889.                /* point                        */
  890.  
  891.        DrawTextString(pefw,    pefw->iOffset, pefw->iSelStart,    EFDISPLAY_NORMAL);
  892.        else
  893.                /* No normal display text before    the selected    */
  894.                /* text,    calculate the starting right edge of    */
  895.                /* the non-display text                */
  896.  
  897.        pefw->rclDraw.xRight    = lCalcDisplayPoint(pefw, pefw->iSelStart);
  898.  
  899.                /* Check    to see if any highlighted text needs to    */
  900.                /* be displayed.     The basic trick here is to    */
  901.                /* check    to see if the previously drawn text is    */
  902.                /* within the text bounding rectangle.        */
  903.  
  904.        if ( pefw->rclDraw.xRight < pefw->rclText.xRight    )
  905.        {
  906.                /* Draw the text    starting from the highlighting    */
  907.                /* point                        */
  908.  
  909.        DrawTextString(pefw,    pefw->iSelStart, pefw->iSelEnd,    EFDISPLAY_HIGHLIGHT);
  910.  
  911.                /* Check    to see if there    is any text that needs    */
  912.                /* to be    drawn after the    highlighted text that    */
  913.                /* is within the    text boudning rectangle        */
  914.  
  915.        if (    (pefw->cText > pefw->iSelEnd) &&
  916.         (pefw->rclDraw.xRight <    pefw->rclText.xRight) )
  917.  
  918.                /* Draw the text    starting from the highlighting    */
  919.                /* point                        */
  920.  
  921.            DrawTextString(pefw, pefw->iSelEnd, pefw->cText,
  922.                   EFDISPLAY_NORMAL);
  923.  
  924.                /* No text to the right of the highlighted text,    */
  925.                /* erase    the remaining portion of the rectangle    */
  926.  
  927.        pefw->rclDraw.xLeft = pefw->rclDraw.xRight;
  928.        pefw->rclDraw.xRight    = pefw->rclText.xRight;
  929.        WinFillRect(pefw->hPS, &pefw->rclDraw, pefw->lClrBackground);
  930.        }
  931.        }
  932.                /* Redisplay the    cursor since all of the    drawing    */
  933.                /* is now complete                */
  934.  
  935. WinShowCursor(pefw->hWnd, pefw->fCursorShown = TRUE);
  936. }
  937. #pragma    subtitle("   Entry Field Control - Text Character Position Procedure")
  938. #pragma    page( )
  939.  
  940. /* --- DrawSubText ------------------------------------    [ Private } ---    */
  941. /*                                    */
  942. /*     This function is    used to    determine where    the mouse pointer    */
  943. /*     has clicked in terms of the characters that compose the text    */
  944. /*     of the entry field.                        */
  945. /*                                    */
  946. /*     Upon Entry:                            */
  947. /*                                    */
  948. /*     PENTRYFWIN pefw;      = Entry Field    Data Pointer            */
  949. /*     LONG      iStart; = Starting Character Index            */
  950. /*     LONG      iEnd;      = Ending Character Index            */
  951. /*                                    */
  952. /*     Upon Exit:                            */
  953. /*                                    */
  954. /*     Nothing                                */
  955. /*                                    */
  956. /* --------------------------------------------------------------------    */
  957.  
  958. static VOID DrawSubText(PENTRYFWIN pefw, LONG iStart, LONG iEnd)
  959.  
  960. {
  961.                /* Check    to see if the starting point is    before    */
  962.                /* the shift offset and if the case make    the    */
  963.                /* starting point the shift offset        */
  964.  
  965. if ( iStart < pefw->iOffset )
  966.    iStart = pefw->iOffset;
  967.  
  968.                /* Check    to see if the ending point is after the    */
  969.                /* last character and if    the case make the    */
  970.                /* ending point the last    character offset    */
  971.  
  972. if ( iEnd > pefw->cText    )
  973.    iEnd    = pefw->cText;
  974.                /* Check    to see if the cursor is    being shown and    */
  975.                /* if so, hide it before    drawing            */
  976.  
  977. if ( pefw->fCursorShown    )
  978.    WinShowCursor(pefw->hWnd, pefw->fCursorShown    = FALSE);
  979.  
  980.                /* Check    to see if there    is any highlighting    */
  981.                /* required which is indicated by a selecting    */
  982.                /* range    and when not the case, just draw the    */
  983.                /* text range normally                */
  984.  
  985. if ( (pefw->iSelStart == pefw->iSelEnd)    || (iStart > pefw->iSelEnd) ||
  986.      (iEnd < pefw->iSelStart) )
  987.    {
  988.                /* Draw the text    starting from the starting    */
  989.                /* point                        */
  990.  
  991.    DrawTextString(pefw,    iStart,    iEnd, EFDISPLAY_NORMAL);
  992.  
  993.                /* Check    to see if in overtype mode which means    */
  994.                /* that the character immediately to the    right    */
  995.                /* of the insertion point should    be highlighted.    */
  996.                /* This will only occur if a character is indeed    */
  997.                /* adjacent to the cursor and the left mouse    */
  998.                /* button is not    currently being    pressed.    */
  999.  
  1000.    if (    pefw->fOvertype    && (pefw->iSelStart == pefw->iSelEnd) &&
  1001.     pefw->fFocus &&    (pefw->iSel != pefw->cText) && !pefw->fBtnDown )
  1002.        DrawOvertype(pefw);
  1003.    }
  1004. else
  1005.                /* Check    to see if just highlighted text    is to    */
  1006.                /* be drawn                    */
  1007.  
  1008.    if (    (iStart    > pefw->iSelStart) && (iEnd < pefw->iSelEnd) )
  1009.  
  1010.                /* Draw the text    starting from the starting    */
  1011.                /* point    highlighted                */
  1012.  
  1013.        DrawTextString(pefw, iStart, iEnd, EFDISPLAY_HIGHLIGHT);
  1014.    else
  1015.        if ( iStart > pefw->iSelStart )
  1016.        {
  1017.                /* Draw the text    starting from the starting    */
  1018.                /* point    highlighted                */
  1019.  
  1020.        DrawTextString(pefw,    iStart,    pefw->iSelEnd, EFDISPLAY_HIGHLIGHT);
  1021.  
  1022.                /* Check    to see if the right edge of the    high-    */
  1023.                /* lighted area was within the text bounding    */
  1024.                /* rectangle in which case there    is normal text    */
  1025.                /* that still needs to be drawn to the right    */
  1026.                /* of the highlighted area            */
  1027.  
  1028.        if (    pefw->rclDraw.xRight < pefw->rclText.xRight )
  1029.  
  1030.                /* Draw the text    starting from the starting    */
  1031.                /* point    normally                */
  1032.  
  1033.            DrawTextString(pefw, pefw->iSelEnd, iEnd, EFDISPLAY_NORMAL);
  1034.        }
  1035.        else
  1036.                /* Check    to see if the end point    is before the    */
  1037.                /* the selection    end point            */
  1038.        if (    iEnd < pefw->iSelEnd )
  1039.            {
  1040.                /* First    draw the normal    text that appears    */
  1041.                /* before the highlighted selection        */
  1042.  
  1043.            DrawTextString(pefw, iStart, pefw->iSelStart, EFDISPLAY_NORMAL);
  1044.  
  1045.                /* Check    to make    sure that the right edge of the    */
  1046.                /* text just drawn falls    within the text        */
  1047.                /* bounding rectangle which indicates that the    */
  1048.                /* remaining text can be    drawn            */
  1049.  
  1050.            if ( pefw->rclDraw.xRight < pefw->rclText.xRight    )
  1051.  
  1052.                /* Draw the text    starting from the starting    */
  1053.                /* point    highlighted                */
  1054.  
  1055.            DrawTextString(pefw,    pefw->iSelStart, iEnd,
  1056.                   EFDISPLAY_HIGHLIGHT);
  1057.            }
  1058.        else
  1059.            {
  1060.                /* First    draw the normal    text that appears    */
  1061.                /* before the highlighted selection        */
  1062.  
  1063.            DrawTextString(pefw, iStart, pefw->iSelStart, EFDISPLAY_NORMAL);
  1064.  
  1065.                /* Check    to make    sure that the right edge of the    */
  1066.                /* text just drawn falls    within the text        */
  1067.                /* bounding rectangle which indicates that the    */
  1068.                /* remaining text can be    drawn            */
  1069.  
  1070.            if ( pefw->rclDraw.xRight < pefw->rclText.xRight    )
  1071.            {
  1072.                /* Next draw the    highlighted text        */
  1073.  
  1074.            DrawTextString(pefw,    pefw->iSelStart, pefw->iSelEnd,
  1075.                   EFDISPLAY_HIGHLIGHT);
  1076.  
  1077.                /* Check    to make    sure that the right edge of the    */
  1078.                /* text just drawn falls    within the text        */
  1079.                /* bounding rectangle which indicates that the    */
  1080.                /* remaining text can be    drawn            */
  1081.  
  1082.            if (    pefw->rclDraw.xRight < pefw->rclText.xRight )
  1083.  
  1084.                /* Lastly draw the normal text that appears    */
  1085.                /* after    the highlighted    selection        */
  1086.  
  1087.                DrawTextString(pefw, pefw->iSelEnd, iEnd,
  1088.                       EFDISPLAY_NORMAL);
  1089.            }
  1090.            }
  1091.                /* Redisplay the    cursor since all of the    drawing    */
  1092.                /* is now complete                */
  1093.  
  1094. WinShowCursor(pefw->hWnd, pefw->fCursorShown = TRUE);
  1095. }
  1096. #pragma    subtitle("   Entry Field Control - Overtype Text Draw Procedure")
  1097. #pragma    page( )
  1098.  
  1099. /* --- DrawOvertypeText    -------------------------------    [ Private } ---    */
  1100. /*                                    */
  1101. /*     This function is    used to    draw the text indicating the overtype    */
  1102. /*     location.                            */
  1103. /*                                    */
  1104. /*     Upon Entry:                            */
  1105. /*                                    */
  1106. /*     PENTRYFWIN pefw;          =    Entry Field Data Pointer        */
  1107. /*     BOOL      fMoveRight; =    Move Right Direction            */
  1108. /*                                    */
  1109. /*     Upon Exit:                            */
  1110. /*                                    */
  1111. /*     Nothing                                */
  1112. /*                                    */
  1113. /* --------------------------------------------------------------------    */
  1114.  
  1115. static VOID DrawOvertypeText(PENTRYFWIN    pefw, BOOL fMoveRight)
  1116.  
  1117. {
  1118.                /* Check    to see if the cursor is    being shown and    */
  1119.                /* if so, hide it before    drawing            */
  1120.  
  1121. if ( pefw->fCursorShown    )
  1122.    WinShowCursor(pefw->hWnd, pefw->fCursorShown    = FALSE);
  1123.  
  1124.                /* Get the presentation space for the control    */
  1125.                /* place    the colour table into RGB mode before    */
  1126.                /* performing any drawing            */
  1127.  
  1128. GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
  1129.                0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  1130.  
  1131.                /* Check    to see if any text to the right    of the    */
  1132.                /* selection point or if    not moving to the right    */
  1133.                /* just calculate the left edge            */
  1134.  
  1135. if ( !fMoveRight && ((pefw->iSel + 1L) == pefw->cText) )
  1136.    pefw->rclDraw.xLeft = lCalcDisplayPoint(pefw, pefw->iSel + 1);
  1137. else
  1138.    {
  1139.                /* Calculate the    left drawing point for the    */
  1140.                /* text                        */
  1141.  
  1142.    pefw->rclDraw.xLeft = pefw->ptlDraw.x = lCalcDisplayPoint(pefw, fMoveRight ?    pefw->iSel - 1 : pefw->iSel + 1);
  1143.  
  1144.                /* Calculate the    right drawing point for    the    */
  1145.                /* text                        */
  1146.  
  1147.    pefw->rclDraw.xRight    = lCalcDisplayPoint(pefw, fMoveRight ? pefw->iSel : pefw->iSel + 2);
  1148.  
  1149.                /* Set the foreground and background colour for    */
  1150.                /* the text to be drawn.     This is the normal    */
  1151.                /* text drawing colour.                */
  1152.  
  1153.    GpiSetColor(pefw->hPS, pefw->lClrText);
  1154.    WinFillRect(pefw->hPS, &pefw->rclDraw, pefw->lClrBackground);
  1155.  
  1156.                /* Draw the text                    */
  1157.  
  1158.    GpiCharStringPosAt(pefw->hPS, &pefw->ptlDraw, &pefw->rclDraw, CHS_CLIP, 1L,
  1159.               &pefw->szText[fMoveRight ? pefw->iSel - 1    : pefw->iSel + 1], NULL);
  1160.    }
  1161.                /* Determine if the current selection point is    */
  1162.                /* not at the end of the    text string which if    */
  1163.                /* the case need    to draw    overtype text character    */
  1164.  
  1165. if ( pefw->iSel    < pefw->cText )
  1166.    {
  1167.                /* Check    to see if a move right performed which    */
  1168.                /* causes the display points to be adjusted for    */
  1169.                /* the action                    */
  1170.    if (    fMoveRight )
  1171.        {
  1172.        pefw->rclDraw.xLeft = pefw->ptlDraw.x = pefw->rclDraw.xRight;
  1173.        pefw->rclDraw.xRight = lCalcDisplayPoint(pefw, pefw->iSel + 1);
  1174.        }
  1175.    else
  1176.        {
  1177.                /* Just displaying the overtype point, find the    */
  1178.                /* display bounding rectangle for the character    */
  1179.  
  1180.        pefw->rclDraw.xRight = pefw->rclDraw.xLeft;
  1181.        pefw->rclDraw.xLeft = pefw->ptlDraw.x = lCalcDisplayPoint(pefw, pefw->iSel);
  1182.        }
  1183.                /* Set the colour for the highlighted character    */
  1184.  
  1185.    GpiSetColor(pefw->hPS, pefw->lClrHilite);
  1186.    WinFillRect(pefw->hPS, &pefw->rclDraw, pefw->lClrHiliteBackground);
  1187.  
  1188.                /* Draw the highlighted character        */
  1189.  
  1190.    GpiCharStringPosAt(pefw->hPS, &pefw->ptlDraw, &pefw->rclDraw, CHS_CLIP,
  1191.               1L, &pefw->szText[pefw->iSel], NULL);
  1192.    }
  1193.                /* Release the presentation space        */
  1194. WinReleasePS(pefw->hPS);
  1195.                /* Redisplay the    cursor since all of the    drawing    */
  1196.                /* is now complete                */
  1197.  
  1198. WinShowCursor(pefw->hWnd, pefw->fCursorShown = TRUE);
  1199. }
  1200. #pragma    subtitle("   Entry Field Control - Text Character Position Procedure")
  1201. #pragma    page( )
  1202.  
  1203. /* --- SelectText -------------------------------------    [ Private } ---    */
  1204. /*                                    */
  1205. /*     This function is    used to    determine where    the mouse pointer    */
  1206. /*     has clicked in terms of the characters that compose the text    */
  1207. /*     of the entry field.                        */
  1208. /*                                    */
  1209. /*     Upon Entry:                            */
  1210. /*                                    */
  1211. /*     PENTRYFWIN pefw;         = Entry Field Data    Pointer            */
  1212. /*     LONG      iAnchor;   = Anchor Position                */
  1213. /*     LONG      iSelected; = New Selection Position            */
  1214. /*                                    */
  1215. /*     Upon Exit:                            */
  1216. /*                                    */
  1217. /*     Nothing                                */
  1218. /*                                    */
  1219. /* --------------------------------------------------------------------    */
  1220.  
  1221. static VOID SelectText(PENTRYFWIN pefw,    LONG iAnchor, LONG iSelected)
  1222.  
  1223. {
  1224. LONG iSelStart;               /* Previous Selected    Start        */
  1225. LONG iSelEnd;               /* Previous Selected    End        */
  1226.  
  1227.                /* Check    to see if the selection    point specified    */
  1228.                /* is not the current selection point which if    */
  1229.                /* the case, just ignore    selection request    */
  1230.  
  1231. if ( iSelected != pefw->iSel )
  1232.    {
  1233.                /* Get the presentation space for the control    */
  1234.                /* place    the colour table into RGB mode before    */
  1235.                /* performing any drawing            */
  1236.  
  1237.    GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd), 0L,    LCOLF_RGB,
  1238.               0L, 0L, (PLONG)NULL);
  1239.  
  1240.                /* Save the current selection points        */
  1241.  
  1242.    iSelStart = pefw->iSelStart;
  1243.    iSelEnd   = pefw->iSelEnd;
  1244.  
  1245.                /* Check    to see if the anchor point is the    */
  1246.                /* current selection point which    if the case    */
  1247.                /* need to remove any selection indicators    */
  1248.  
  1249.    if (    iSelected == iAnchor )
  1250.        {
  1251.                /* Redraw the revised text non-highlighting    */
  1252.                /* after    setting    the selection points to    the    */
  1253.                /* new anchor point                */
  1254.  
  1255.        pefw->iSelStart = pefw->iSelEnd = iAnchor;
  1256.        DrawSubText(pefw, iSelStart, iSelEnd);
  1257.        }
  1258.    else
  1259.                /* Check    to see if the anchor point is before    */
  1260.                /* the new selection point which    if the case    */
  1261.                /* means    that the movement is going from    left    */
  1262.                /* to right generally                */
  1263.  
  1264.        if ( iSelected <    iAnchor    )
  1265.        {
  1266.                /* Save the new selection points            */
  1267.  
  1268.        pefw->iSelStart = iSelected;
  1269.        pefw->iSelEnd   = iAnchor;
  1270.  
  1271.                /* Refresh the text display showing the new    */
  1272.                /* selection                    */
  1273.  
  1274.        DrawSubText(pefw,
  1275.                iSelStart < pefw->iSelStart ? iSelStart : pefw->iSelStart,
  1276.                pefw->iSelEnd);
  1277.        }
  1278.        else
  1279.                /* Anchor point is after    the selection point,    */
  1280.                /* which    means that the movement    is going from    */
  1281.                /* right    to left    generally            */
  1282.        {
  1283.                /* Save the new selection points            */
  1284.  
  1285.        pefw->iSelStart = iAnchor;
  1286.        pefw->iSelEnd   = iSelected;
  1287.  
  1288.                /* Refresh the text display showing the new    */
  1289.                /* selection                    */
  1290.  
  1291.        DrawSubText(pefw, pefw->iSelStart,
  1292.                iSelEnd > pefw->iSelEnd ? iSelEnd : pefw->iSelEnd);
  1293.        }
  1294.                /* Release the presentation space        */
  1295.  
  1296.    WinReleasePS(pefw->hPS);
  1297.    }
  1298. }
  1299. #pragma    subtitle("   Entry Field Control - Entry Field Metrics Update Procedure")
  1300. #pragma    page( )
  1301.  
  1302. /* --- RefreshMetrics ---------------------------------    [ Private ] ---    */
  1303. /*                                    */
  1304. /*     This function is    used to    update entry field metrics when        */
  1305. /*     a possible font change has occurred or when the style of        */
  1306. /*     the entry field has changed.                    */
  1307. /*                                    */
  1308. /*     Upon Entry:                            */
  1309. /*                                    */
  1310. /*     PENTRYFWIN pefw;    = Entry    Field Private Data            */
  1311. /*                                    */
  1312. /*     Upon Exit:                            */
  1313. /*                                    */
  1314. /*     Nothing                                */
  1315. /*                                    */
  1316. /* --------------------------------------------------------------------    */
  1317.  
  1318. static VOID RefreshMetrics(PENTRYFWIN pefw)
  1319.  
  1320. {
  1321. FONTMETRICS fm;               /* Font Metrics            */
  1322.  
  1323.                /* Get the font metrics for the presentation    */
  1324.                /* space                        */
  1325.  
  1326. GpiQueryFontMetrics(pefw->hPS, sizeof(FONTMETRICS), &fm);
  1327.  
  1328.                /* Check    to see if any text defined currently    */
  1329.                /* for the entry    field and if so, cause the    */
  1330.                /* display points array to be updated such that    */
  1331.                /* it properly reflects the revised font    metrics    */
  1332.                /* differences that may have been caused    due to    */
  1333.                /* a font change                    */
  1334. if ( pefw->cText )
  1335.     {
  1336.                /* Get the revised points array            */
  1337.  
  1338.     QueryCharPoints(pefw);
  1339.  
  1340.                /* Calculate the    new cursor position and    force    */
  1341.                /* it to    the new    location            */
  1342.  
  1343.     pefw->xCursor = pefw->aptl[pefw->iSel].x + EFMARGIN_LEFT;
  1344.     ShowCursor(pefw, pefw->iSel);
  1345.     }
  1346. else
  1347.                /* Set the cursor location for the start    of the    */
  1348.                /* empty    entry field                */
  1349.  
  1350.     pefw->xCursor = EFMARGIN_LEFT;
  1351.  
  1352.                /* Calculate the    new metrics for    the entry field    */
  1353.  
  1354. pefw->cxMargin = (pefw->cxChar = fm.lAveCharWidth) / 2L;
  1355. pefw->cyCursor = fm.lMaxBaselineExt;
  1356. pefw->yDesc    = fm.lMaxDescender;
  1357. pefw->yCursor  = EFMARGIN_BOTTOM;
  1358.  
  1359.                /* Adjust the sizing of the entry field        */
  1360.  
  1361. if ( (pefw->cx > 0L) &&    (pefw->cx > 0L)    )
  1362.     SizeEntryField(pefw);
  1363. }
  1364. #pragma    subtitle("   Entry Field Control - Entry Field Control Data Decoding Procedure")
  1365. #pragma    page( )
  1366.  
  1367. /* --- DecodeCtlData ----------------------------------    [ Private ] ---    */
  1368. /*                                    */
  1369. /*     This function is    used to    process    the entry field    control    data    */
  1370. /*     that may    be provided when the entry field is first created.    */
  1371. /*                                    */
  1372. /*     Upon Entry:                            */
  1373. /*                                    */
  1374. /*     PENTRYFWIN pefw;    = Entry    Field Private Data            */
  1375. /*     MPARAM      mp1;    = Message Parameter 1                */
  1376. /*                                    */
  1377. /*     Upon Exit:                            */
  1378. /*                                    */
  1379. /*     Nothing                                */
  1380. /*                                    */
  1381. /* --------------------------------------------------------------------    */
  1382.  
  1383. static VOID DecodeCtlData(PENTRYFWIN pefw, MPARAM mp1)
  1384.  
  1385. {
  1386. PENTRYFCDATA pefcd;           /* Entry Field Control Data Pointer    */
  1387.  
  1388.                /* Check    to see if any control data specified    */
  1389.                /* in the first message parameter        */
  1390.  
  1391. if ( (pefcd = (PENTRYFCDATA)PVOIDFROMMP(mp1)) == NULL )
  1392.  
  1393.                /* No control data defined during the creation,    */
  1394.                /* set up the control for the default text limit    */
  1395.    pefw->cLimit    = 32L;
  1396. else
  1397.                /* Data present,    check to see if    the control    */
  1398.                /* data the older 16-bit    type or    the newer    */
  1399.                /* 32-bit type by checking the size of the    */
  1400.                /* structure                    */
  1401.  
  1402.    if (    pefcd->efd.cb == sizeof(ENTRYFDATA) )
  1403.        {
  1404.                /* 16-bit layout, get the maximum amount    of text    */
  1405.                /* the control is to handle along with any    */
  1406.                /* predefined selections                */
  1407.  
  1408.        pefw->cLimit  = pefcd->efd.cchEditLimit;
  1409.        pefw->iSel    = pefw->iSelStart = pefw->iAnchor = pefcd->efd.ichMinSel;
  1410.        pefw->iSelEnd = pefcd->efd.ichMaxSel;
  1411.        }
  1412.    else
  1413.        {
  1414.                /* 32-bit layout, get the maximum amount    of text    */
  1415.                /* the control is to handle along with any    */
  1416.                /* predefined selections                */
  1417.  
  1418.        pefw->cLimit  = (LONG)pefcd->efd2.cchEditLimit;
  1419.        pefw->iSel    = pefw->iSelStart = pefw->iAnchor = (LONG)pefcd->efd2.ichMinSel;
  1420.        pefw->iSelEnd = (LONG)pefcd->efd2.ichMaxSel;
  1421.        }
  1422. }
  1423. #pragma    subtitle("   Entry Field Control - Entry Field Message Processing Procedure")
  1424. #pragma    page( )
  1425.  
  1426. /* --- mrBaseFieldHandler -----------------------------    [ Private ] ---    */
  1427. /*                                    */
  1428. /*     This function is    used to    process    the base messages for the    */
  1429. /*     entry field control window.                    */
  1430. /*                                    */
  1431. /*     Upon Entry:                            */
  1432. /*                                    */
  1433. /*     HWND   hWnd; = Window Handle                    */
  1434. /*     ULONG  msg;  = PM Message                    */
  1435. /*     MPARAM mp1;  = Message Parameter    1                */
  1436. /*     MPARAM mp2;  = Message Parameter    2                */
  1437. /*                                    */
  1438. /*     Upon Exit:                            */
  1439. /*                                    */
  1440. /*     mrBaseFieldHandler = Message Handling Result            */
  1441. /*                                    */
  1442. /* --------------------------------------------------------------------    */
  1443.  
  1444. MRESULT    EXPENTRY mrBaseFieldHandler(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  1445.  
  1446. {
  1447. #pragma    info(nopar)
  1448.  
  1449. BOOL       fChanged;           /* Previous Changed Flag        */
  1450. BOOL       fInsertMode;           /* Previous Insert Mode Flag        */
  1451. BOOL       fReadOnly;           /* Previous Read Only Flag        */
  1452. PCHAR       pchClipText;           /* Clipboard    Text Pointer        */
  1453. PENTRYFWIN pefw;           /* Entry Field Internal Data    Pointer    */
  1454. register LONG n;           /* Text Length Holder        */
  1455.  
  1456. pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  1457.  
  1458. switch ( msg )
  1459.    {
  1460.  
  1461.    /*********************************************************************/
  1462.    /*  Base message:       EM_CLEAR                    */
  1463.    /*               mp1 = 0L;                    */
  1464.    /*               mp2 = 0L;                    */
  1465.    /*********************************************************************/
  1466.  
  1467.    case    EM_CLEAR :
  1468.                /* Check    to make    sure that the entry field is    */
  1469.                /* not read-only    and that a selection has been    */
  1470.                /* made before trying to    delete the text        */
  1471.  
  1472.        if ( !pefw->fReadOnly &&    (pefw->iSelStart != pefw->iSelEnd) )
  1473.        {
  1474.        DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, TRUE);
  1475.        return(MRFROMLONG(TRUE));
  1476.        }
  1477.        else
  1478.        return(MRFROMLONG(FALSE));
  1479.  
  1480.    /*********************************************************************/
  1481.    /*  Base message:       EM_COPY                    */
  1482.    /*               mp1 = 0L;                    */
  1483.    /*               mp2 = 0L;                    */
  1484.    /*********************************************************************/
  1485.  
  1486.    case    EM_COPY    :
  1487.                /* Check    to make    sure that a selection within    */
  1488.                /* the text has been made before    trying to copy    */
  1489.                /* the selection    to the clipboard        */
  1490.  
  1491.        if ( (pefw->iSelStart !=    pefw->iSelEnd) )
  1492.        {
  1493.                /* Check    to see if the entry field is unreadable    */
  1494.                /* which    means that it is being used for    some-    */
  1495.                /* thing    like a password    entry area.  In    this    */
  1496.                /* case do not allow the    text to    be copied to    */
  1497.                /* the clipboard.  (Note:  this differs from    */
  1498.                /* the OS/2 entry field in that it will allow    */
  1499.                /* you to copy the text to the clipboard)    */
  1500.  
  1501.        if (    pefw->flStyle &    ES_UNREADABLE )
  1502.            {
  1503.            WinAlarm(HWND_DESKTOP, WA_ERROR);
  1504.            return(MRFROMLONG(FALSE));
  1505.            }
  1506.        else
  1507.            {
  1508.                /* Allocate the shared memory for the text    */
  1509.                /* making sure that there is enough memory for    */
  1510.                /* the text plus    the NULL terminating byte    */
  1511.  
  1512.            DosAllocSharedMem((PPVOID)(PVOID)&pchClipText, NULL,
  1513.                  (ULONG)(pefw->iSelEnd - pefw->iSelStart + 1),
  1514.                  fALLOCSHR);
  1515.  
  1516.                /* Open and empty the clipboard before copying    */
  1517.                /* the selected text to the shared memory    */
  1518.                /* and placing the pointer on the clipboard    */
  1519.  
  1520.            WinOpenClipbrd(pefw->hAB);
  1521.            WinEmptyClipbrd(pefw->hAB);
  1522.            WinSetClipbrdData(pefw->hAB, (ULONG)pszCopyText(pefw, pchClipText,
  1523.                                    pefw->iSelStart,
  1524.                                    pefw->iSelEnd),
  1525.                  CF_TEXT, CFI_POINTER);
  1526.  
  1527.                /* Close    the clipboard to allow the copied text    */
  1528.                /* to be    used by    other processes    as well    as this    */
  1529.                /* one                        */
  1530.  
  1531.            WinCloseClipbrd(pefw->hAB);
  1532.            return(MRFROMLONG(TRUE));
  1533.            }
  1534.        }
  1535.        else
  1536.        return(MRFROMLONG(FALSE));
  1537.  
  1538.    /*********************************************************************/
  1539.    /*  Base message:       EM_CUT                    */
  1540.    /*               mp1 = 0L;                    */
  1541.    /*               mp2 = 0L;                    */
  1542.    /*********************************************************************/
  1543.  
  1544.    case    EM_CUT :
  1545.                /* Check    to make    sure that the entry field is    */
  1546.                /* not read-only    and that a selection has been    */
  1547.                /* made before trying to    cut the    text from the    */
  1548.                /* entry    field and place    it on the system    */
  1549.                /* clipboard                    */
  1550.  
  1551.        if ( !pefw->fReadOnly &&    (pefw->iSelStart != pefw->iSelEnd) )
  1552.        {
  1553.                /* Allocate the shared memory for the text    */
  1554.                /* making sure that there is enough memory for    */
  1555.                /* the text plus    the NULL terminating byte    */
  1556.  
  1557.        DosAllocSharedMem((PPVOID)(PVOID)&pchClipText, NULL,
  1558.                  (ULONG)(pefw->iSelEnd - pefw->iSelStart + 1),
  1559.                  fALLOCSHR);
  1560.  
  1561.                /* Open and empty the clipboard before copying    */
  1562.                /* the selected text to the shared memory    */
  1563.                /* and placing the pointer on the clipboard    */
  1564.  
  1565.        WinOpenClipbrd(pefw->hAB);
  1566.        WinEmptyClipbrd(pefw->hAB);
  1567.        WinSetClipbrdData(pefw->hAB,
  1568.                  (ULONG)pszCopyText(pefw, pchClipText, pefw->iSelStart, pefw->iSelEnd),
  1569.                  CF_TEXT, CFI_POINTER);
  1570.  
  1571.                /* Close    the clipboard to allow the copied text    */
  1572.                /* to be    used by    other processes    as well    as this    */
  1573.                /* one                        */
  1574.  
  1575.        WinCloseClipbrd(pefw->hAB);
  1576.  
  1577.                /* Delete the selected text            */
  1578.  
  1579.        DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, TRUE);
  1580.        return(MRFROMLONG(TRUE));
  1581.        }
  1582.        else
  1583.        return(MRFROMLONG(FALSE));
  1584.  
  1585.    /*********************************************************************/
  1586.    /*  Base message:       EM_PASTE                    */
  1587.    /*               mp1 = 0L;                    */
  1588.    /*               mp2 = 0L;                    */
  1589.    /*********************************************************************/
  1590.  
  1591.    case    EM_PASTE :
  1592.                /* Check    to make    sure that the entry field is    */
  1593.                /* not read-only                    */
  1594.  
  1595.        if ( pefw->fReadOnly )
  1596.        return(MRFROMLONG(FALSE));
  1597.        else
  1598.        {
  1599.                /* Open the clipboard and then check to see if    */
  1600.                /* any text has been placed on it that can be    */
  1601.                /* pasted within    the entry field            */
  1602.  
  1603.        WinOpenClipbrd(pefw->hAB);
  1604.        if (    WinQueryClipbrdData(pefw->hAB, CF_TEXT)    )
  1605.            {
  1606.                /* Text contained within    the clipboard, get the    */
  1607.                /* pointer to the text                */
  1608.  
  1609.            if ( (pchClipText = (PCHAR)WinQueryClipbrdData(pefw->hAB, CF_TEXT)) != NULL )
  1610.  
  1611.                /* Check    to make    sure that the selection    within    */
  1612.                /* the clipboard    will fit within    the entry field    */
  1613.  
  1614.            if (    ((n = (LONG)strlen(pchClipText)) + pefw->cText)    < pefw->cLimit )
  1615.                {
  1616.                /* Check    to see if any text is currently        */
  1617.                /* selected which means that the    text should be    */
  1618.                /* replaced by the text from the    clipboard.  If    */
  1619.                /* the case, delete the selected    text.        */
  1620.  
  1621.                if ( pefw->iSelStart != pefw->iSelEnd )
  1622.                DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, FALSE);
  1623.  
  1624.                /* Paste    the text into the entry    field at the    */
  1625.                /* current selection point            */
  1626.  
  1627.                PasteText(pefw, pchClipText, n);
  1628.                }
  1629.                /* Finished with    the clipboard, close it        */
  1630.  
  1631.            WinCloseClipbrd(pefw->hAB);
  1632.            return(MRFROMLONG(TRUE));
  1633.            }
  1634.        else
  1635.                /* No text within the clipboard,    close it    */
  1636.            {
  1637.            WinCloseClipbrd(pefw->hAB);
  1638.            return(MRFROMLONG(FALSE));
  1639.            }
  1640.        }
  1641.  
  1642.    /*********************************************************************/
  1643.    /*  Base message:       EM_QUERYCHANGED                */
  1644.    /*               mp1 = 0L;                    */
  1645.    /*               mp2 = 0L;                    */
  1646.    /*********************************************************************/
  1647.  
  1648.    case    EM_QUERYCHANGED    :
  1649.        fChanged    = pefw->fChanged;
  1650.        pefw->fChanged =    FALSE;
  1651.        return(MRFROMLONG(fChanged));
  1652.  
  1653.    /*********************************************************************/
  1654.    /*  Base message:       EM_QUERYFIRSTCHAR                */
  1655.    /*               mp1 = 0L;                    */
  1656.    /*               mp2 = 0L;                    */
  1657.    /*********************************************************************/
  1658.  
  1659.    case    EM_QUERYFIRSTCHAR :
  1660.                /* Return the offset to the first displayed    */
  1661.                /* character in the entry field            */
  1662.  
  1663.        return(MRFROMLONG(pefw->iOffset));
  1664.  
  1665.    /*********************************************************************/
  1666.    /*  Base message:       EM_QUERYREADONLY                */
  1667.    /*               mp1 = 0L;                    */
  1668.    /*               mp2 = 0L;                    */
  1669.    /*********************************************************************/
  1670.  
  1671.    case    EM_QUERYREADONLY :
  1672.  
  1673.                /* Return the read-only status of the entry    */
  1674.                /* field                        */
  1675.  
  1676.        return(MRFROMLONG(pefw->fReadOnly));
  1677.  
  1678.    /*********************************************************************/
  1679.    /*  Base message:       EM_QUERYSEL                    */
  1680.    /*               mp1 = 0L;                    */
  1681.    /*               mp2 = 0L;                    */
  1682.    /*********************************************************************/
  1683.  
  1684.    case    EM_QUERYSEL :
  1685.                /* Return the selection range            */
  1686.  
  1687.        return(MRFROM2SHORT(pefw->iSelStart, pefw->iSelEnd));
  1688.  
  1689.    /*********************************************************************/
  1690.    /*  Base message:       EM_SETFIRSTCHAR                */
  1691.    /*               mp1 = MPFROMSHORT(sOffset);            */
  1692.    /*               mp2 = 0L;                    */
  1693.    /*********************************************************************/
  1694.  
  1695.    case    EM_SETFIRSTCHAR    :
  1696.                /* Check    to make    sure that the value specified    */
  1697.                /* for the message is within the    text limits    */
  1698.  
  1699.        if ( ((LONG)(SHORT)SHORT1FROMMP(mp1) >= 0L) &&
  1700.         ((LONG)(SHORT)SHORT1FROMMP(mp1) <= pefw->cText) )
  1701.        {
  1702.                /* Check    to see if the requested    starting point    */
  1703.                /* is the current offset    in which case nothing    */
  1704.                /* needs    to be done                */
  1705.  
  1706.        if (    pefw->iOffset != (LONG)(SHORT)SHORT1FROMMP(mp1)    )
  1707.            {
  1708.                /* New offset being defined, save the new value    */
  1709.  
  1710.            pefw->iOffset = (LONG)(SHORT)SHORT1FROMMP(mp1);
  1711.  
  1712.                /* Get the presentation space handle for    the    */
  1713.                /* entry    field and place    it in RGB mode before    */
  1714.                /* causing the text to be redrawn showing the    */
  1715.                /* new offset                    */
  1716.  
  1717.            GpiCreateLogColorTable(pefw->hPS    = WinGetPS(pefw->hWnd),
  1718.                       0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  1719.            DrawText(pefw);
  1720.            WinReleasePS(pefw->hPS);
  1721.            }
  1722.        return(MRFROMLONG(TRUE));
  1723.        }
  1724.        else
  1725.        return(MRFROMLONG(FALSE));
  1726.  
  1727.    /*********************************************************************/
  1728.    /*  Base message:       EM_SETINSERTMODE                */
  1729.    /*               mp1 = MPFROMSHORT(usInsert);            */
  1730.    /*               mp2 = 0L;                    */
  1731.    /*********************************************************************/
  1732.  
  1733.    case    EM_SETINSERTMODE :
  1734.                /* Determine the    current    insert mode and    save    */
  1735.                /* since    it is returned                */
  1736.  
  1737.        if ( pefw->fOvertype )
  1738.        fInsertMode = FALSE;
  1739.        else
  1740.        fInsertMode = TRUE;
  1741.  
  1742.                /* Determine the    new insert mode    and save the    */
  1743.                /* overtype equivalent                */
  1744.  
  1745.        if ( (BOOL)SHORT1FROMMP(mp1) )
  1746.        pefw->fOvertype = FALSE;
  1747.        else
  1748.        pefw->fOvertype = TRUE;
  1749.  
  1750.                /* Update the internal OS/2 PM insert mode to    */
  1751.                /* reflect the change                */
  1752.  
  1753.        WinSetSysValue(HWND_DESKTOP, SV_INSERTMODE,
  1754.               (LONG)(BOOL)SHORT1FROMMP(mp1));
  1755.  
  1756.                /* Check    to see if the overtype character needs    */
  1757.                /* to be    redrawn    do to the change of the    insert    */
  1758.                /* mode                        */
  1759.  
  1760.        if ( fInsertMode    != (BOOL)SHORT1FROMMP(mp1) )
  1761.        {
  1762.        GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
  1763.                   0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  1764.        DrawText(pefw);
  1765.        WinReleasePS(pefw->hPS);
  1766.        }
  1767.        return(MRFROMLONG(fInsertMode));
  1768.  
  1769.    /*********************************************************************/
  1770.    /*  Base message:       EM_SETREADONLY                */
  1771.    /*               mp1 = MPFROMSHORT(usReadOnly);        */
  1772.    /*               mp2 = 0L;                    */
  1773.    /*********************************************************************/
  1774.  
  1775.    case    EM_SETREADONLY :
  1776.        fReadOnly = pefw->fReadOnly;
  1777.  
  1778.        pefw->fReadOnly = (BOOL)SHORT1FROMMP(mp1);
  1779.        return(MRFROMLONG(fReadOnly));
  1780.  
  1781.    /*********************************************************************/
  1782.    /*  Base message:       EM_SETSEL                    */
  1783.    /*               mp1 = MPFROM2SHORT(usMinSel,    usMaxSel);    */
  1784.    /*               mp2 = 0L;                    */
  1785.    /*********************************************************************/
  1786.  
  1787.    case    EM_SETSEL :
  1788.        if ( ((LONG)(SHORT)SHORT1FROMMP(mp1) >= 0L) &&
  1789.         ((LONG)(SHORT)SHORT1FROMMP(mp1) <= (LONG)(SHORT)SHORT2FROMMP(mp1)) )
  1790.        {
  1791.                /* Check    to see if the selection    range is    */
  1792.                /* different in which case need to reflect the    */
  1793.                /* new range otherwise just ignore the request    */
  1794.  
  1795.        if (    (pefw->iSelStart != (LONG)(SHORT)SHORT1FROMMP(mp1)) &&
  1796.         (pefw->iSelEnd     != (LONG)(SHORT)SHORT2FROMMP(mp1)) )
  1797.            {
  1798.                /* New selection    range being specified, save the    */
  1799.                /* starting value                */
  1800.  
  1801.            pefw->iSelStart = (LONG)(SHORT)SHORT1FROMMP(mp1);
  1802.  
  1803.                /* Check    the ending selection value to make sure    */
  1804.                /* that if it is    greater    than the amount    of text    */
  1805.                /* contained within the entry field, the    range    */
  1806.                /* ends at the end of the text            */
  1807.  
  1808.            if ( (pefw->iSelEnd = (LONG)(SHORT)SHORT2FROMMP(mp1)) > pefw->cText )
  1809.            pefw->iSelEnd = pefw->cText;
  1810.  
  1811.                /* Get the presentation space handle for    the    */
  1812.                /* entry    field and place    it in RGB mode before    */
  1813.                /* causing the text to be redrawn showing the    */
  1814.                /* new selection                    */
  1815.  
  1816.            GpiCreateLogColorTable(pefw->hPS    = WinGetPS(pefw->hWnd),
  1817.                   0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  1818.            DrawText(pefw);
  1819.            WinReleasePS(pefw->hPS);
  1820.            }
  1821.  
  1822.        return(MRFROMLONG(TRUE));
  1823.        }
  1824.        else
  1825.        return(MRFROMLONG(FALSE));
  1826.  
  1827.    /*********************************************************************/
  1828.    /*  Base message:       EM_SETTEXTLIMIT                */
  1829.    /*               mp1 = MPFROMSHORT(sTextLimit);        */
  1830.    /*               mp2 = 0L;                    */
  1831.    /*********************************************************************/
  1832.  
  1833.    case    EM_SETTEXTLIMIT    :
  1834.                /* Check    to make    sure that the text limit    */
  1835.                /* specified is within the current text holder    */
  1836.                /* limits                    */
  1837.  
  1838.        if ( ((LONG)(SHORT)SHORT1FROMMP(mp1) >= 0L) &&
  1839.         ((LONG)(SHORT)SHORT1FROMMP(mp1) < 1024L) )
  1840.        {
  1841.                /* New limit within control limits, save    the    */
  1842.                /* value    internally                */
  1843.  
  1844.        pefw->cLimit    = (LONG)(SHORT)SHORT1FROMMP(mp1);
  1845.        return(MRFROMLONG(TRUE));
  1846.        }
  1847.        else
  1848.                /* Requested text limit too high, inform    the    */
  1849.                /* owner    of the problem                */
  1850.        {
  1851.        mrNotifyOwner(pefw, EN_MEMERROR);
  1852.        return(MRFROMLONG(FALSE));
  1853.        }
  1854.    }
  1855. return(0L);
  1856. }
  1857. #pragma    info(par)
  1858.  
  1859. #pragma    subtitle("   Entry Field Control   - Exception Handler Routine")
  1860. #pragma    page( )
  1861.  
  1862. /* --- EntryFieldExceptionHandler ---------------------    [ Private ] ---    */
  1863. /*                                    */
  1864. /*     This function is    used process exceptions    under 2.x and to,    */
  1865. /*     depending on the    exception, provide a method of performing    */
  1866. /*     lazy pointer validation for the data types.            */
  1867. /*                                    */
  1868. /*     Upon Entry:                            */
  1869. /*                                    */
  1870. /*     PEXCEPTIONREPORTRECORD        pxcptrepr; = Report    Record        */
  1871. /*     PEXCEPTIONREGISTRATIONRECORD pxcptregr; = Registration Record    */
  1872. /*     PCONTEXTRECORD            pcr;       = Context Record        */
  1873. /*     PVOID                sysinfo;   = System    Reserved    */
  1874. /*                                    */
  1875. /*     Upon Exit:                            */
  1876. /*                                    */
  1877. /*     EntryFieldExceptionHandler = Exception Handling Value        */
  1878. /*                                    */
  1879. /* --------------------------------------------------------------------    */
  1880.  
  1881. APIRET APIENTRY    EntryFieldExceptionHandler(PEXCEPTIONREPORTRECORD pxcptrepr,
  1882.                        PEXCEPTIONREGISTRATIONRECORD    pxcptregr,
  1883.                        PCONTEXTRECORD pcr, PVOID sysinfo)
  1884.  
  1885. {
  1886. #pragma    info(nopar)
  1887.  
  1888. if ( (EH_EXIT_UNWIND & pxcptrepr->fHandlerFlags) ||
  1889.      (EH_UNWINDING   & pxcptrepr->fHandlerFlags) ||
  1890.      (EH_NESTED_CALL & pxcptrepr->fHandlerFlags) )
  1891.    return(XCPT_CONTINUE_SEARCH);
  1892.  
  1893. if ( pxcptrepr->ExceptionNum ==    XCPT_ACCESS_VIOLATION )
  1894.    longjmp((INT    *)jBuf,    1);
  1895.  
  1896. return(XCPT_CONTINUE_SEARCH);
  1897. }
  1898. #pragma    info(par)
  1899.  
  1900. #pragma    subtitle("   Entry Field Control - Delete Text Routine")
  1901. #pragma    page( )
  1902.  
  1903. /* --- DeleteText -------------------------------------    [ Private ] ---    */
  1904. /*                                    */
  1905. /*     This function is    used delete the    selected range of text from    */
  1906. /*     the entry field and to save the deleted text within the undo    */
  1907. /*     buffer for later    retrieval if required.                */
  1908. /*                                    */
  1909. /*     Upon Entry:                            */
  1910. /*                                    */
  1911. /*     PENTRYFWIN pefw;         = Entry Field Private Data            */
  1912. /*     LONG      iSelStart; = Deletion    Start Index            */
  1913. /*     LONG      iSelEnd;   = Deletion    End Index            */
  1914. /*     BOOL      fRedraw;   = Redraw Flag                */
  1915. /*                                    */
  1916. /*     Upon Exit:                            */
  1917. /*                                    */
  1918. /*     Nothing                                */
  1919. /*                                    */
  1920. /* --------------------------------------------------------------------    */
  1921.  
  1922. static VOID DeleteText(PENTRYFWIN pefw,    LONG iSelStart,    LONG iSelEnd,
  1923.                BOOL fRedraw)
  1924.  
  1925. {
  1926. register LONG n;           /* Length Value            */
  1927. EXCEPTIONREGISTRATIONRECORD xcptregr;       /* Exception    Record        */
  1928.  
  1929.                /* Check    to make    sure that the selection    start    */
  1930.                /* is not after the end of the text        */
  1931.  
  1932. if ( iSelStart < pefw->cText )
  1933.    {
  1934.                /* Register exception handler that is used for    */
  1935.                /* the lazy pointer validation tests        */
  1936.  
  1937.    xcptregr.prev_structure   = NULL;
  1938.    xcptregr.ExceptionHandler = &EntryFieldExceptionHandler;
  1939.  
  1940.    DosSetExceptionHandler(&xcptregr);
  1941.  
  1942.    if (    !setjmp(jBuf) )
  1943.        {
  1944.                /* Check    to make    sure that the ending range for    */
  1945.                /* the text to be deleted does not exceed the    */
  1946.                /* current text in which    case make the ending    */
  1947.                /* selection value the text limits        */
  1948.  
  1949.        if ( iSelEnd > pefw->cText )
  1950.        iSelEnd = pefw->cText;
  1951.  
  1952.                /* Copy the selected range of text to the undo    */
  1953.                /* buffer                    */
  1954.  
  1955.        memcpy(pefw->szUndo, &pefw->szText[iSelStart],
  1956.           (UINT)(n = iSelEnd - iSelStart));
  1957.        pefw->szUndo[n] = 0;
  1958.  
  1959.                /* Check    to see if the selection    was to the end    */
  1960.                /* of the text in which case NULL terminate the    */
  1961.                /* text string at the selection starting    point    */
  1962.  
  1963.        if ( iSelEnd == pefw->cText )
  1964.        pefw->szText[iSelStart] = 0;
  1965.        else
  1966.                /* Move up the text that    was after the selection    */
  1967.  
  1968.        memmove(&pefw->szText[iSelStart], &pefw->szText[iSelEnd],
  1969.            (UINT)(pefw->cText -    iSelEnd    + 1));
  1970.  
  1971.                /* Update the text length            */
  1972.        pefw->cText -= n;
  1973.                /* Set the new selection    point to the starting    */
  1974.                /* location where the previous selection    started    */
  1975.  
  1976.        pefw->iSel = pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = iSelStart;
  1977.  
  1978.                /* Get the presentation space handle for    the    */
  1979.                /* entry    field                    */
  1980.  
  1981.        pefw->hPS = WinGetPS(pefw->hWnd);
  1982.  
  1983.                /* Get the new point array for the text string    */
  1984.  
  1985.        QueryCharPoints(pefw);
  1986.  
  1987.        if ( pefw->cText    && pefw->iOffset && (pefw->aptl[pefw->cText].x < pefw->rclText.xRight) )
  1988.        {
  1989.        pefw->iOffset = 0L;
  1990.        if (    !fRedraw )
  1991.            {
  1992.                /* Deletion changes need    to be redrawn, place    */
  1993.                /* the colour table into    RGB mode and draw the    */
  1994.                /* revised text string within the entry field    */
  1995.                /* so as    to reflect the changes made        */
  1996.  
  1997.            GpiCreateLogColorTable(pefw->hPS, 0L, LCOLF_RGB,
  1998.                       0L, 0L, (PLONG)NULL);
  1999.            DrawText(pefw);
  2000.            }
  2001.        }
  2002.        else
  2003.        {
  2004.        GpiCreateLogColorTable(pefw->hPS, 0L, LCOLF_RGB,
  2005.                   0L, 0L, (PLONG)NULL);
  2006.        if (    pefw->fCursorShown )
  2007.            WinShowCursor(pefw->hWnd, pefw->fCursorShown = FALSE);
  2008.        WinFillRect(pefw->hPS, &pefw->rcl, pefw->lClrBackground);
  2009.        }
  2010.                /* Check    to see if the changes should be    redrawn    */
  2011.        if ( fRedraw )
  2012.        {
  2013.                /* Deletion changes need    to be redrawn, place    */
  2014.                /* the colour table into    RGB mode and draw the    */
  2015.                /* revised text string within the entry field    */
  2016.                /* so as    to reflect the changes made        */
  2017.  
  2018.        GpiCreateLogColorTable(pefw->hPS, 0L, LCOLF_RGB,
  2019.                   0L, 0L, (PLONG)NULL);
  2020.        DrawText(pefw);
  2021.  
  2022.                /* Notify the owner that    changes    have occurred    */
  2023.  
  2024.        mrNotifyOwner(pefw, EN_CHANGE);
  2025.        }
  2026.                /* Release the presentation space handle        */
  2027.  
  2028.        WinReleasePS(pefw->hPS);
  2029.        }
  2030.                /* Remove the exception handle since the    lazy    */
  2031.                /* pointer evaluation is    done            */
  2032.  
  2033.    DosUnsetExceptionHandler(&xcptregr);
  2034.    }
  2035. }
  2036. #pragma    subtitle("   Entry Field Control - Copy Text Routine")
  2037. #pragma    page( )
  2038.  
  2039. /* --- pszCopyText ------------------------------------    [ Private ] ---    */
  2040. /*                                    */
  2041. /*     This function is    used to    copy the text selection    to the        */
  2042. /*     supplied    buffer.                            */
  2043. /*                                    */
  2044. /*     Upon Entry:                            */
  2045. /*                                    */
  2046. /*     PENTRYFWIN pefw;         = Entry Field Private Data            */
  2047. /*     PSZ      pszBuffer; = Copy Buffer                */
  2048. /*     LONG      iSelStart; = Deletion    Start Index            */
  2049. /*     LONG      iSelEnd;   = Deletion    End Index            */
  2050. /*                                    */
  2051. /*     Upon Exit:                            */
  2052. /*                                    */
  2053. /*     pszCopyText = Address of    pszBuffer                */
  2054. /*                                    */
  2055. /* --------------------------------------------------------------------    */
  2056.  
  2057. static PSZ pszCopyText(PENTRYFWIN pefw,    PSZ pszBuffer, LONG iSelStart,
  2058.                LONG iSelEnd)
  2059.  
  2060. {
  2061. register LONG i;           /* Length Holder            */
  2062. EXCEPTIONREGISTRATIONRECORD xcptregr;       /* Exception    Record        */
  2063.  
  2064.                /* Check    to make    sure that the selection    start    */
  2065.                /* is not after the end of the text        */
  2066.  
  2067. if ( iSelStart < pefw->cText )
  2068.    {
  2069.                /* Register exception handler that is used for    */
  2070.                /* the lazy pointer validation tests        */
  2071.  
  2072.    xcptregr.prev_structure   = NULL;
  2073.    xcptregr.ExceptionHandler = &EntryFieldExceptionHandler;
  2074.  
  2075.    DosSetExceptionHandler(&xcptregr);
  2076.  
  2077.    if (    !setjmp(jBuf) )
  2078.        {
  2079.                /* Check    to make    sure that the ending range for    */
  2080.                /* the text to be deleted does not exceed the    */
  2081.                /* current text in which    case make the ending    */
  2082.                /* selection value the text limits        */
  2083.  
  2084.        if ( iSelEnd > pefw->cText )
  2085.        iSelEnd = pefw->cText;
  2086.  
  2087.                /* Check    to make    sure that the start of the    */
  2088.                /* selection is not after the selection end    */
  2089.                /* which    would be incorrect            */
  2090.  
  2091.        if ( iSelStart <    iSelEnd    )
  2092.        {
  2093.                /* Copy the text    from the internal text buffer    */
  2094.                /* to the supplied buffer            */
  2095.  
  2096.        memcpy(pszBuffer,
  2097.           (PSZ)(pefw->flStyle &    ES_UNREADABLE ?
  2098.             &pefw->szPassword[iSelStart] :
  2099.             &pefw->szText[iSelStart]), (UINT)(i = iSelEnd -    iSelStart));
  2100.        pszBuffer[i]    = 0;
  2101.        }
  2102.        else
  2103.                /* No text to copy, make    the supplied buffer    */
  2104.                /* reflect the condition                */
  2105.  
  2106.        pszBuffer[0]    = 0;
  2107.        }
  2108.                /* Remove the exception handle since the    lazy    */
  2109.                /* pointer evaluation is    done            */
  2110.  
  2111.    DosUnsetExceptionHandler(&xcptregr);
  2112.    }
  2113. return(pszBuffer);
  2114. }
  2115. #pragma    subtitle("   Entry Field Control - Paste Text Routine")
  2116. #pragma    page( )
  2117.  
  2118. /* --- PasteText --------------------------------------    [ Private ] ---    */
  2119. /*                                    */
  2120. /*     This function is    used process exceptions    under 2.x and to,    */
  2121. /*     depending on the    exception, provide a method of performing    */
  2122. /*     lazy pointer validation for the data types.            */
  2123. /*                                    */
  2124. /*     Upon Entry:                            */
  2125. /*                                    */
  2126. /*     PENTRYFWIN pefw;          =    Entry Field Private Data        */
  2127. /*     PSZ      pszInsText; =    Copy Buffer                */
  2128. /*                                    */
  2129. /*     Upon Exit:                            */
  2130. /*                                    */
  2131. /*     Nothing                                */
  2132. /*                                    */
  2133. /* --------------------------------------------------------------------    */
  2134.  
  2135. static VOID PasteText(PENTRYFWIN pefw, PSZ pszInsText, LONG cLen)
  2136.  
  2137. {
  2138. PSZ pszBuffer;               /* Text Buffer Pointer        */
  2139. EXCEPTIONREGISTRATIONRECORD xcptregr;       /* Exception    Record        */
  2140.  
  2141.                /* Register exception handler that is used for    */
  2142.                /* the lazy pointer validation tests        */
  2143.  
  2144. xcptregr.prev_structure      = NULL;
  2145. xcptregr.ExceptionHandler = &EntryFieldExceptionHandler;
  2146.  
  2147. DosSetExceptionHandler(&xcptregr);
  2148.  
  2149. if ( !setjmp(jBuf) )
  2150.    {
  2151.                /* Check    to see which text buffer should    be used    */
  2152.                /* since    the entry field    allows for unreadable    */
  2153.                /* display                    */
  2154.  
  2155.    if (    pefw->flStyle &    ES_UNREADABLE )
  2156.        pszBuffer = pefw->szPassword;
  2157.    else
  2158.        pszBuffer = pefw->szText;
  2159.  
  2160.                /* Check    to see if the insertion    point is before    */
  2161.                /* the end of the string                */
  2162.  
  2163.    if (    pefw->iSel < pefw->cText )
  2164.        {
  2165.                /* Text being inserted within the entry field    */
  2166.                /* string, open up exactly the space required    */
  2167.                /* to allow the new text    to be inserted        */
  2168.  
  2169.        memmove(&pszBuffer[pefw->iSel + cLen], &pszBuffer[pefw->iSel],
  2170.            (UINT)((pefw->cText + cLen) - pefw->iSel));
  2171.  
  2172.                /* Check    to see if a full string    is being    */
  2173.                /* inserted or just a character.     In either    */
  2174.                /* case,    insert the text    appropriately.        */
  2175.        if ( cLen > 1L )
  2176.        memmove(&pszBuffer[pefw->iSel], pszInsText, (UINT)cLen);
  2177.        else
  2178.        pszBuffer[pefw->iSel] = pszInsText[0];
  2179.  
  2180.                /* Update the insert selection point along with    */
  2181.                /* the text length                */
  2182.  
  2183.        pefw->iSel += cLen;
  2184.        pefw->cText += cLen;
  2185.        }
  2186.    else
  2187.        {
  2188.                /* Text being concatonated to the end of    the    */
  2189.                /* entry    field string, check to see which    */
  2190.                /* concatonation    method should be used        */
  2191.        if ( cLen > 1L )
  2192.        strncat(pszBuffer, pszInsText, (UINT)cLen + 1);
  2193.        else
  2194.        {
  2195.        pszBuffer[pefw->iSel] = pszInsText[0];
  2196.        pszBuffer[pefw->iSel    + 1L] =    0;
  2197.        }
  2198.                /* Update the insert selection point along with    */
  2199.                /* the text length                */
  2200.  
  2201.        pefw->iSel = pefw->cText    += cLen;
  2202.        }
  2203.                /* Update the selection indices            */
  2204.  
  2205.    pefw->iSelEnd = pefw->iSelStart = pefw->iAnchor = pefw->iSel;
  2206.  
  2207.                /* Insertion changes need to be redrawn,    place    */
  2208.                /* the colour table into    RGB mode and draw the    */
  2209.                /* revised text string within the entry field    */
  2210.                /* so as    to reflect the changes made        */
  2211.  
  2212.    GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
  2213.               0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  2214.  
  2215.                /* Calculate the    new display points for the text    */
  2216.                /* string                    */
  2217.    QueryCharPoints(pefw);
  2218.  
  2219.                /* Check    to see if the new cursor position will    */
  2220.                /* be outside the range of the entry field which    */
  2221.                /* means    that the text will need    to be scrolled    */
  2222.    if (    fScrollRight(pefw) )
  2223.        {
  2224.                /* Check    to see if the scrolling    is within    */
  2225.                /* limits, making sure that the scrolled    text    */
  2226.                /* is properly shown                */
  2227.  
  2228.        if ( (pefw->iOffset += pefw->cScroll) > pefw->cText )
  2229.        pefw->iOffset = pefw->cText;
  2230.        DrawText(pefw);
  2231.                /* Notify of the    owner of the entry field that    */
  2232.                /* the entry field was scrolled            */
  2233.  
  2234.        mrNotifyOwner(pefw, EN_SCROLL);
  2235.        }
  2236.    else
  2237.                /* No scrolling required, update    the text    */
  2238.                /* displayed within the entry field to reflect    */
  2239.                /* the text added                */
  2240.  
  2241.        DrawTextString(pefw, 0L,    pefw->cText, FALSE);
  2242.  
  2243.                /* Release the presentation space        */
  2244.    WinReleasePS(pefw->hPS);
  2245.  
  2246.                /* Inform the owner of the entry    field that a    */
  2247.                /* change in the    contents has occurred        */
  2248.  
  2249.    mrNotifyOwner(pefw, EN_CHANGE);
  2250.  
  2251.                /* Show the cursor in the new location to    */
  2252.                /* reflection the new insertion point        */
  2253.  
  2254.    ShowCursor(pefw, pefw->iSel);
  2255.    }
  2256.                /* Remove the exception handle since the    lazy    */
  2257.                /* pointer evaluation is    done            */
  2258.  
  2259. DosUnsetExceptionHandler(&xcptregr);
  2260. }
  2261.  
  2262. /************************************************************************/
  2263. /************************************************************************/
  2264. /*                                    */
  2265. /* Module Public Functions                        */
  2266. /*                                    */
  2267. /************************************************************************/
  2268. /************************************************************************/
  2269.  
  2270. #pragma    subtitle("   Entry Field Control - Entry Field Registration Procedure")
  2271. #pragma    page( )
  2272.  
  2273. /* --- fRegisterEntryField ----------------------------- [ Public ] ---    */
  2274. /*                                    */
  2275. /*     This function is    used to    register the Entry Field for the    */
  2276. /*     application with    PM.                        */
  2277. /*                                    */
  2278. /*     Upon Entry:                            */
  2279. /*                                    */
  2280. /*     HAB hAB;    = Anchor Block Handle                    */
  2281. /*                                    */
  2282. /*     Upon Exit:                            */
  2283. /*                                    */
  2284. /*     fRegisterEntryField =  TRUE : Entry Field Registration        */
  2285. /*                     Successfull            */
  2286. /*               = FALSE : Entry Field Registration Failed    */
  2287. /*                                    */
  2288. /* --------------------------------------------------------------------    */
  2289.  
  2290. BOOL EXPENTRY fRegisterEntryField(HAB hAB)
  2291.  
  2292. {
  2293.                /* Register the replace entry field class    */
  2294.  
  2295. if ( WinRegisterClass(hAB, "EntryFieldWindow", (PFNWP)EntryWndProc,
  2296.               CS_SYNCPAINT | CS_SIZEREDRAW | CS_PARENTCLIP | CS_CLIPCHILDREN,
  2297.               USER_RESERVED) )
  2298.    return(TRUE);
  2299. else
  2300.    return(FALSE);
  2301. }
  2302. #pragma    subtitle("   Entry Field Control - Entry Field Window Procedure")
  2303. #pragma    page( )
  2304.  
  2305. /* --- EntryWndProc ------------------------------------ [ Public ] ---    */
  2306. /*                                    */
  2307. /*     This function is    used to    process    the messages for the entry    */
  2308. /*     field control window.                        */
  2309. /*                                    */
  2310. /*     Upon Entry:                            */
  2311. /*                                    */
  2312. /*     HWND   hWnd; = Window Handle                    */
  2313. /*     ULONG  msg;  = PM Message                    */
  2314. /*     MPARAM mp1;  = Message Parameter    1                */
  2315. /*     MPARAM mp2;  = Message Parameter    2                */
  2316. /*                                    */
  2317. /*     Upon Exit:                            */
  2318. /*                                    */
  2319. /*     EntryWndProc = Message Handling Result                */
  2320. /*                                    */
  2321. /* --------------------------------------------------------------------    */
  2322.  
  2323. MRESULT    EXPENTRY EntryWndProc(HWND hWnd, ULONG msg, MPARAM mp1,    MPARAM mp2)
  2324.  
  2325. {
  2326. HHEAPMEM      hHeap;           /* Heap Handle            */
  2327. HWND          hwndHelp;           /* Help Window Handle        */
  2328. LONG          iSelCurrent;       /* Current Selection    Pointer        */
  2329. PCHAR          pchClipText;       /* Clipboard    Text Pointer        */
  2330. PCREATESTRUCT pcrst;           /* Create Structure Pointer        */
  2331. PENTRYFWIN    pefw;           /* Entry Field Internal Data    Pointer    */
  2332. POINTL          ptl;           /* Display Point            */
  2333. PSWP          pswp;           /* Size Window Position Pointer    */
  2334. PWNDPARAMS    pwprm;           /* Window Parameters    Pointer        */
  2335. RECTL          rclPaint;           /* Display Rectangle            */
  2336. ULONG          flStyle;           /* Style Flags            */
  2337. register LONG n;           /* Length Counter            */
  2338. EXCEPTIONREGISTRATIONRECORD xcptregr;       /* Exception    Record        */
  2339.  
  2340. switch ( msg )
  2341.    {
  2342.  
  2343. /************************************************************************/
  2344. /************************************************************************/
  2345. /*                                    */
  2346. /* Part    1: Control creation coding                    */
  2347. /*                                    */
  2348. /************************************************************************/
  2349. /************************************************************************/
  2350.  
  2351.    /*********************************************************************/
  2352.    /*  Control creation                            */
  2353.    /*********************************************************************/
  2354.  
  2355.    case    WM_CREATE :
  2356.                /* Allocate space for the internal control data    */
  2357.                /* as well as a small heap.  Save the address of    */
  2358.                /* the internal control data in the control's    */
  2359.                /* reserved memory to allow it to be referenced    */
  2360.                /* as required by the control.            */
  2361.  
  2362.        WinSetWindowPtr(hWnd, QUCWP_WNDP,
  2363.                (PVOID)(pefw = (PENTRYFWIN)HeapMalloc(hHeap = HeapAlloc(4096UL, 4096UL),
  2364.                                  sizeof(ENTRYFWIN))));
  2365.        pefw->hHeap = hHeap;
  2366.  
  2367.                /* Get the control's creation structure address  */
  2368.                /* to copy the relevant information such    as the    */
  2369.                /* size,    position and text of the control into    */
  2370.                /* the internal control data            */
  2371.  
  2372.        pcrst = (PCREATESTRUCT)PVOIDFROMMP(mp2);
  2373.  
  2374.                /* Save the owner and parent of the control so    */
  2375.                /* notification messages    can be sent back to    */
  2376.                /* the proper locations within the owning    */
  2377.                /* application                    */
  2378.  
  2379.        pefw->hAB    = WinQueryAnchorBlock(hWnd);
  2380.        pefw->hWnd    = hWnd;
  2381.        pefw->hwndOwner    = pcrst->hwndOwner;
  2382.        pefw->hwndParent    = pcrst->hwndParent;
  2383.        pefw->id        = pcrst->id;
  2384.  
  2385.        if ( pcrst->pszText )
  2386.        memcpy(pefw->szText,    pcrst->pszText,
  2387.           (UINT)((pefw->cText =    (LONG)strlen(pcrst->pszText)) +    1));
  2388.  
  2389.                /* Save the size    of the Entry Field along with    */
  2390.                /* the current style                */
  2391.  
  2392.        pefw->cx         = pcrst->cx;
  2393.        pefw->cy         = pcrst->cy;
  2394.        if ( (pefw->flStyle = pcrst->flStyle) & ES_READONLY )
  2395.        pefw->fReadOnly = TRUE;
  2396.  
  2397.                /* Get the default colours for the entry    field    */
  2398.  
  2399.        pefw->lClrText          = lGetPresParam(hWnd,    PP_FOREGROUNDCOLOR,
  2400.                           PP_FOREGROUNDCOLORINDEX,
  2401.                           SYSCLR_OUTPUTTEXT);
  2402.        pefw->lClrBorder          = lGetPresParam(hWnd,    PP_BORDERCOLOR,
  2403.                           PP_BORDERCOLORINDEX,
  2404.                           SYSCLR_BUTTONDARK);
  2405.        pefw->lClrBackground      = lGetPresParam(hWnd,    PP_BACKGROUNDCOLOR,
  2406.                           PP_BACKGROUNDCOLORINDEX,
  2407.                           SYSCLR_ENTRYFIELD);
  2408.        pefw->lClrHilite          = lGetPresParam(hWnd,    PP_HILITEFOREGROUNDCOLOR,
  2409.                           PP_HILITEFOREGROUNDCOLORINDEX,
  2410.                           SYSCLR_HILITEFOREGROUND);
  2411.        pefw->lClrHiliteBackground = lGetPresParam(hWnd,    PP_HILITEBACKGROUNDCOLOR,
  2412.                           PP_HILITEBACKGROUNDCOLORINDEX,
  2413.                           SYSCLR_HILITEBACKGROUND);
  2414.  
  2415.                /* Get the text pointer shape for use when the    */
  2416.                /* pointer is within the    confines of the    entry    */
  2417.                /* field    rectangle                */
  2418.  
  2419.        pefw->hptr = WinQuerySysPointer(HWND_DESKTOP, SPTR_TEXT,    FALSE);
  2420.  
  2421.                /* Get the font metrics to determine the    height    */
  2422.                /* and width of a character            */
  2423.  
  2424.        if ( pefw->cText    )
  2425.        pefw->iSel =    pefw->iSelStart    = pefw->iSelEnd    = pefw->iAnchor    = pefw->cText;
  2426.        pefw->hPS = WinGetPS(hWnd);
  2427.        RefreshMetrics(pefw);
  2428.        WinReleasePS(pefw->hPS);
  2429.  
  2430.                /* Calculate the    scroll rates            */
  2431.  
  2432.        pefw->ulScrollRateStart = WinQuerySysValue(HWND_DESKTOP,    SV_SCROLLRATE) * 4UL;
  2433.        pefw->ulScrollRate      = WinQuerySysValue(HWND_DESKTOP,    SV_SCROLLRATE) * 2UL;
  2434.  
  2435.                /* Determine the    current    insertion mode        */
  2436.  
  2437.        if ( !WinQuerySysValue(HWND_DESKTOP, SV_INSERTMODE) )
  2438.        pefw->fOvertype = TRUE;
  2439.  
  2440.                /* Decode the control data for the control    */
  2441.  
  2442.        DecodeCtlData(pefw, mp1);
  2443.        break;
  2444.  
  2445. /************************************************************************/
  2446. /************************************************************************/
  2447. /*                                    */
  2448. /* Part    2: Control activation                        */
  2449. /*                                    */
  2450. /************************************************************************/
  2451. /************************************************************************/
  2452.  
  2453.    /*********************************************************************/
  2454.    /*  Control being activated/deactivated                */
  2455.    /*********************************************************************/
  2456.  
  2457.    case    WM_ACTIVATE :
  2458.        if ( (hwndHelp =    WinQueryHelpInstance(hWnd)) != (HWND)NULL )
  2459.  
  2460.                /* When the window is being activated or        */
  2461.                /* deactivated, make sure that the control    */
  2462.                /* responds properly to help requests when it    */
  2463.                /* has the focus                    */
  2464.  
  2465.        if (    SHORT1FROMMP(mp1) )
  2466.            WinSendMsg(hwndHelp, HM_SET_ACTIVE_WINDOW,
  2467.               MPFROMHWND(WinQueryWindow(hWnd, QW_PARENT)),
  2468.               MPFROMHWND(WinQueryWindow(hWnd, QW_PARENT)));
  2469.        else
  2470.            WinSendMsg(hwndHelp, HM_SET_ACTIVE_WINDOW, 0L, 0L);
  2471.        break;
  2472.  
  2473.    /*********************************************************************/
  2474.    /*  Control receiving/losing    focus                    */
  2475.    /*********************************************************************/
  2476.  
  2477.    case    WM_SETFOCUS :
  2478.                /* Get the Entry    Field information pointer from    */
  2479.                /* the reserved memory of the window        */
  2480.  
  2481.        pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  2482.  
  2483.                /* When the window is being activated or        */
  2484.                /* deactivated, make sure that the control    */
  2485.                /* responds properly to help requests when it    */
  2486.                /* has the focus                    */
  2487.  
  2488.        if ( SHORT1FROMMP(mp2) )
  2489.        {
  2490.                /* Notify the owner of the Entry    Field that that    */
  2491.                /* Entry    Field is gaining focus            */
  2492.  
  2493.        mrNotifyOwner(pefw, EN_SETFOCUS);
  2494.        if (    !pefw->fFocus )
  2495.            {
  2496.                /* Check    to see if the insert mode has changed    */
  2497.                /* since    the last time the control received    */
  2498.                /* focus                        */
  2499.  
  2500.            if ( !WinQuerySysValue(HWND_DESKTOP, SV_INSERTMODE) )
  2501.            pefw->fOvertype = TRUE;
  2502.  
  2503.                /* Determine if some text has been selected    */
  2504.                /* within the entry field and if    the case add    */
  2505.                /* the highlighting                */
  2506.  
  2507.            if ( pefw->iSelStart != pefw->iSelEnd )
  2508.            {
  2509.            GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd), 0L,
  2510.                       LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  2511.            DrawText(pefw);
  2512.            WinReleasePS(pefw->hPS);
  2513.            }
  2514.                /* Create the cursor where the current insertion    */
  2515.                /* point    is                    */
  2516.  
  2517.            WinCreateCursor(hWnd, pefw->xCursor, pefw->yCursor,
  2518.                    0L, pefw->cyCursor, CURSOR_SOLID    | CURSOR_FLASH,    NULL);
  2519.            WinShowCursor(hWnd, pefw->fCursorShown =    TRUE);
  2520.            }
  2521.                /* Set the focus    flag                */
  2522.  
  2523.        pefw->fFocus    = TRUE;
  2524.        }
  2525.        else
  2526.                /* Focus    being lost, only update    internal flags    */
  2527.                /* if the control has received focus previously    */
  2528.  
  2529.        if (    pefw->fFocus )
  2530.            {
  2531.                /* Notify the owner of the entry    field that that    */
  2532.                /* entry    field is losing    focus            */
  2533.  
  2534.            mrNotifyOwner(pefw, EN_KILLFOCUS);
  2535.  
  2536.                /* Destroy the cursor                */
  2537.  
  2538.            WinDestroyCursor(hWnd);
  2539.  
  2540.                /* Clear    the focus flags                */
  2541.  
  2542.            pefw->fCursorShown = pefw->fFocus = FALSE;
  2543.  
  2544.                /* Determine if some text has been selected    */
  2545.                /* within the entry field and if    the case remove    */
  2546.                /* the highlighting                */
  2547.  
  2548.            if ( (pefw->iSelStart !=    pefw->iSelEnd) || pefw->fOvertype )
  2549.            {
  2550.            GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd), 0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  2551.            DrawText(pefw);
  2552.            WinReleasePS(pefw->hPS);
  2553.            }
  2554.            }
  2555.        break;
  2556.  
  2557. /************************************************************************/
  2558. /************************************************************************/
  2559. /*                                    */
  2560. /* Part    3: Control sizing                        */
  2561. /*                                    */
  2562. /************************************************************************/
  2563. /************************************************************************/
  2564.  
  2565.    /*********************************************************************/
  2566.    /*  Control changing    size or    position                */
  2567.    /*********************************************************************/
  2568.  
  2569.    case    WM_ADJUSTWINDOWPOS :
  2570.        pswp = (PSWP)PVOIDFROMMP(mp1);
  2571.        if ( (pswp->fl &    SWP_SIZE) && (pswp->cx > 0) && (pswp->cx > 0) )
  2572.  
  2573.                /* Get the address of the control info from the    */
  2574.                /* control's reserved memory and save the new    */
  2575.                /* size of the control                */
  2576.        {
  2577.        pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  2578.        pefw->cx = pswp->cx;
  2579.        pefw->cy = pswp->cy;
  2580.        if (    (pswp->cx > 0L)    && (pswp->cy > 0L) )
  2581.            SizeEntryField(pefw);
  2582.        }
  2583.        break;
  2584.  
  2585.    /*********************************************************************/
  2586.    /*  Convert position    query                        */
  2587.    /*********************************************************************/
  2588.  
  2589.    case    WM_QUERYCONVERTPOS :
  2590.        return(MRFROMLONG(QCP_NOCONVERT));
  2591.  
  2592.    /*********************************************************************/
  2593.    /*  Control changing    size                        */
  2594.    /*********************************************************************/
  2595.  
  2596.    case    WM_SIZE    :
  2597.                /* Get the address of the control info from the    */
  2598.                /* control's reserved memory and save the new    */
  2599.                /* size of the control                */
  2600.  
  2601.        pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  2602.        pefw->cx    = (LONG)(SHORT)SHORT1FROMMP(mp2);
  2603.        pefw->cy    = (LONG)(SHORT)SHORT2FROMMP(mp2);
  2604.        if ( ((LONG)(SHORT)SHORT1FROMMP(mp2) > 0L) &&
  2605.         ((LONG)(SHORT)SHORT2FROMMP(mp2) > 0L) )
  2606.        SizeEntryField(pefw);
  2607.        break;
  2608.  
  2609. /************************************************************************/
  2610. /************************************************************************/
  2611. /*                                    */
  2612. /* Part    3: Mouse interface                        */
  2613. /*                                    */
  2614. /************************************************************************/
  2615. /************************************************************************/
  2616.  
  2617.    /*********************************************************************/
  2618.    /*  Button 1    click                            */
  2619.    /*********************************************************************/
  2620.  
  2621.    case    WM_BUTTON1DOWN :
  2622.                /* Get the Entry    Field information pointer from    */
  2623.                /* the reserved memory of the window        */
  2624.  
  2625.        pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  2626.  
  2627.                /* Make sure that the entry field has focus    */
  2628.  
  2629.        if ( !pefw->fFocus )
  2630.        WinSetFocus(HWND_DESKTOP, hWnd);
  2631.  
  2632.                /* Check    to see if the entry field has any text    */
  2633.                /* before trying    to interprete the mouse        */
  2634.                /* position                    */
  2635.        if ( pefw->cText    )
  2636.        {
  2637.                /* Get the mouse    hot-spot and check to see if it    */
  2638.                /* is within the    bounds of the entry field    */
  2639.  
  2640.        ptl.x = (LONG)SHORT1FROMMP(mp1);
  2641.        ptl.y = (LONG)SHORT2FROMMP(mp1);
  2642.        if (    WinPtInRect(pefw->hAB, &pefw->rcl, &ptl) )
  2643.            {
  2644.                /* Mouse    hot-spot within    the entry field, set    */
  2645.                /* the mouse movement flags            */
  2646.  
  2647.            pefw->fScrollStart = pefw->fCapture = pefw->fBtnDown = TRUE;
  2648.  
  2649.                /* Locate the character where the mouse pointer    */
  2650.                /* has been clicked                */
  2651.  
  2652.            FINDCHARACTER((LONG)SHORT1FROMMP(mp1));
  2653.  
  2654.                /* Check    to see if the extended selection using    */
  2655.                /* the shift key    is being performed        */
  2656.  
  2657.            if ( !((ULONG)WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x0008000UL) )
  2658.            {
  2659.                /* Normal selection being performed, save the    */
  2660.                /* location where the mouse was clicked as being    */
  2661.                /* the new selection point            */
  2662.  
  2663.            pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = pefw->iSel;
  2664.  
  2665.                /* Get the presentation space for the entry    */
  2666.                /* field    and draw the changes made due to the    */
  2667.                /* button click                    */
  2668.  
  2669.            GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd), 0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  2670.            DrawText(pefw);
  2671.            WinReleasePS(pefw->hPS);
  2672.            }
  2673.            else
  2674.                /* Extended mouse selection being performed,    */
  2675.                /* select the text                */
  2676.  
  2677.            SelectText(pefw, pefw->iAnchor, pefw->iSel);
  2678.  
  2679.                /* Capture the mouse input while    the mouse    */
  2680.                /* is pressed to    make sure that the button    */
  2681.                /* release is registered    even if    the mouse    */
  2682.                /* pointer is outside the confines of the entry    */
  2683.                /* field                        */
  2684.  
  2685.            WinSetCapture(HWND_DESKTOP, hWnd);
  2686.  
  2687.                /* Display the mouse cursor in the new location    */
  2688.                /* as reflected by the mouse pointer position    */
  2689.  
  2690.            if ( pefw->fCursorShown )
  2691.            WinCreateCursor(hWnd, pefw->xCursor,    pefw->yCursor,
  2692.                    0L, 0L, CURSOR_SETPOS, NULL);
  2693.            }
  2694.        }
  2695.        return(MRFROMLONG(TRUE));
  2696.  
  2697.    /*********************************************************************/
  2698.    /*  Button 1    double click                        */
  2699.    /*********************************************************************/
  2700.  
  2701.    case    WM_BUTTON1DBLCLK :
  2702.                /* Get the entry    field information pointer from    */
  2703.                /* the reserved memory of the window        */
  2704.  
  2705.        pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  2706.        return(MRFROMLONG(TRUE));
  2707.  
  2708.    /*********************************************************************/
  2709.    /*  Button 1    released                        */
  2710.    /*********************************************************************/
  2711.  
  2712.    case    WM_BUTTON1UP :
  2713.                /* Get the entry    field information pointer from    */
  2714.                /* the reserved memory of the window        */
  2715.  
  2716.        pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  2717.  
  2718.                /* Check    to see if the mouse is being captured    */
  2719.                /* and if the case, release the capture        */
  2720.  
  2721.        if ( pefw->fCapture && (WinQueryCapture(HWND_DESKTOP) ==    hWnd) )
  2722.        {
  2723.        WinSetCapture(HWND_DESKTOP, (HWND)NULL);
  2724.        pefw->fCapture = FALSE;
  2725.        }
  2726.                /* Clear    the button down    flag now that the    */
  2727.                /* has been released                */
  2728.  
  2729.        pefw->fBtnDown =    FALSE;
  2730.  
  2731.                /* See if the scroll timer is active and    if the    */
  2732.                /* case,    stop it    since it is no longer required    */
  2733.  
  2734.        if ( pefw->fTimer )
  2735.        {
  2736.        pefw->fTimer    = FALSE;
  2737.        WinStopTimer(pefw->hAB, hWnd, TID_SCROLL);
  2738.        }
  2739.                /* Check    to see if in overtype mode in which    */
  2740.                /* case the overtype character needs to be    */
  2741.                /* displayed only if there is no    text selection    */
  2742.  
  2743.        if ( pefw->fOvertype && (pefw->iSelStart    == pefw->iSelEnd) )
  2744.        {
  2745.        GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
  2746.                   0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  2747.        DrawSubText(pefw, pefw->iSel, pefw->iSel + 1L);
  2748.        WinReleasePS(pefw->hPS);
  2749.        }
  2750.                /* Show the cursor in the new location        */
  2751.  
  2752.        ShowCursor(pefw,    pefw->iSel);
  2753.        return(MRFROMLONG(TRUE));
  2754.  
  2755.    /*********************************************************************/
  2756.    /*  Button 2    clicked                            */
  2757.    /*  Button 3    clicked                            */
  2758.    /*********************************************************************/
  2759.  
  2760.    case    WM_BUTTON2DOWN :
  2761.    case    WM_BUTTON2DBLCLK :
  2762.    case    WM_BUTTON3DOWN :
  2763.    case    WM_BUTTON3DBLCLK :
  2764.        WinSetActiveWindow(HWND_DESKTOP,    hWnd);
  2765.        break;
  2766.  
  2767.    /*********************************************************************/
  2768.    /* Process mouse movement over the entry field            */
  2769.    /*********************************************************************/
  2770.  
  2771.    case    WM_MOUSEMOVE :
  2772.                /* Get the entry    field information pointer from    */
  2773.                /* the reserved memory of the window        */
  2774.  
  2775.        pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  2776.  
  2777.                /* Send the WM_CONTROLPOINTER message to    the    */
  2778.                /* owner    of the control to allow    the owner of    */
  2779.                /* control to change the    pointer    shape from the    */
  2780.                /* current defined arrow    shape            */
  2781.  
  2782.        if ( WinIsWindowEnabled(hWnd) )
  2783.        WinSetPointer(HWND_DESKTOP,
  2784.              (HPOINTER)WinSendMsg(pefw->hwndOwner,
  2785.                           WM_CONTROLPOINTER,
  2786.                           MPFROMLONG(pefw->id),
  2787.                           MPFROMLONG(pefw->hptr)));
  2788.  
  2789.                /* Check    to see if the mouse left button    is    */
  2790.                /* depressed which means    the user is drag-    */
  2791.                /* selecting the    text within the    entry field    */
  2792.  
  2793.        if ( pefw->fBtnDown )
  2794.  
  2795.                /* Check    to see if any text contained within the    */
  2796.                /* entry    field.    When no    text in    the entry field    */
  2797.                /* the dragging should be ignored since there is    */
  2798.                /* nothing to select.                */
  2799.  
  2800.        if (    pefw->cText )
  2801.            {
  2802.                /* Check    to se if the mouse pointer is within    */
  2803.                /* the bounds of    the entry field    horizontally    */
  2804.                /* which    means the timer    scroll is no longer    */
  2805.                /* needed since the points can be mapped    with    */
  2806.                /* the current mouse pointer position        */
  2807.  
  2808.            if ( ((LONG)(SHORT)SHORT1FROMMP(mp1) >= pefw->rcl.xLeft)    &&
  2809.             ((LONG)(SHORT)SHORT1FROMMP(mp1) <= pefw->rcl.xRight) )
  2810.            {
  2811.                /* Check    to see if the scroll timer is being    */
  2812.                /* used and if the case,    turn it    off        */
  2813.  
  2814.            if (    pefw->fTimer )
  2815.                {
  2816.                WinStopTimer(pefw->hAB, hWnd, TID_SCROLL);
  2817.                pefw->fTimer = FALSE;
  2818.                }
  2819.            }
  2820.            else
  2821.                /* Mouse    pointer    is not within the horizontal    */
  2822.                /* bounds of the    entry field, turn on the scroll    */
  2823.                /* timer    only if    auto scrolling is specified for    */
  2824.                /* the control                    */
  2825.  
  2826.            if (    pefw->flStyle &    ES_AUTOSCROLL )
  2827.                {
  2828.                /* Start    the timer off slowly for the start of    */
  2829.                /* scrolling and    faster if scrolling has    already    */
  2830.                /* be started                    */
  2831.  
  2832.                WinStartTimer(pefw->hAB,    hWnd, TID_SCROLL,
  2833.                      pefw->fScrollStart    ? pefw->ulScrollRateStart : pefw->ulScrollRate);
  2834.                pefw->fTimer = TRUE;
  2835.                }
  2836.                /* Check    the current selected character against    */
  2837.                /* the recorded one and if different, reflect    */
  2838.                /* the selection    change and move    the cursor to    */
  2839.                /* the new location                */
  2840.  
  2841.            if ( (iSelCurrent = lFindCharacterIndex(pefw, (LONG)(SHORT)SHORT1FROMMP(mp1))) != pefw->iSel )
  2842.            {
  2843.            SelectText(pefw, pefw->iAnchor, iSelCurrent);
  2844.            FINDCHARACTER((LONG)(SHORT)SHORT1FROMMP(mp1));
  2845.            ShowCursor(pefw, pefw->iAnchor);
  2846.            }
  2847.            }
  2848.        return(MRFROMLONG(TRUE));
  2849.  
  2850.    /*********************************************************************/
  2851.    /* Process timer notification                    */
  2852.    /*********************************************************************/
  2853.  
  2854.    case    WM_TIMER :
  2855.                /* Check    to make    sure that the timer is the    */
  2856.                /* scroll timer for the entry field when    mouse    */
  2857.                /* capture has been started during the drag    */
  2858.                /* operation of the mouse and the mouse pointer    */
  2859.                /* is outside the entry field display area    */
  2860.  
  2861.        if ( SHORT1FROMMP(mp1) == TID_SCROLL )
  2862.        {
  2863.                /* Get the address of the control info from the    */
  2864.                /* control's reserved memory                     */
  2865.  
  2866.        pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  2867.  
  2868.                /* Get the current mouse    pointer    position    */
  2869.  
  2870.        WinQueryPointerPos(HWND_DESKTOP, &ptl);
  2871.  
  2872.                /* Convert the mouse pointer position, which is    */
  2873.                /* in desktop co-ordinates to the entry field    */
  2874.                /* co-ordinates                    */
  2875.  
  2876.        WinMapWindowPoints(HWND_DESKTOP, hWnd, &ptl,    1L);
  2877.  
  2878.                /* Check    to see if the mouse pointer is inside    */
  2879.                /* the display rectangle    in which case the timer    */
  2880.                /* should be stopped to allow the normal        */
  2881.                /* mouse    handling to be performed        */
  2882.  
  2883.        if (    WinPtInRect(pefw->hAB, &pefw->rcl, &ptl) )
  2884.            {
  2885.            pefw->fTimer = FALSE;
  2886.            WinStopTimer(pefw->hAB, hWnd, TID_SCROLL);
  2887.            }
  2888.        else
  2889.            {
  2890.                /* Check    to see if this is the starting of the    */
  2891.                /* timer    scrolling in which case    the scrolling    */
  2892.                /* rate should be made faster            */
  2893.  
  2894.            if ( pefw->fScrollStart )
  2895.            {
  2896.            if (    pefw->fTimer )
  2897.                {
  2898.                WinStopTimer(pefw->hAB, hWnd, TID_SCROLL);
  2899.                WinStartTimer(pefw->hAB,    hWnd, TID_SCROLL,
  2900.                      pefw->ulScrollRate);
  2901.                }
  2902.            pefw->fScrollStart =    FALSE;
  2903.            }
  2904.                /* Check    to see if the mouse pointer is to the    */
  2905.                /* right    of the entry field which means that    */
  2906.                /* scrolling is being performed from left to    */
  2907.                /* right                        */
  2908.  
  2909.            if ( ptl.x > pefw->rcl.xRight )
  2910.  
  2911.                /* Check    to see if there    is any text further to    */
  2912.                /* right    edge of    the entry field    that cannot be    */
  2913.                /* seen and should be scrolled            */
  2914.  
  2915.            if (    FALLOWSCROLLRIGHT(pefw)    )
  2916.                {
  2917.                /* Scrolling of text required, update the offset    */
  2918.                /* shift    factor making sure that    it does    not go    */
  2919.                /* beyond the end of the    text            */
  2920.  
  2921.                if ( (pefw->iOffset += pefw->cScroll) > pefw->cText )
  2922.                pefw->iOffset = pefw->cText;
  2923.  
  2924.                /* Update the selection end point making    sure    */
  2925.                /* that it does not go beyond the end of    the    */
  2926.                /* text                        */
  2927.  
  2928.                if ( (pefw->iSelEnd += pefw->cScroll) > pefw->cText )
  2929.                pefw->iSelEnd = pefw->cText;
  2930.  
  2931.                /* Get the presentation space handle for    the    */
  2932.                /* entry    field and place    the colour table into    */
  2933.                /* RGB mode before drawing the selected text    */
  2934.  
  2935.                GpiCreateLogColorTable(pefw->hPS    = WinGetPS(hWnd),
  2936.                           0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  2937.                DrawText(pefw);
  2938.                WinReleasePS(pefw->hPS);
  2939.  
  2940.                /* Inform the owner of the entry    field that the    */
  2941.                /* contents have    been scrolled            */
  2942.  
  2943.                mrNotifyOwner(pefw, EN_SCROLL);
  2944.  
  2945.                /* Move the cursor to the new location        */
  2946.  
  2947.                ShowCursor(pefw,    pefw->iAnchor);
  2948.                }
  2949.            else
  2950.                /* No scrolling required    but check to make sure    */
  2951.                /* the end selection point is shifted        */
  2952.  
  2953.                if ( pefw->iSelEnd < pefw->cText    )
  2954.                {
  2955.  
  2956.                /* Update the end point for the newly selected    */
  2957.                /* text                        */
  2958.  
  2959.                ++pefw->iSelEnd;
  2960.  
  2961.                /* Get the presentation space handle for    the    */
  2962.                /* entry    field and place    the colour table into    */
  2963.                /* RGB mode before drawing the selected text    */
  2964.  
  2965.                GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
  2966.                           0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  2967.                DrawText(pefw);
  2968.                WinReleasePS(pefw->hPS);
  2969.                ShowCursor(pefw, pefw->iAnchor);
  2970.                }
  2971.                else
  2972.  
  2973.                /* No further selection necessary, but make sure    */
  2974.                /* that the selection point is at the end of the    */
  2975.                /* selection field                */
  2976.  
  2977.                pefw->iSel =    pefw->iSelEnd;
  2978.            else
  2979.                /* Mouse    is to the left of the entry field,    */
  2980.                /* scrolling is being performed from the    right    */
  2981.                /* to left.  Check to make sure that further    */
  2982.                /* scrolling can    be permitted to    the left.    */
  2983.  
  2984.            if (    pefw->iOffset )
  2985.                {
  2986.                /* Scrolling of text required, update the offset    */
  2987.                /* shift    factor making sure that    it does    not go    */
  2988.                /* beyond the start of the text            */
  2989.  
  2990.                if ( (pefw->iOffset -= pefw->cScroll) < 0 )
  2991.                pefw->iOffset = 0L;
  2992.  
  2993.                /* Update the selection end point making    sure    */
  2994.                /* that it does not go beyond the start of the    */
  2995.                /* text                        */
  2996.  
  2997.                if ( (pefw->iSelStart -=    pefw->cScroll) < 0 )
  2998.                 pefw->iSelStart = 0L;
  2999.  
  3000.                /* Get the presentation space handle for    the    */
  3001.                /* entry    field and place    the colour table into    */
  3002.                /* RGB mode before drawing the selected text    */
  3003.  
  3004.                GpiCreateLogColorTable(pefw->hPS    = WinGetPS(hWnd),
  3005.                           0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  3006.                DrawText(pefw);
  3007.                WinReleasePS(pefw->hPS);
  3008.  
  3009.                /* Inform the owner of the entry    field that the    */
  3010.                /* contents have    been scrolled            */
  3011.  
  3012.                mrNotifyOwner(pefw, EN_SCROLL);
  3013.  
  3014.                /* Move the cursor to the new location        */
  3015.  
  3016.                ShowCursor(pefw,    pefw->iAnchor);
  3017.                }
  3018.            else
  3019.                pefw->iSel = pefw->iSelStart;
  3020.            }
  3021.        }
  3022.        else
  3023.                /* Check    to see if the timer is for the flashing    */
  3024.                /* of the cursor    in which case make sure    that    */
  3025.                /* the message gets through to the default    */
  3026.                /* window procedure otherwise it    will not flash    */
  3027.  
  3028.        if (    SHORT1FROMMP(mp1) == TID_CURSOR    )
  3029.            return(WinDefWindowProc(hWnd, msg, mp1, mp2));
  3030.        break;
  3031.  
  3032. /************************************************************************/
  3033. /************************************************************************/
  3034. /*                                    */
  3035. /* Part    4: Keyboard interface                        */
  3036. /*                                    */
  3037. /************************************************************************/
  3038. /************************************************************************/
  3039.  
  3040.  
  3041. /************************************************************************/
  3042. /************************************************************************/
  3043. /*                                    */
  3044. /************************************************************************/
  3045. /************************************************************************/
  3046. /*     The keystrokes processed    by an entry field control are:        */
  3047. /*                                    */
  3048. /*     Left arrow       Move    the cursor one character to the    left.    */
  3049. /*     Right arrow       Move    the cursor one character to the    right.    */
  3050. /*     Shift+Left arrow       Extend the selection    by one character to the    */
  3051. /*               left.                    */
  3052. /*     Shift+Right arrow   Extend the selection    by one character to the    */
  3053. /*               right.                    */
  3054. /*     Home           Move    the cursor to the beginning of the text.*/
  3055. /*     End           Move    the cursor to the end of the text.    */
  3056. /*     Backspace       Delete the character    to the left of the    */
  3057. /*               cursor.                    */
  3058. /*     Delete           When    the selection is an insertion point,    */
  3059. /*               delete the character    to the right of    the    */
  3060. /*               cursor, otherwise delete the    current        */
  3061. /*               selection, but do not put it    in the        */
  3062. /*               clipboard.                    */
  3063. /*     Shift+Del       Cut the current selection to    the clipboard.    */
  3064. /*     Shift+Ins       Replace the current selection with the text    */
  3065. /*               contents from the clipboard.            */
  3066. /*     Ctrl+Del           Delete to the end of    the field.        */
  3067. /*     Ctrl+Ins           Copy    the current selection to the clipboard.    */
  3068. /*                                    */
  3069. /*     If the control contains more text than can be shown, the        */
  3070. /*     actions defined above that move the cursor cause    the text to be    */
  3071. /*     scrolled. The amount of scrolling varies    from key to key, and    */
  3072. /*     the position of the text    within the control varies for the same    */
  3073. /*     cursor position.                            */
  3074. /************************************************************************/
  3075. /************************************************************************/
  3076. /*                                    */
  3077. /************************************************************************/
  3078. /************************************************************************/
  3079.  
  3080.  
  3081.    /*********************************************************************/
  3082.    /*  Key being pressed                        */
  3083.    /*********************************************************************/
  3084.  
  3085.                /* Keyboard character received            */
  3086.    case    WM_CHAR    :
  3087.                /* Only act on key down requests    therefore if a    */
  3088.                /* key up event,    ignore it            */
  3089.  
  3090.        if ( CHARMSG(&msg)->fs &    KC_KEYUP )
  3091.        break;
  3092.                /* Check    for virtual key    presses    first        */
  3093.  
  3094.        if ( CHARMSG(&msg)->fs &    KC_VIRTUALKEY )
  3095.        switch ( CHARMSG(&msg)->vkey    )
  3096.            {
  3097.  
  3098.            /*********************************************************/
  3099.            /*********************************************************/
  3100.            /*      Home                        */
  3101.            /*********************************************************/
  3102.            /*********************************************************/
  3103.  
  3104.            case VK_HOME :
  3105.  
  3106.                /* Get the entry    field data pointer from    the    */
  3107.                /* window                    */
  3108.  
  3109.            pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3110.  
  3111.                /* Check    to see if an offset shift being    used    */
  3112.                /* and if there is, set it along    with the    */
  3113.                /* selections to    the first character in the text    */
  3114.                /* string and redraw the    text in    the entry field    */
  3115.  
  3116.            if (    pefw->iOffset )
  3117.                {
  3118.                pefw->iOffset = pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = pefw->iSel = 0L;
  3119.  
  3120.                /* Get a    presentation space handle for the entry    */
  3121.                /* field, turn the colour table to RGB mode and    */
  3122.                /* redraw the entry field text            */
  3123.  
  3124.                GpiCreateLogColorTable(pefw->hPS    = WinGetPS(pefw->hWnd),
  3125.                           0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  3126.                DrawText(pefw);
  3127.                WinReleasePS(pefw->hPS);
  3128.                mrNotifyOwner(pefw, EN_SCROLL);
  3129.                }
  3130.            else
  3131.                /* No offset shift being    used, but check    to see    */
  3132.                /* if any text has been selected    in which case    */
  3133.                /* it needs to be deselected and    the selection    */
  3134.                /* placed at the    first character    in the text    */
  3135.                /* string forcing the text to be    redrawn    as well    */
  3136.  
  3137.                if ( pefw->iSelStart != pefw->iSelEnd )
  3138.                {
  3139.                pefw->iOffset = pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = pefw->iSel    = 0L;
  3140.  
  3141.                /* Get a    presentation space handle for the entry    */
  3142.                /* field, turn the colour table to RGB mode and    */
  3143.                /* redraw the entry field text            */
  3144.  
  3145.                GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
  3146.                           0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  3147.                DrawText(pefw);
  3148.                WinReleasePS(pefw->hPS);
  3149.                }
  3150.                else
  3151.  
  3152.                /* No shift offset or text is selected, just    */
  3153.                /* make sure that the cursor is at the beginning    */
  3154.                /* of the entry field                */
  3155.  
  3156.                pefw->iSel =    0L;
  3157.  
  3158.            ShowCursor(pefw, 0L);
  3159.            return(MRFROMLONG(TRUE));
  3160.  
  3161.            /*********************************************************/
  3162.            /*********************************************************/
  3163.            /*      End                        */
  3164.            /*********************************************************/
  3165.            /*********************************************************/
  3166.  
  3167.            case VK_END :
  3168.  
  3169.                /* Get the entry    field data pointer from    the    */
  3170.                /* window                    */
  3171.  
  3172.            pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3173.  
  3174.                /* Check    to see if the right part of the    text    */
  3175.                /* within the entry field is visible and    if it    */
  3176.                /* isn't, scroll the text to make it visible     */
  3177.  
  3178.            if (    pefw->aptl[pefw->cText].x > pefw->rclText.xRight )
  3179.                {
  3180.                /* Set the cursor selection point to be just    */
  3181.                /* after    the last character in the text string    */
  3182.  
  3183.                pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = pefw->iSel = pefw->cText;
  3184.  
  3185.                /* Determine the    offset value that should be    */
  3186.                /* used making sure that    it is within limits    */
  3187.  
  3188.                if ( (pefw->iOffset = pefw->cText - pefw->cScroll * 2L) < 0L )
  3189.                pefw->iOffset = 0L;
  3190.  
  3191.                /* Get a    presentation space handle for the entry    */
  3192.                /* field, turn the colour table to RGB mode and    */
  3193.                /* redraw the entry field text            */
  3194.  
  3195.                GpiCreateLogColorTable(pefw->hPS    = WinGetPS(pefw->hWnd),
  3196.                           0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  3197.                DrawText(pefw);
  3198.                WinReleasePS(pefw->hPS);
  3199.                mrNotifyOwner(pefw, EN_SCROLL);
  3200.                }
  3201.            else
  3202.                if ( pefw->iSelStart != pefw->iSelEnd )
  3203.                {
  3204.                pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = pefw->iSel    = pefw->cText;
  3205.                pefw->iOffset = 0L;
  3206.  
  3207.                /* Get a    presentation space handle for the entry    */
  3208.                /* field, turn the colour table to RGB mode and    */
  3209.                /* redraw the entry field text            */
  3210.  
  3211.                GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
  3212.                           0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  3213.                DrawText(pefw);
  3214.                WinReleasePS(pefw->hPS);
  3215.                }
  3216.                else
  3217.  
  3218.                /* No shift offset or text is selected, just    */
  3219.                /* make sure that the cursor is at the end of    */
  3220.                /* entry    field                    */
  3221.  
  3222.                pefw->iSel =    pefw->cText;
  3223.  
  3224.            ShowCursor(pefw, pefw->cText);
  3225.            return(MRFROMLONG(TRUE));
  3226.  
  3227.            /*********************************************************/
  3228.            /*********************************************************/
  3229.            /*      Backspace                    */
  3230.            /*********************************************************/
  3231.            /*********************************************************/
  3232.  
  3233.            case VK_BACKSPACE :
  3234.  
  3235.                /* Get the entry    field data pointer from    the    */
  3236.                /* window                    */
  3237.  
  3238.            pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3239.  
  3240.                /* Check    to see if the entry field is read-only    */
  3241.                /* which    means that any editing requests    have to    */
  3242.                /* be ignored                    */
  3243.  
  3244.            if (    pefw->fReadOnly    )
  3245.                return(MRFROMLONG(FALSE));
  3246.            else
  3247.                {
  3248.                /* Check    to see if any text has been selected    */
  3249.                /* which    in this    case, the backspace operates    */
  3250.                /* exactly like the Del key, only the selected    */
  3251.                /* text is deleted                */
  3252.  
  3253.                if ( pefw->iSelStart != pefw->iSelEnd )
  3254.                DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, TRUE);
  3255.                else
  3256.  
  3257.                /* No text has been selected, delete the        */
  3258.                /* character that reside    prior to the cursor    */
  3259.                /* location unless the cursor is    at the        */
  3260.                /* beginning of the text                */
  3261.  
  3262.                if (    pefw->iSel )
  3263.                    DeleteText(pefw,    pefw->iSel - 1,    pefw->iSel, TRUE);
  3264.  
  3265.                ShowCursor(pefw,    pefw->iSel);
  3266.                return(MRFROMLONG(TRUE));
  3267.                }
  3268.  
  3269.            /*********************************************************/
  3270.            /*********************************************************/
  3271.            /*      Del                        */
  3272.            /*      Ctrl+Del                        */
  3273.            /*      Shift+Del                    */
  3274.            /*********************************************************/
  3275.            /*********************************************************/
  3276.  
  3277.            case VK_DELETE :
  3278.  
  3279.                /* Get the entry    field data pointer from    the    */
  3280.                /* window                    */
  3281.  
  3282.            pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3283.  
  3284.                /* Check    to see if the entry field is read-only    */
  3285.                /* which    means that any editing requests    have to    */
  3286.                /* be ignored                    */
  3287.  
  3288.            if (    pefw->fReadOnly    )
  3289.                return(MRFROMLONG(FALSE));
  3290.            else
  3291.                {
  3292.                /* Check    to see if Ctrl+Del is being pressed,    */
  3293.                /* which    means that the text from the cursor    */
  3294.                /* position to the end of the text string should    */
  3295.                /* be deleted                    */
  3296.  
  3297.                if ( CHARMSG(&msg)->fs &    KC_CTRL    )
  3298.                DeleteText(pefw, pefw->iSelStart, pefw->cText, TRUE);
  3299.                else
  3300.  
  3301.                /* Check    to see if the Shift+Del    is being    */
  3302.                /* pressed, which is the    convention for cutting    */
  3303.                /* text from the    entry field            */
  3304.  
  3305.                if (    (CHARMSG(&msg)->fs & KC_SHIFT) &&
  3306.                 (pefw->iSelStart != pefw->iSelEnd) )
  3307.                    {
  3308.  
  3309.                /* Allocate the shared memory for the text    */
  3310.                /* making sure that there is enough memory for    */
  3311.                /* the text plus    the NULL terminating byte    */
  3312.  
  3313.                    DosAllocSharedMem((PPVOID)(PVOID)&pchClipText, NULL,
  3314.                          (ULONG)(pefw->iSelEnd -
  3315.                              pefw->iSelStart + 1),
  3316.                          fALLOCSHR);
  3317.  
  3318.                /* Open and empty the clipboard before copying    */
  3319.                /* the selected text to the shared memory    */
  3320.                /* and placing the pointer on the clipboard    */
  3321.  
  3322.                    WinOpenClipbrd(pefw->hAB);
  3323.                    WinEmptyClipbrd(pefw->hAB);
  3324.                    WinSetClipbrdData(pefw->hAB,
  3325.                          (ULONG)pszCopyText(pefw,
  3326.                                     pchClipText,
  3327.                                     pefw->iSelStart,
  3328.                                     pefw->iSelEnd),
  3329.                          CF_TEXT, CFI_POINTER);
  3330.  
  3331.                /* Close    the clipboard to allow the copied text    */
  3332.                /* to be    used by    other processes    as well    as this    */
  3333.                /* one                        */
  3334.  
  3335.                    WinCloseClipbrd(pefw->hAB);
  3336.  
  3337.                /* Delete the selected text            */
  3338.  
  3339.                    DeleteText(pefw,    pefw->iSelStart,
  3340.                       pefw->iSelEnd, TRUE);
  3341.                    }
  3342.                else
  3343.  
  3344.                /* Just the Del key is being pressed, check to    */
  3345.                /* see if any text is selected which is to be    */
  3346.                /* deleted                    */
  3347.  
  3348.                    if ( pefw->iSelStart != pefw->iSelEnd )
  3349.                    DeleteText(pefw, pefw->iSelStart,
  3350.                           pefw->iSelEnd, TRUE);
  3351.                    else
  3352.  
  3353.                /* No text has been selected, just delete the    */
  3354.                /* character immediately    to the right of    the    */
  3355.                /* cursor                    */
  3356.  
  3357.                    DeleteText(pefw, pefw->iSel,
  3358.                           pefw->iSel + 1, TRUE);
  3359.  
  3360.                ShowCursor(pefw,    pefw->iSel);
  3361.                return(MRFROMLONG(TRUE));
  3362.                }
  3363.  
  3364.            /*********************************************************/
  3365.            /*********************************************************/
  3366.            /*      Left                        */
  3367.            /*********************************************************/
  3368.            /*********************************************************/
  3369.  
  3370.            case VK_LEFT :
  3371.  
  3372.                /* Get the entry    field data pointer from    the    */
  3373.                /* window                    */
  3374.  
  3375.            pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3376.            if (    pefw->iSel )
  3377.                {
  3378.                if ( (pefw->aptl[--pefw->iSel].x    - pefw->aptl[pefw->iOffset].x) < EFMARGIN_LEFT )
  3379.                {
  3380.                if (    (pefw->iOffset -= pefw->cScroll) < 0L )
  3381.                    pefw->iOffset = 0L;
  3382.  
  3383.                /* Get a    presentation space handle for the entry    */
  3384.                /* field, turn the colour table to RGB mode and    */
  3385.                /* redraw the entry field text            */
  3386.  
  3387.                GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
  3388.                           0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  3389.                DrawText(pefw);
  3390.                WinReleasePS(pefw->hPS);
  3391.                mrNotifyOwner(pefw, EN_SCROLL);
  3392.                }
  3393.                else
  3394.                if (    pefw->fOvertype    && (pefw->iSelStart == pefw->iSelEnd) )
  3395.                    DrawOvertypeText(pefw, EFMOVE_LEFT);
  3396.                ShowCursor(pefw,    pefw->iSel);
  3397.                }
  3398.            return(MRFROMLONG(TRUE));
  3399.  
  3400.            /*********************************************************/
  3401.            /*********************************************************/
  3402.            /*      Right                        */
  3403.            /*********************************************************/
  3404.            /*********************************************************/
  3405.  
  3406.            case VK_RIGHT :
  3407.  
  3408.                /* Get the entry    field data pointer from    the    */
  3409.                /* window                    */
  3410.  
  3411.            pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3412.            if (    pefw->iSel < pefw->cText )
  3413.                {
  3414.                if ( (pefw->aptl[++pefw->iSel].x    - pefw->aptl[pefw->iOffset].x) > pefw->rclText.xRight )
  3415.                {
  3416.                if (    FALLOWSCROLLRIGHT(pefw)    )
  3417.                    {
  3418.                    if ( (pefw->iOffset += pefw->cScroll) > pefw->cText )
  3419.                    pefw->iOffset = pefw->cText;
  3420.  
  3421.                /* Get a    presentation space handle for the entry    */
  3422.                /* field, turn the colour table to RGB mode and    */
  3423.                /* redraw the entry field text            */
  3424.  
  3425.                    GpiCreateLogColorTable(pefw->hPS    = WinGetPS(pefw->hWnd),
  3426.                               0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  3427.                    DrawText(pefw);
  3428.                    WinReleasePS(pefw->hPS);
  3429.                    mrNotifyOwner(pefw, EN_SCROLL);
  3430.                    }
  3431.                }
  3432.                else
  3433.                if (    pefw->fOvertype    && (pefw->iSelStart == pefw->iSelEnd) )
  3434.                    DrawOvertypeText(pefw, EFMOVE_RIGHT);
  3435.                ShowCursor(pefw,    pefw->iSel);
  3436.                }
  3437.            return(MRFROMLONG(TRUE));
  3438.  
  3439.            /*********************************************************/
  3440.            /*********************************************************/
  3441.            /*      Ins                        */
  3442.            /*      Ctrl+Ins                        */
  3443.            /*      Shift+Ins                    */
  3444.            /*********************************************************/
  3445.            /*********************************************************/
  3446.  
  3447.            case VK_INSERT :
  3448.  
  3449.                /* Get the entry    field data pointer from    the    */
  3450.                /* window                    */
  3451.  
  3452.            pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3453.  
  3454.                /* Check    to make    sure that a selection within    */
  3455.                /* the text has been made before    trying to copy    */
  3456.                /* the selection    to the clipboard        */
  3457.  
  3458.            if (    (CHARMSG(&msg)->fs & KC_CTRL) &&
  3459.             (pefw->iSelEnd != pefw->iSelStart) )
  3460.                {
  3461.                /* Check    to see if the entry field is unreadable    */
  3462.                /* which    means that it is being used for    some-    */
  3463.                /* thing    like a password    entry area.  In    this    */
  3464.                /* case do not allow the    text to    be copied to    */
  3465.                /* the clipboard.  (Note:  this differs from    */
  3466.                /* the OS/2 entry field in that it will allow    */
  3467.                /* you to copy the text to the clipboard)    */
  3468.  
  3469.                if ( pefw->flStyle & ES_UNREADABLE )
  3470.                WinAlarm(HWND_DESKTOP, WA_ERROR);
  3471.                else
  3472.                {
  3473.  
  3474.                /* Allocate the shared memory for the text    */
  3475.                /* making sure that there is enough memory for    */
  3476.                /* the text plus    the NULL terminating byte    */
  3477.  
  3478.                DosAllocSharedMem((PPVOID)(PVOID)&pchClipText, NULL,
  3479.                          (ULONG)(pefw->iSelEnd - pefw->iSelStart + 1), fALLOCSHR);
  3480.  
  3481.                /* Open and empty the clipboard before copying    */
  3482.                /* the selected text to the shared memory    */
  3483.                /* and placing the pointer on the clipboard    */
  3484.  
  3485.                WinOpenClipbrd(pefw->hAB);
  3486.                WinEmptyClipbrd(pefw->hAB);
  3487.                WinSetClipbrdData(pefw->hAB,
  3488.                          (ULONG)pszCopyText(pefw, pchClipText, pefw->iSelStart, pefw->iSelEnd),
  3489.                          CF_TEXT, CFI_POINTER);
  3490.  
  3491.                /* Close    the clipboard to allow the copied text    */
  3492.                /* to be    used by    other processes    as well    as this    */
  3493.                /* one                        */
  3494.  
  3495.                WinCloseClipbrd(pefw->hAB);
  3496.                }
  3497.                }
  3498.            else
  3499.                /* Check    to see if the entry field is read-only    */
  3500.                /* which    means that any editing requests    have to    */
  3501.                /* be ignored                    */
  3502.  
  3503.                if ( (CHARMSG(&msg)->fs & KC_SHIFT) && !pefw->fReadOnly )
  3504.                {
  3505.  
  3506.                /* Open the clipboard and then check to see if    */
  3507.                /* any text has been placed on it that can be    */
  3508.                /* pasted within    the entry field            */
  3509.  
  3510.                WinOpenClipbrd(pefw->hAB);
  3511.                if (    WinQueryClipbrdData(pefw->hAB, CF_TEXT)    )
  3512.  
  3513.                /* Text contained within    the clipboard, get the    */
  3514.                /* pointer to the text                */
  3515.  
  3516.                    if ( (pchClipText = (PCHAR)WinQueryClipbrdData(pefw->hAB, CF_TEXT)) != NULL )
  3517.  
  3518.                /* Check    to make    sure that the selection    within    */
  3519.                /* the clipboard    will fit within    the entry field    */
  3520.  
  3521.                    if (    ((n = (LONG)strlen(pchClipText)) + pefw->cText -
  3522.                      (pefw->iSelEnd    - pefw->iSelStart)) < pefw->cLimit )
  3523.                        {
  3524.  
  3525.                /* Check    to see if any text is currently        */
  3526.                /* selected which means that the    text should be    */
  3527.                /* replaced by the text from the    clipboard.  If    */
  3528.                /* the case, delete the selected    text.        */
  3529.  
  3530.                        if ( pefw->iSelStart != pefw->iSelEnd )
  3531.                        DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, FALSE);
  3532.  
  3533.                /* Paste    the text into the entry    field at the    */
  3534.                /* current selection point            */
  3535.  
  3536.                        PasteText(pefw, pchClipText, n);
  3537.                        }
  3538.  
  3539.                /* Finished with    the clipboard, close it        */
  3540.  
  3541.                WinCloseClipbrd(pefw->hAB);
  3542.                }
  3543.                else
  3544.                {
  3545.                if (    pefw->fOvertype    )
  3546.                    {
  3547.                    pefw->fOvertype = FALSE;
  3548.                    if ( pefw->iSelStart == pefw->iSelEnd )
  3549.                    {
  3550.                    GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
  3551.                               0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  3552.                    DrawSubText(pefw, pefw->iSel, pefw->iSel + 1);
  3553.                    WinReleasePS(pefw->hPS);
  3554.                    }
  3555.                    }
  3556.                else
  3557.                    {
  3558.                    pefw->fOvertype = TRUE;
  3559.                    if ( pefw->iSelStart == pefw->iSelEnd )
  3560.                    {
  3561.                    GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
  3562.                               0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  3563.                    DrawSubText(pefw, pefw->iSel, pefw->iSel + 1);
  3564.                    WinReleasePS(pefw->hPS);
  3565.                    }
  3566.                mrNotifyOwner(pefw, EN_INSERTMODETOGGLE);
  3567.                }
  3568.                }
  3569.            return(WinDefWindowProc(hWnd, msg, mp1, mp2));
  3570.  
  3571.            /*********************************************************/
  3572.            /*********************************************************/
  3573.            /*      Down                        */
  3574.            /*      Up                        */
  3575.            /*********************************************************/
  3576.            /*********************************************************/
  3577.  
  3578.            case VK_DOWN :
  3579.            case VK_UP :
  3580.  
  3581.                /* Get the entry    field data pointer from    the    */
  3582.                /* window                    */
  3583.  
  3584.            pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3585.  
  3586.                /* Down or up arrow key pressed,    determine    */
  3587.                /* which    control    is the previous/next entry and    */
  3588.                /* set the focus    on that    control            */
  3589.  
  3590.            WinSetFocus(HWND_DESKTOP,
  3591.                    WinEnumDlgItem(pefw->hwndOwner, hWnd,
  3592.                           (ULONG)(CHARMSG(&msg)->vkey == VK_DOWN ?
  3593.                               EDI_NEXTGROUPITEM    :
  3594.                               EDI_PREVGROUPITEM)));
  3595.            return(MRFROMLONG(TRUE));
  3596.  
  3597.            /*********************************************************/
  3598.            /*********************************************************/
  3599.            /*      Tab                        */
  3600.            /*      Shift+Tab                    */
  3601.            /*********************************************************/
  3602.            /*********************************************************/
  3603.  
  3604.            case VK_TAB :
  3605.            case VK_BACKTAB :
  3606.  
  3607.                /* Get the entry    field data pointer from    the    */
  3608.                /* window                    */
  3609.  
  3610.            pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3611.  
  3612.                /* TAB or Shift+TAB key pressed,    determine which    */
  3613.                /* control is the previous/next tab stop    and set    */
  3614.                /* the focus on that control            */
  3615.  
  3616.            WinSetFocus(HWND_DESKTOP,
  3617.                    WinEnumDlgItem(pefw->hwndOwner, hWnd,
  3618.                           (ULONG)(CHARMSG(&msg)->vkey == VK_TAB ?
  3619.                               EDI_NEXTTABITEM :
  3620.                               EDI_PREVTABITEM)));
  3621.            return(MRFROMLONG(TRUE));
  3622.            }
  3623.        else
  3624.                /* Process normal character input        */
  3625.  
  3626.        if (    CHARMSG(&msg)->fs & KC_CHAR )
  3627.            {
  3628.                /* Get the entry    field data pointer from    the    */
  3629.                /* window                    */
  3630.  
  3631.            pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3632.  
  3633.                /* Check    to see if the entry field is read-only    */
  3634.                /* which    means that any editing requests    have to    */
  3635.                /* be ignored                    */
  3636.  
  3637.            if ( pefw->fReadOnly )
  3638.            return(MRFROMLONG(FALSE));
  3639.            else
  3640.            {
  3641.                /* Check    to see if the entry field input    limit    */
  3642.                /* has been met in which    case the keystroke    */
  3643.                /* should simply    be discarded if    the owner of    */
  3644.                /* control does not return a TRUE response to    */
  3645.                /* the overflow notification            */
  3646.  
  3647.            if (    pefw->cText >= pefw->cLimit )
  3648.                if ( LONGFROMMR(mrNotifyOwner(pefw, EN_OVERFLOW)) == TRUE )
  3649.                {
  3650.                if (    pefw->cText >= pefw->cLimit )
  3651.                    {
  3652.                    WinAlarm(HWND_DESKTOP, WA_ERROR);
  3653.                    return(MRFROMLONG(TRUE));
  3654.                    }
  3655.                }
  3656.                else
  3657.                {
  3658.                WinAlarm(HWND_DESKTOP, WA_ERROR);
  3659.                return(MRFROMLONG(TRUE));
  3660.                }
  3661.  
  3662.                /* Check    to see if any text has been selected    */
  3663.                /* which    means that the selected    text is        */
  3664.                /* to be    replaced with the keystroke character    */
  3665.  
  3666.            if (    pefw->iSelStart    != pefw->iSelEnd )
  3667.                DeleteText(pefw,    pefw->iSelStart, pefw->iSelEnd,
  3668.                   FALSE);
  3669.            else
  3670.                /* No preselected text, now check to see    if the    */
  3671.                /* entry    field is in overtype mode which    means    */
  3672.                /* that the character immediately to the    right    */
  3673.                /* of the cursor    is to be replaced with the    */
  3674.                /* keystroke character                */
  3675.  
  3676.                if ( pefw->fOvertype && (pefw->iSel < pefw->cText) )
  3677.                DeleteText(pefw, pefw->iSel,    pefw->iSel + 1L,
  3678.                       FALSE);
  3679.  
  3680.                /* Save the keystroke within the    text buffer    */                
  3681.                /* and then insert the text into    the entry    */
  3682.                /* field                        */
  3683.  
  3684.            pefw->szInput[0] = (BYTE)CHARMSG(&msg)->chr;
  3685.            PasteText(pefw, pefw->szInput, 1L);
  3686.  
  3687.                /* Check    to see if the text limit has been    */
  3688.                /* reached in which case    the auto tab style    */
  3689.                /* should be checked for    and if present,    cause    */
  3690.                /* the focus to move from the entry field to the    */
  3691.                /* next tabable control                */
  3692.  
  3693.            if (    (pefw->flStyle & ES_AUTOTAB) &&
  3694.             (pefw->cText ==    pefw->cLimit) )
  3695.                WinSetFocus(HWND_DESKTOP,
  3696.                    WinEnumDlgItem(pefw->hwndOwner, hWnd,
  3697.                           EDI_NEXTTABITEM));
  3698.            return(MRFROMLONG(TRUE));
  3699.            }
  3700.            }
  3701.        return(WinDefWindowProc(hWnd, msg, mp1, mp2));
  3702.  
  3703. /************************************************************************/
  3704. /************************************************************************/
  3705. /*                                    */
  3706. /* Part    5: Control messages                        */
  3707. /*                                    */
  3708. /************************************************************************/
  3709. /************************************************************************/
  3710.  
  3711.    /*********************************************************************/
  3712.    /*  Base messages                            */
  3713.    /*********************************************************************/
  3714.  
  3715.    case    EM_QUERYCHANGED    :
  3716.    case    EM_QUERYSEL :
  3717.    case    EM_SETSEL :
  3718.    case    EM_SETTEXTLIMIT    :
  3719.    case    EM_CUT :
  3720.    case    EM_COPY    :
  3721.    case    EM_CLEAR :
  3722.    case    EM_PASTE :
  3723.    case    EM_QUERYFIRSTCHAR :
  3724.    case    EM_SETFIRSTCHAR    :
  3725.    case    EM_QUERYREADONLY :
  3726.    case    EM_SETREADONLY :
  3727.    case    EM_SETINSERTMODE :
  3728.        mrBaseFieldHandler(hWnd,    msg, mp1, mp2);
  3729.        break;
  3730.  
  3731.    /*********************************************************************/
  3732.    /*  Extended    messages                        */
  3733.    /*********************************************************************/
  3734.  
  3735. /************************************************************************/
  3736. /************************************************************************/
  3737. /*                                    */
  3738. /* Part    6: Text    manipulation                        */
  3739. /*                                    */
  3740. /************************************************************************/
  3741. /************************************************************************/
  3742.  
  3743.    /*********************************************************************/
  3744.    /*  Process window parameters query                    */
  3745.    /*********************************************************************/
  3746.  
  3747.    case    WM_QUERYWINDOWPARAMS :
  3748.  
  3749.                /* Get the address for the windows parameters    */
  3750.                /* structure                    */
  3751.  
  3752.        if ( (pwprm = (PWNDPARAMS)PVOIDFROMMP(mp1)) != NULL )
  3753.        {
  3754.  
  3755.                /* Register exception handler that is used for    */
  3756.                /* the lazy pointer validation tests        */
  3757.  
  3758.        xcptregr.prev_structure   = NULL;
  3759.        xcptregr.ExceptionHandler = &EntryFieldExceptionHandler;
  3760.  
  3761.        DosSetExceptionHandler(&xcptregr);
  3762.  
  3763.        if (    !setjmp(jBuf) )
  3764.            {
  3765.                /* Text length being asked for, get the address    */
  3766.                /* of the text string stored in the heap        */
  3767.  
  3768.            pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3769.  
  3770.                /* Determine the    type of    query            */
  3771.  
  3772.            if ( pwprm->fsStatus & WPM_TEXT )
  3773.            {
  3774.  
  3775.            if (    pefw->flStyle &    ES_UNREADABLE )
  3776.                memcpy(pwprm->pszText, pefw->szPassword,    (UINT)pefw->cText);
  3777.            else
  3778.                memcpy(pwprm->pszText, pefw->szText, (UINT)pefw->cText);
  3779.            pefw->fChanged = FALSE;
  3780.            }
  3781.  
  3782.            if ( pwprm->fsStatus & WPM_CCHTEXT )
  3783.            {
  3784.                /* Place    the length the string within the    */
  3785.                /* structure                    */
  3786.  
  3787.            pwprm->cchText = (ULONG)pefw->cText;
  3788.            pefw->fChanged = FALSE;
  3789.            }
  3790.  
  3791.            if ( pwprm->fsStatus & WPM_CBCTLDATA )
  3792.            {
  3793.  
  3794.                /* Set the control data length to zero        */
  3795.  
  3796.            pwprm->cbCtlData = 0;
  3797.            pefw->fChanged = FALSE;
  3798.            }
  3799.            }
  3800.                /* Remove the exception handle since the    lazy    */
  3801.                /* pointer evaluation is    done            */
  3802.  
  3803.        DosUnsetExceptionHandler(&xcptregr);
  3804.        return(MRFROMLONG(TRUE));
  3805.        }
  3806.        break;
  3807.                /* Process window parameters setting        */
  3808.  
  3809.    case    WM_SETWINDOWPARAMS :
  3810.  
  3811.                /* Get the address for the windows parameters    */
  3812.                /* structure                    */
  3813.  
  3814.        if ( (pwprm = (PWNDPARAMS)PVOIDFROMMP(mp1)) != NULL )
  3815.        {
  3816.  
  3817.                /* Register exception handler that is used for    */
  3818.                /* the lazy pointer validation tests        */
  3819.  
  3820.        xcptregr.prev_structure   = NULL;
  3821.        xcptregr.ExceptionHandler = &EntryFieldExceptionHandler;
  3822.  
  3823.        DosSetExceptionHandler(&xcptregr);
  3824.  
  3825.        if (    !setjmp(jBuf) )
  3826.            {
  3827.  
  3828.                /* Check    to see if the text for the control is    */
  3829.                /* being    set                    */
  3830.  
  3831.            if ( pwprm->fsStatus & WPM_TEXT )
  3832.            {
  3833.                /* Text being set, get the address of the text    */
  3834.                /* string stored    in the heap            */
  3835.  
  3836.            pefw    = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3837.  
  3838.                /* Check    to see if any text is being set        */
  3839.  
  3840.            if (    pwprm->cchText )
  3841.  
  3842.                /* Check    to make    sure that the text that    is to    */
  3843.                /* be set is not    greater    than the memory        */
  3844.                /* allocated                    */
  3845.  
  3846.                if ( pwprm->cchText > 1023UL )
  3847.                {
  3848.                memcpy(pefw->szText,    pwprm->pszText,    1023);
  3849.                pefw->szText[pefw->cText = 1023] = 0;
  3850.                }
  3851.                else
  3852.                {
  3853.                memcpy(pefw->szText,    pwprm->pszText,    pwprm->cchText);
  3854.                pefw->szText[pefw->cText = (LONG)pwprm->cchText] = 0;
  3855.                }
  3856.            else
  3857.                /* No text is being set,    clear any existing text    */
  3858.  
  3859.                pefw->szText[pefw->cText    = 0L] =    0;
  3860.  
  3861.            GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
  3862.                       0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
  3863.            QueryCharPoints(pefw);
  3864.            DrawText(pefw);
  3865.            WinReleasePS(pefw->hPS);
  3866.  
  3867.            mrNotifyOwner(pefw, EN_CHANGE);
  3868.            }
  3869.            }
  3870.                /* Remove the exception handle since the    lazy    */
  3871.                /* pointer evaluation is    done            */
  3872.  
  3873.        DosUnsetExceptionHandler(&xcptregr);
  3874.        }
  3875.        break;
  3876.  
  3877. /************************************************************************/
  3878. /************************************************************************/
  3879. /*                                    */
  3880. /* Part    7: Painting and    display                        */
  3881. /*                                    */
  3882. /************************************************************************/
  3883. /************************************************************************/
  3884.  
  3885.    /*********************************************************************/
  3886.    /*  System colour/Presentation parameter change            */
  3887.    /*********************************************************************/
  3888.  
  3889.    case    WM_SYSCOLORCHANGE :
  3890.    case    WM_PRESPARAMCHANGED :
  3891.  
  3892.                /* Get the Entry    Field data pointer from    the window */
  3893.  
  3894.        pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3895.  
  3896.                /* Presentation parameters or system colours    */
  3897.                /* have changed,    get the    new values for the    */
  3898.                /* colours                    */
  3899.  
  3900.        pefw->lClrText          = lGetPresParam(hWnd,    PP_FOREGROUNDCOLOR,
  3901.                           PP_FOREGROUNDCOLORINDEX,
  3902.                           SYSCLR_OUTPUTTEXT);
  3903.        pefw->lClrBorder          = lGetPresParam(hWnd,    PP_BORDERCOLOR,
  3904.                           PP_BORDERCOLORINDEX,
  3905.                           SYSCLR_BUTTONDARK);
  3906.        pefw->lClrBackground      = lGetPresParam(hWnd,    PP_BACKGROUNDCOLOR,
  3907.                           PP_BACKGROUNDCOLORINDEX,
  3908.                           SYSCLR_ENTRYFIELD);
  3909.        pefw->lClrHilite          = lGetPresParam(hWnd,    PP_HILITEFOREGROUNDCOLOR,
  3910.                           PP_HILITEFOREGROUNDCOLORINDEX,
  3911.                           SYSCLR_HILITEFOREGROUND);
  3912.        pefw->lClrHiliteBackground = lGetPresParam(hWnd,    PP_HILITEBACKGROUNDCOLOR,
  3913.                           PP_HILITEBACKGROUNDCOLORINDEX,
  3914.                           SYSCLR_HILITEBACKGROUND);
  3915.  
  3916.                /* Refresh the metrics for the control        */
  3917.  
  3918.        pefw->hPS = WinGetPS(hWnd);
  3919.        RefreshMetrics(pefw);
  3920.        WinReleasePS(pefw->hPS);
  3921.  
  3922.                /* Cause    the control to be repainted if it is    */
  3923.                /* visible                    */
  3924.  
  3925.        if ( WinIsWindowShowing(hWnd) )
  3926.        WinInvalidateRect(hWnd, &pefw->rcl, FALSE);
  3927.        break;
  3928.  
  3929.    /*********************************************************************/
  3930.    /*  Paint control                            */
  3931.    /*********************************************************************/
  3932.  
  3933.    case    WM_PAINT :
  3934.                /* Get the address of the control info from the    */
  3935.                /* control's reserved memory                     */
  3936.  
  3937.        pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  3938.  
  3939.                /* Set the colour table to RGB mode        */
  3940.  
  3941.        if ( (pefw->hPS = WinBeginPaint(hWnd, (HPS)NULL,    &rclPaint)) != (HPS)NULL )
  3942.        {    
  3943.                /* Check    to see if a style change has occurred    */
  3944.                /* and if the case, save    the new    style        */
  3945.                /* internally and refresh the control metrics    */
  3946.  
  3947.        if (    ((flStyle = WinQueryWindowULong(hWnd, QWL_STYLE)) &
  3948.           0x0000ffffUL)    != (pefw->flStyle & 0x0000ffffUL) )
  3949.            {
  3950.            pefw->flStyle = flStyle;
  3951.            RefreshMetrics(pefw);
  3952.            }
  3953.                /* Place    the colour table into RGB mode        */
  3954.  
  3955.        GpiCreateLogColorTable(pefw->hPS, 0L, LCOLF_RGB, 0L,    0L, (PLONG)NULL);
  3956.  
  3957.                /* Erase    the rectangle for the control        */
  3958.  
  3959.        WinFillRect(pefw->hPS, &pefw->rcl, pefw->lClrBackground);
  3960.  
  3961.                /* Check    to see if a margin for the entry field    */
  3962.                /* is desired and if so,    draw it            */
  3963.  
  3964.        if (    pefw->flStyle &    ES_MARGIN )
  3965.            {
  3966.                /* First    set the    colour of the border and then    */
  3967.                /* draw the inside edge of the border.  The    */
  3968.                /* border follows the typical 3D    effect of    */
  3969.                /* one line being dark and the second line being    */
  3970.                /* light.                    */
  3971.  
  3972.            GpiSetColor(pefw->hPS, RGB_WHITE);
  3973.            GpiMove(pefw->hPS, pefw->aptlInside);
  3974.            GpiPolyLine(pefw->hPS, 4L, &pefw->aptlInside[1]);
  3975.  
  3976.                /* Having drawn the inside edge,    now draw the    */
  3977.                /* outside edge of the border            */
  3978.  
  3979.            GpiSetColor(pefw->hPS, pefw->lClrBorder);
  3980.            GpiMove(pefw->hPS, pefw->aptlOutside);
  3981.            GpiPolyLine(pefw->hPS, 4L, &pefw->aptlOutside[1]);
  3982.            }
  3983.                /* Check    to see if any text needs to be drawn    */
  3984.                /* and if present, draw it            */
  3985.  
  3986.        if (    pefw->szText[0]    )
  3987.            DrawText(pefw);
  3988.  
  3989.        WinEndPaint(pefw->hPS);
  3990.        }
  3991.        break;
  3992.  
  3993. /************************************************************************/
  3994. /************************************************************************/
  3995. /*                                    */
  3996. /* Part    8: Control destruction coding                    */
  3997. /*                                    */
  3998. /************************************************************************/
  3999. /************************************************************************/
  4000.  
  4001.    /*********************************************************************/
  4002.    /*  Control being destroyed,    perform    clean-up            */
  4003.    /*********************************************************************/
  4004.  
  4005.    case    WM_DESTROY :
  4006.                /* Get the address of the control info from the    */
  4007.                /* control's reserved memory and release the     */
  4008.                /* heap.                        */
  4009.  
  4010.        pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
  4011.        HeapRelease(pefw->hHeap);
  4012.        break;
  4013.                /* Default message processing            */
  4014.    default :
  4015.        return(WinDefWindowProc(hWnd, msg, mp1, mp2));
  4016.    }
  4017. return(0L);
  4018. }
  4019.