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

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