home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
lstbx4.zip
/
EntryFld.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-05
|
149KB
|
4,168 lines
#pragma title("List Box Replacement -- Version 1.2 -- (EntryFld.C)")
#pragma subtitle(" Entry Field Control - Interface Definitions")
/* Program name: Listbox.C Title: A Entry Field Replacement */
/* */
/* OS/2 Developer Magazine, Issue: July '94 GUI Corner */
/* Author: Mark Benge IBM Corp. */
/* Matt Smith Prominare Inc. */
/* Description: Replacement for OS/2 List Box, third of a series. */
/* */
/* Program Requirements: OS/2 2.x */
/* IBM C Set/2 */
/* WATCOM C 386/9.0 */
/* Borland C++ for OS/2 */
/* OS/2 Toolkit */
/* Copyright ╕ International Business Machines Corp. 1991-1994 */
/* Copyright ╕ 1989-1994 Prominare Inc. All Rights Reserved. */
/************************************************************************/
/************************************************************************/
/* SPECIAL NOTE */
/************************************************************************/
/************************************************************************/
/* The behaviour of this control is similar to that provided */
/* by OS/2 PM. Although it may be based on documentation */
/* describing programming interfaces and techniques, it should */
/* not be misconstrued that this sample code is an official */
/* release of the OS/2 PM control and is supported as such. */
/************************************************************************/
/************************************************************************/
/************************************************************************/
/************************************************************************/
/* DISCLAIMER OF WARRANTIES. */
/************************************************************************/
/************************************************************************/
/* The following [enclosed] code is source code created by the */
/* authors. This source code is provided to you solely */
/* for the purpose of assisting you in the development of your */
/* applications. The code is provided "AS IS", without */
/* warranty of any kind. The authors shall not be liable */
/* for any damages arising out of your use of the source code, */
/* even if they have been advised of the possibility of such */
/* damages. It is provided purely for instructional and */
/* illustrative purposes. */
/************************************************************************/
/************************************************************************/
#pragma info(noext)
#pragma strings(readonly)
#define INCL_DOS /* Include OS/2 DOS Kernal */
#define INCL_GPI /* Include OS/2 PM GPI Interface */
#define INCL_WIN /* Include OS/2 PM Windows Interface */
#include <os2.h>
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#include "entryfld.h"
#include "listbox.h"
/* This module contains the common routines used by the Entry Field */
/* along with the window procedure for the Entry Field. */
/* */
/* Equivalent command line invocation of each module using the */
/* IBM C Set++ Compiler Version 2.0 is: */
/* */
/* Icc -G3e- -O+ -Rn -C -W3 -FoEntryfld Entryfld.C */
/* Filename: Entryfld.C */
/* Version: 1.0 */
/* Created: 1994-03-03 */
/* Revised: 1994-07-03 */
/* Routines: static LONG lGetPresParam(HWND hWnd, ULONG ulID1, */
/* ULONG ulID2, LONG lDefault); */
/* static VOID SizeEntryField(PENTRYFWIN pefw); */
/* static VOID QueryCharPoints(PENTRYFWIN pefw); */
/* static LONG lFindCharacterIndex(PENTRYFWIN pefw, */
/* LONG xClick); */
/* static LONG lCalcDisplayPoint(PENTRYFWIN pefw, */
/* LONG iChar); */
/* static BOOL fScrollRight(PENTRYFWIN pefw); */
/* static VOID ShowCursor(PENTRYFWIN pefw, LONG iSel); */
/* static VOID DrawOvertype(PENTRYFWIN pefw); */
/* static VOID DrawTextString(PENTRYFWIN pefw, LONG iStart, */
/* LONG iEnd, BOOL fHighlighted);*/
/* static VOID DrawText(PENTRYFWIN pefw); */
/* static VOID DrawSubText(PENTRYFWIN pefw, LONG iStart, */
/* LONG iEnd); */
/* static VOID DrawOvertypeText(PENTRYFWIN pefw, */
/* BOOL fMoveRight); */
/* static VOID SelectText(PENTRYFWIN pefw, LONG iAnchor, */
/* LONG iSelected); */
/* static VOID RefreshMetrics(PENTRYFWIN pefw); */
/* static VOID DecodeCtlData(PENTRYFWIN pefw, MPARAM mp1); */
/* MRESULT EXPENTRY mrBaseFieldHandler(HWND hWnd, ULONG msg,*/
/* MPARAM mp1, */
/* MPARAM mp2); */
/* APIRET APIENTRY EntryFieldExceptionHandler( */
/* PEXCEPTIONREPORTRECORD pxcptrepr, */
/* PEXCEPTIONREGISTRATIONRECORD pxcptregr, */
/* PCONTEXTRECORD pcr, PVOID sysinfo); */
/* static VOID DeleteText(PENTRYFWIN pefw, LONG iSelStart, */
/* LONG iSelEnd, BOOL fRedraw); */
/* static PSZ pszCopyText(PENTRYFWIN pefw, PSZ pszBuffer, */
/* LONG iSelStart, LONG iSelEnd); */
/* static VOID PasteText(PENTRYFWIN pefw, PSZ pszInsText, */
/* LONG cLen); */
/* BOOL EXPENTRY fRegisterEntryField(HAB hAB); */
/* MRESULT EXPENTRY EntryWndProc(HWND hWnd, ULONG msg, */
/* MPARAM mp1, MPARAM mp2); */
/* -------------------------------------------------------------------- */
/************************************************************************/
/* */
/* Standard Entry Field Styles */
/* */
/* ES_LEFT 0x00000000L */
/* ES_CENTER 0x00000001L */
/* ES_RIGHT 0x00000002L */
/* ES_AUTOSCROLL 0x00000004L */
/* ES_MARGIN 0x00000008L */
/* ES_AUTOTAB 0x00000010L */
/* ES_READONLY 0x00000020L */
/* ES_COMMAND 0x00000040L */
/* ES_UNREADABLE 0x00000080L */
/* ES_AUTOSIZE 0x00000200L */
/* ES_ANY 0x00000000L */
/* ES_SBCS 0x00001000L */
/* ES_DBCS 0x00002000L */
/* ES_MIXED 0x00003000L */
/* */
/* Standard Entry Field notification messages */
/* */
/* EN_SETFOCUS 0x0001 */
/* EN_KILLFOCUS 0x0002 */
/* EN_CHANGE 0x0004 */
/* EN_SCROLL 0x0008 */
/* EN_MEMERROR 0x0010 */
/* EN_OVERFLOW 0x0020 */
/* EN_INSERTMODETOGGLE 0x0040 */
/* */
/* Standard Entry Field messages */
/* */
/* EM_QUERYCHANGED 0x0140 */
/* EM_QUERYSEL 0x0141 */
/* EM_SETSEL 0x0142 */
/* EM_SETTEXTLIMIT 0x0143 */
/* EM_CUT 0x0144 */
/* EM_COPY 0x0145 */
/* EM_CLEAR 0x0146 */
/* EM_PASTE 0x0147 */
/* EM_QUERYFIRSTCHAR 0x0148 */
/* EM_SETFIRSTCHAR 0x0149 */
/* EM_QUERYREADONLY 0x014a */
/* EM_SETREADONLY 0x014b */
/* EM_SETINSERTMODE 0x014c */
jmp_buf jBuf; /* Jump Buffer */
/************************************************************************/
/* */
/* Module Variable Definitions */
/* */
/************************************************************************/
extern HMODULE hmodDLL; /* DLL Module Handle */
/************************************************************************/
/* */
/* Module Prototype Definitions */
/* */
/************************************************************************/
static LONG lGetPresParam(HWND hWnd, ULONG ulID1, ULONG ulID2, LONG lDefault);
static VOID SizeEntryField(PENTRYFWIN pefw);
static VOID QueryCharPoints(PENTRYFWIN pefw);
static LONG lFindCharacterIndex(PENTRYFWIN pefw, LONG xClick);
static LONG lCalcDisplayPoint(PENTRYFWIN pefw, LONG iChar);
static BOOL fScrollRight(PENTRYFWIN pefw);
static VOID ShowCursor(PENTRYFWIN pefw, LONG iSel);
static VOID DrawOvertype(PENTRYFWIN pefw);
static VOID DrawTextString(PENTRYFWIN pefw, LONG iStart, LONG iEnd, BOOL fHighlighted);
static VOID DrawText(PENTRYFWIN pefw);
static VOID DrawSubText(PENTRYFWIN pefw, LONG iStart, LONG iEnd);
static VOID DrawOvertypeText(PENTRYFWIN pefw, BOOL fMoveRight);
static VOID SelectText(PENTRYFWIN pefw, LONG iAnchor, LONG iSelected);
static VOID RefreshMetrics(PENTRYFWIN pefw);
static VOID DecodeCtlData(PENTRYFWIN pefw, MPARAM mp1);
MRESULT EXPENTRY mrBaseFieldHandler(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);
APIRET APIENTRY EntryFieldExceptionHandler(PEXCEPTIONREPORTRECORD pxcptrepr,
PEXCEPTIONREGISTRATIONRECORD pxcptregr,
PCONTEXTRECORD pcr, PVOID sysinfo);
static VOID DeleteText(PENTRYFWIN pefw, LONG iSelStart, LONG iSelEnd, BOOL fRedraw);
static PSZ pszCopyText(PENTRYFWIN pefw, PSZ pszBuffer, LONG iSelStart, LONG iSelEnd);
static VOID PasteText(PENTRYFWIN pefw, PSZ pszBuffer, LONG cLen);
/************************************************************************/
/************************************************************************/
/* */
/* Module Private Functions */
/* */
/************************************************************************/
/************************************************************************/
#pragma subtitle(" Entry Field Control - Presentation Parameter Retrieve Procedure")
#pragma page( )
/* --- lGetPresParam ---------------------------------- [ Private } --- */
/* */
/* This function is used to retrieve a presentation parameter */
/* that may be present. If the presentation parameter is not, */
/* the default colour passed to the function will be used. All */
/* colours queried for are RGB or their RGB equivalents. */
/* */
/* Upon Entry: */
/* */
/* HWND hWnd; = Window Handle */
/* ULONG ulID1; = Presentation Parameter 1 ID (RGB) */
/* ULONG ulID2; = Presentation Parameter 2 ID (Index) */
/* LONG lDefault; = Default Colour */
/* */
/* Upon Exit: */
/* */
/* lGetPresParam = Colour to Use (RGB) */
/* */
/* -------------------------------------------------------------------- */
static LONG lGetPresParam(HWND hWnd, ULONG ulID1, ULONG ulID2, LONG lDefault)
{
HPS hPS; /* Presentation Space Handle */
LONG lClr; /* Presentation Parameter Colour */
ULONG ulID; /* Presentation Parameter ID */
/* First try to determine if any presentation */
/* parameters are set for the area requested. */
/* The first ID is RGB index and the second ID */
/* is colour index. */
if ( WinQueryPresParam(hWnd, ulID1, ulID2, &ulID, sizeof(LONG), (PVOID)&lClr,
QPF_NOINHERIT | QPF_ID2COLORINDEX | QPF_PURERGBCOLOR) )
/* Presentation parameter set for the area, */
/* return the RGB colour */
return(lClr);
else
/* No presentation parameters set, check to see */
/* if the default is a system colour in which */
/* only need to query the index for the RGB */
/* value */
if ( (lDefault >= SYSCLR_SHADOWHILITEBGND) &&
(lDefault <= SYSCLR_HELPHILITE) )
return(WinQuerySysColor(HWND_DESKTOP, lDefault, 0L));
else
/* Standard colour index, get the RGB equivalent */
/* for the index */
if ( (hPS = WinGetPS(hWnd)) != (HPS)NULL )
if ( (lClr = GpiQueryRGBColor(hPS, LCOLOPT_REALIZED, lDefault)) == GPI_ALTERROR )
{
/* Colour was not found, return white as colour */
WinReleasePS(hPS);
return(RGB_WHITE);
}
else
{
/* Colour found, return the RGB value */
WinReleasePS(hPS);
return(lClr);
}
else
return(RGB_WHITE);
}
#pragma subtitle(" Entry Field Control - Entry Field Sizing Procedure")
#pragma page( )
/* --- SizeEntryField --------------------------------- [ Private } --- */
/* */
/* This function is used to calculate the display points and */
/* rectangles for the entry field when it has changed in size. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID SizeEntryField(PENTRYFWIN pefw)
{
PLISTBOXWIN plbw; /* List Box Internal Data Pointer */
/* Form the bounding rectangle for the control */
pefw->rcl.xLeft = pefw->rcl.yBottom = 0L;
pefw->rcl.xRight = pefw->cx;
pefw->rcl.yTop = pefw->cy;
/* Save this rectangle within the bounding */
/* rectangle of the text. Also, adjust the text */
/* boundaries to allow for a little "white" */
/* space at the margins. */
pefw->rclDraw = pefw->rclText = pefw->rcl;
/* Calculate the scrolling shift count in */
/* characters. The formula used here is to take */
/* the width of the control and find its 1/3 */
/* point. Using this 1/3 width, now calculate */
/* the average number of characters that would */
/* fit in the space. */
pefw->cScroll = (pefw->xScrollLimit = pefw->rcl.xRight / 3L) / pefw->cxChar;
/* Set the baseline for the text as being the */
/* descender size plus the "white"space margin */
plbw = (PLISTBOXWIN)WinQueryWindowPtr(pefw->hwndOwner, QUCWP_WNDP);
pefw->ptlDraw.y = pefw->yBaseline = pefw->rcl.yTop - plbw->yAscender;
}
#pragma subtitle(" Entry Field Control - Text Character Position Procedure")
#pragma page( )
/* --- QueryCharPoints -------------------------------- [ Private } --- */
/* */
/* This function is used to build the point array which contains */
/* the starting position of each character in the text of the */
/* entry field. This function should only be called when the */
/* text within the control has changed. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID QueryCharPoints(PENTRYFWIN pefw)
{
POINTL rgptl[TXTBOX_COUNT]; /* Text Box Point Array */
/* Check to see if a previous array defined and */
/* if the case, release the array while clearing */
/* the pointer to make sure that an empty entry */
/* field is handled properly */
if ( pefw->aptl )
{
HeapFree(pefw->hHeap, pefw->aptl);
pefw->aptl = (PPOINTL)NULL;
}
/* Check to see if any text contained within the */
/* entry field and if the case, begin the */
/* process of building the point array */
if ( pefw->cText )
{
/* When the entry field is defined as being */
/* unreadable, the base text holder will contain */
/* asterisks (*) instead of the actual text. */
/* This is done to prevent the input from being */
/* displayed. A second input buffer is used to */
/* hold the actual text and the standard text */
/* buffer is filled with asterisks. */
if ( pefw->flStyle & ES_UNREADABLE )
{
memcpy(pefw->szPassword, pefw->szText, (UINT)pefw->cText);
memset(pefw->szText, '*', (UINT)pefw->cText);
pefw->szText[pefw->cText] = 0;
}
/* Allocate the point holders for the text and */
/* query the points. Make sure that there is */
/* one additional point holder for the right */
/* edge of the last character. */
GpiQueryCharStringPos(pefw->hPS, 0UL, pefw->cText, pefw->szText, (PLONG)NULL,
pefw->aptl = (PPOINTL)HeapMalloc(pefw->hHeap,
(ULONG)(sizeof(POINTL) * (pefw->cText + 1))));
/* Determine the actual text box bounding */
/* rectangle */
GpiQueryTextBox(pefw->hPS, pefw->cText, pefw->szText, 5L, rgptl);
/* Save the right edge of the last character */
/* in the last point holder. This will allow */
/* to a fast lookup of mouse clicks since all */
/* characters edges are horizontally defined. */
pefw->aptl[pefw->cText].x = rgptl[TXTBOX_CONCAT].x - rgptl[TXTBOX_BOTTOMLEFT].x;
}
else
pefw->iOffset = 0L;
/* Set the change flag to reflect the new text */
/* entered */
pefw->fChanged = TRUE;
}
#pragma subtitle(" Entry Field Control - Text Character Position Procedure")
#pragma page( )
/* --- lFindCharacterIndex ---------------------------- [ Private } --- */
/* */
/* This function is used to determine where the mouse pointer */
/* has clicked in terms of the characters that compose the text */
/* of the entry field. The method used is a binary search on */
/* the character point array that has been cached internally with */
/* the private control data. Further selection is performed for */
/* the selection point depending on whether the point is in the */
/* front half of the character box or the later half. When the */
/* point is in the front half, the character index for the */
/* found character box is used otherwise if it is in the later */
/* half, the next character is used. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* LONG xClick; = Horizontal Mouse Click Point */
/* */
/* Upon Exit: */
/* */
/* lFindCharacterIndex = Character Index */
/* */
/* -------------------------------------------------------------------- */
static LONG lFindCharacterIndex(PENTRYFWIN pefw, LONG xClick)
{
LONG iHigh; /* High Index */
LONG iLow; /* Low Index */
register LONG i; /* Index Positions */
/* Check to see if the mouse click is past the */
/* right-most character in the entry field text */
/* in which case indicate the text position as */
/* being just after the last character */
if ( (xClick += (pefw->aptl[pefw->iOffset].x - EFMARGIN_LEFT)) >= pefw->aptl[pefw->cText].x )
return(pefw->cText);
else
/* Check to make sure that the relative position */
/* does not extend to the left of the left */
/* margin */
if ( xClick > 0L )
{
/* Have determined that the mouse click is */
/* with the current text limit. Initialize the */
/* the high and low points for the binary search */
/* as being the shift offset as the low starting */
/* boundary and the length of the text as the */
/* high ending boundary. */
iLow = i = pefw->iOffset;
iHigh = pefw->cText - 1L;
/* Loop through the point array to see which */
/* cell falls under the mouse click */
while( iLow <= iHigh )
if ( xClick < pefw->aptl[i = (iLow + iHigh) / 2L].x )
iHigh = i - 1L;
else
if ( xClick >= pefw->aptl[i + 1L].x )
iLow = i + 1L;
else
/* Have found the cell where the mouse was */
/* clicked over. Now have to further refine the */
/* selection. When the mouse has been clicked */
/* in the left half of the cell, that cell is */
/* deemed as being the character cell selected. */
/* When the mouse has been clicked in the right */
/* half of the cell, the next character is */
/* deemed as being selected. */
if ( xClick > ((pefw->aptl[i + 1L].x - pefw->aptl[i].x) / 2L) + pefw->aptl[i].x)
return(i + 1L);
else
return(i);
return(i);
}
return(0L);
}
#pragma subtitle(" Entry Field Control - Text Character Position Procedure")
#pragma page( )
/* --- lCalcDisplayPoint ------------------------------ [ Private } --- */
/* */
/* This function is used to determine the left edge of a selected */
/* character cell. The display point is rationalized to be */
/* contained within the boundary rectangle for the text. What */
/* this means is that when the display point is beyond the right */
/* margin of the bounding rectangle, the point is rationalized to */
/* be that margin. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* LONG iChar; = Character Index */
/* */
/* Upon Exit: */
/* */
/* lCalcDisplayPoint = Character Display Point */
/* */
/* -------------------------------------------------------------------- */
static LONG lCalcDisplayPoint(PENTRYFWIN pefw, LONG iChar)
{
LONG xPoint; /* Point Position */
/* Check to see if there is a shifting offset */
/* indicating that the text has been scrolled */
/* such that portions of the text have been */
/* scrolled off to the left of the entry field. */
/* When this is the case, the point needs to be */
/* adjusted for this shift. The method used is */
/* to subtract the starting point for the first */
/* visible character from the desired character. */
/* If not the case, the actual display point is */
/* used. */
if ( pefw->iOffset )
/* Make sure that the character requested is not */
/* in front of the shifting offset which if the */
/* case, use the offset as the bounding edge */
if ( pefw->iOffset > iChar )
xPoint = pefw->aptl[pefw->iOffset].x + EFMARGIN_LEFT;
else
xPoint = pefw->aptl[iChar].x - pefw->aptl[pefw->iOffset].x + EFMARGIN_LEFT;
else
xPoint = pefw->aptl[iChar].x + EFMARGIN_LEFT;
/* Make sure that the point within the text */
/* bounding rectangle on the right edge */
return((xPoint < pefw->rclText.xRight) ? xPoint : pefw->rclText.xRight);
}
#pragma subtitle(" Entry Field Control - Scroll Right Determination Procedure")
#pragma page( )
/* --- fScrollRight ----------------------------------- [ Private } --- */
/* */
/* This function is used to determine if the entry field should */
/* be scrolled right depending on the position of the current */
/* selection such that if it is at the right margin and less than */
/* half an average character from the edge, scrolling to the */
/* right should occur. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* */
/* Upon Exit: */
/* */
/* fScrollRight = TRUE : Scrolling to Right Should Occur */
/* = FALSE : No Scrolling Should Occur
/* */
/* -------------------------------------------------------------------- */
static BOOL fScrollRight(PENTRYFWIN pefw)
{
/* Check to see if the character selection point */
/* is within the right margin area */
if ( (pefw->aptl[pefw->iSel].x - pefw->aptl[pefw->iOffset].x) >
(pefw->rclText.xRight - pefw->cxMargin) )
/* Current selection point within the margin */
/* area, check to see if scrolling should */
/* occur */
if ( (pefw->aptl[pefw->cText].x - pefw->aptl[pefw->iOffset].x) < (pefw->rclText.xRight / 3L) )
/* Scrolling not required since the end of the */
/* displayed text is fully visible within the */
/* entry field */
return(FALSE);
else
/* Scrolling permissible, return with the */
/* scroll flag */
return(TRUE);
else
/* Not within the margin area, return with the */
/* no scroll flag */
return(FALSE);
}
#pragma subtitle(" Entry Field Control - Cursor Management Procedure")
#pragma page( )
/* --- ShowCursor ------------------------------------- [ Private } --- */
/* */
/* This function is used to determine if the cursor location */
/* calculated for the current insertion point is visible and when */
/* the case to display it in that location otherwise it is not */
/* shown. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* LONG iSel; = Selection Point */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID ShowCursor(PENTRYFWIN pefw, LONG iSel)
{
LONG xCursor; /* New Cursor Location */
if ( pefw->aptl )
xCursor = pefw->aptl[iSel].x - pefw->aptl[pefw->iOffset].x + EFMARGIN_LEFT;
else
xCursor = EFMARGIN_LEFT;
/* Calculate the new position of the cursor and */
/* if it is different from the previous location */
/* determine if it should be shown and */
/* repositioned */
if ( pefw->xCursor != xCursor )
{
/* New cursor location calculated, save the new */
/* location internally within the private */
/* control data */
pefw->xCursor = xCursor;
/* Check to see if the new cursor location is */
/* within the bounding text rectangle of the */
/* entry field */
if ( (pefw->xCursor >= pefw->rclText.xLeft) &&
(pefw->xCursor <= pefw->rclText.xRight) )
{
/* Place the cursor in its new position */
WinCreateCursor(pefw->hWnd, pefw->xCursor, pefw->yCursor,
0L, 0L, CURSOR_SETPOS, NULL);
/* Cursor is within the rectangle, check to see */
/* if it was previously hidden and if the case, */
/* make it visible */
if ( !pefw->fCursorShown )
WinShowCursor(pefw->hWnd, pefw->fCursorShown = TRUE);
}
else
/* Cursor is not visible within the bounding */
/* text rectangle. Check to see if the it is */
/* currently visible and if the case, hide it. */
if ( pefw->fCursorShown )
WinShowCursor(pefw->hWnd, pefw->fCursorShown = FALSE);
}
}
#pragma subtitle(" Entry Field Control - Overtype Character Drawing Procedure")
#pragma page( )
/* --- DrawOvertype ----------------------------------- [ Private } --- */
/* */
/* This function is used to draw the selected overtype character. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID DrawOvertype(PENTRYFWIN pefw)
{
/* Determine the left edge of the drawing area */
pefw->ptlDraw.x = pefw->rclDraw.xLeft = lCalcDisplayPoint(pefw, pefw->iSel);
/* Determine the right edge of the drawing area */
pefw->rclDraw.xRight = lCalcDisplayPoint(pefw, pefw->iSel + 1);
/* Set the foreground and background colour for */
/* the text to be drawn. This is the highlight */
/* text drawing colour. */
GpiSetColor(pefw->hPS, pefw->lClrHilite);
WinFillRect(pefw->hPS, &pefw->rclDraw, pefw->lClrHiliteBackground);
/* Draw the one character that is to be high- */
/* lighted */
GpiCharStringPosAt(pefw->hPS, &pefw->ptlDraw, &pefw->rclDraw, CHS_CLIP,
1L, &pefw->szText[pefw->iSel], NULL);
}
#pragma subtitle(" Entry Field Control - Text Drawing Procedure")
#pragma page( )
/* --- DrawTextString --------------------------------- [ Private } --- */
/* */
/* This function is used to draw the text string using range */
/* provided either in normal or highlighted mode. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* LONG iStart; = Starting Point */
/* LONG iEnd; = Ending Point */
/* BOOL fHighlighted; = Highlighting Required Flag */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID DrawTextString(PENTRYFWIN pefw, LONG iStart, LONG iEnd,
BOOL fHighlighted)
{
/* Determine the left edge of the drawing area */
pefw->ptlDraw.x = pefw->rclDraw.xLeft = lCalcDisplayPoint(pefw, iStart);
/* Determine the right edge of the drawing area */
pefw->rclDraw.xRight = lCalcDisplayPoint(pefw, iEnd);
/* Set the foreground and background colour for */
/* the text to be drawn. This is the highlight */
/* text drawing colour. */
GpiSetColor(pefw->hPS, fHighlighted ? pefw->lClrHilite : pefw->lClrText);
WinFillRect(pefw->hPS, &pefw->rclDraw, fHighlighted ?
pefw->lClrHiliteBackground :
pefw->lClrBackground);
/* Draw the desired text in the location */
/* calculated */
GpiCharStringPosAt(pefw->hPS, &pefw->ptlDraw, &pefw->rclDraw, CHS_CLIP,
iEnd - iStart, &pefw->szText[iStart], NULL);
}
#pragma subtitle(" Entry Field Control - Text Character Position Procedure")
#pragma page( )
/* --- DrawText --------------------------------------- [ Private } --- */
/* */
/* This function is used to determine where the mouse pointer */
/* has clicked in terms of the characters that compose the text */
/* of the entry field. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID DrawText(PENTRYFWIN pefw)
{
/* Check to see if the cursor is being shown and */
/* if so, hide it before drawing */
if ( pefw->fCursorShown )
WinShowCursor(pefw->hWnd, pefw->fCursorShown = FALSE);
/* Check to see if there is no selected text or */
/* that the control has lost its focus which */
/* causes the highlighted text to be dehigh- */
/* lighted. Also check for a special case where */
/* the shift offset is greater than the end of */
/* the selected text. */
if ( (pefw->iSelStart == pefw->iSelEnd) || !pefw->fFocus ||
(pefw->iOffset > pefw->iSelEnd) )
{
/* Draw the text starting from the shift offset */
/* point */
DrawTextString(pefw, pefw->iOffset, pefw->cText, EFDISPLAY_NORMAL);
/* Check to see if in overtype mode which means */
/* that the character immediately to the right */
/* of the insertion point should be highlighted. */
/* This will only occur if a character is indeed */
/* adjacent to the cursor and the left mouse */
/* button is not currently being pressed. */
if ( pefw->fOvertype && (pefw->iSelStart == pefw->iSelEnd) &&
pefw->fFocus && (pefw->iSel != pefw->cText) && !pefw->fBtnDown )
DrawOvertype(pefw);
}
else
/* Check to see if the shift offset is after the */
/* selection starting point */
if ( pefw->iOffset > pefw->iSelStart )
{
/* Draw the text starting from the shift offset */
/* point */
DrawTextString(pefw, pefw->iOffset, pefw->iSelEnd, EFDISPLAY_HIGHLIGHT);
/* Check to see if any text is to be drawn to */
/* the right of the selected text and if the */
/* case, draw it */
if ( (pefw->iSelEnd < pefw->cText) &&
(pefw->rclDraw.xRight < pefw->rclText.xRight) )
/* Draw the text starting from the highlighted */
/* point */
DrawTextString(pefw, pefw->iSelEnd, pefw->cText, EFDISPLAY_NORMAL);
else
/* No text to the right of the highlighted text, */
/* erase the remaining portion of the rectangle */
{
pefw->rclDraw.xLeft = pefw->rclDraw.xRight;
pefw->rclDraw.xRight = pefw->rclText.xRight;
WinFillRect(pefw->hPS, &pefw->rclDraw, pefw->lClrBackground);
}
}
else
/* Check to see if the selection point is not */
/* starting at the begining of the text of the */
/* entry field which means that the displayed */
/* text needs to be displayed normally before */
/* the highlighted text is drawn */
{
if ( pefw->iSelStart && (pefw->iOffset < pefw->iSelStart) )
/* Draw the text starting from the shift offset */
/* point */
DrawTextString(pefw, pefw->iOffset, pefw->iSelStart, EFDISPLAY_NORMAL);
else
/* No normal display text before the selected */
/* text, calculate the starting right edge of */
/* the non-display text */
pefw->rclDraw.xRight = lCalcDisplayPoint(pefw, pefw->iSelStart);
/* Check to see if any highlighted text needs to */
/* be displayed. The basic trick here is to */
/* check to see if the previously drawn text is */
/* within the text bounding rectangle. */
if ( pefw->rclDraw.xRight < pefw->rclText.xRight )
{
/* Draw the text starting from the highlighting */
/* point */
DrawTextString(pefw, pefw->iSelStart, pefw->iSelEnd, EFDISPLAY_HIGHLIGHT);
/* Check to see if there is any text that needs */
/* to be drawn after the highlighted text that */
/* is within the text boudning rectangle */
if ( (pefw->cText > pefw->iSelEnd) &&
(pefw->rclDraw.xRight < pefw->rclText.xRight) )
/* Draw the text starting from the highlighting */
/* point */
DrawTextString(pefw, pefw->iSelEnd, pefw->cText,
EFDISPLAY_NORMAL);
/* No text to the right of the highlighted text, */
/* erase the remaining portion of the rectangle */
pefw->rclDraw.xLeft = pefw->rclDraw.xRight;
pefw->rclDraw.xRight = pefw->rclText.xRight;
WinFillRect(pefw->hPS, &pefw->rclDraw, pefw->lClrBackground);
}
}
/* Redisplay the cursor since all of the drawing */
/* is now complete */
WinShowCursor(pefw->hWnd, pefw->fCursorShown = TRUE);
}
#pragma subtitle(" Entry Field Control - Text Character Position Procedure")
#pragma page( )
/* --- DrawSubText ------------------------------------ [ Private } --- */
/* */
/* This function is used to determine where the mouse pointer */
/* has clicked in terms of the characters that compose the text */
/* of the entry field. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* LONG iStart; = Starting Character Index */
/* LONG iEnd; = Ending Character Index */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID DrawSubText(PENTRYFWIN pefw, LONG iStart, LONG iEnd)
{
/* Check to see if the starting point is before */
/* the shift offset and if the case make the */
/* starting point the shift offset */
if ( iStart < pefw->iOffset )
iStart = pefw->iOffset;
/* Check to see if the ending point is after the */
/* last character and if the case make the */
/* ending point the last character offset */
if ( iEnd > pefw->cText )
iEnd = pefw->cText;
/* Check to see if the cursor is being shown and */
/* if so, hide it before drawing */
if ( pefw->fCursorShown )
WinShowCursor(pefw->hWnd, pefw->fCursorShown = FALSE);
/* Check to see if there is any highlighting */
/* required which is indicated by a selecting */
/* range and when not the case, just draw the */
/* text range normally */
if ( (pefw->iSelStart == pefw->iSelEnd) || (iStart > pefw->iSelEnd) ||
(iEnd < pefw->iSelStart) )
{
/* Draw the text starting from the starting */
/* point */
DrawTextString(pefw, iStart, iEnd, EFDISPLAY_NORMAL);
/* Check to see if in overtype mode which means */
/* that the character immediately to the right */
/* of the insertion point should be highlighted. */
/* This will only occur if a character is indeed */
/* adjacent to the cursor and the left mouse */
/* button is not currently being pressed. */
if ( pefw->fOvertype && (pefw->iSelStart == pefw->iSelEnd) &&
pefw->fFocus && (pefw->iSel != pefw->cText) && !pefw->fBtnDown )
DrawOvertype(pefw);
}
else
/* Check to see if just highlighted text is to */
/* be drawn */
if ( (iStart > pefw->iSelStart) && (iEnd < pefw->iSelEnd) )
/* Draw the text starting from the starting */
/* point highlighted */
DrawTextString(pefw, iStart, iEnd, EFDISPLAY_HIGHLIGHT);
else
if ( iStart > pefw->iSelStart )
{
/* Draw the text starting from the starting */
/* point highlighted */
DrawTextString(pefw, iStart, pefw->iSelEnd, EFDISPLAY_HIGHLIGHT);
/* Check to see if the right edge of the high- */
/* lighted area was within the text bounding */
/* rectangle in which case there is normal text */
/* that still needs to be drawn to the right */
/* of the highlighted area */
if ( pefw->rclDraw.xRight < pefw->rclText.xRight )
/* Draw the text starting from the starting */
/* point normally */
DrawTextString(pefw, pefw->iSelEnd, iEnd, EFDISPLAY_NORMAL);
}
else
/* Check to see if the end point is before the */
/* the selection end point */
if ( iEnd < pefw->iSelEnd )
{
/* First draw the normal text that appears */
/* before the highlighted selection */
DrawTextString(pefw, iStart, pefw->iSelStart, EFDISPLAY_NORMAL);
/* Check to make sure that the right edge of the */
/* text just drawn falls within the text */
/* bounding rectangle which indicates that the */
/* remaining text can be drawn */
if ( pefw->rclDraw.xRight < pefw->rclText.xRight )
/* Draw the text starting from the starting */
/* point highlighted */
DrawTextString(pefw, pefw->iSelStart, iEnd,
EFDISPLAY_HIGHLIGHT);
}
else
{
/* First draw the normal text that appears */
/* before the highlighted selection */
DrawTextString(pefw, iStart, pefw->iSelStart, EFDISPLAY_NORMAL);
/* Check to make sure that the right edge of the */
/* text just drawn falls within the text */
/* bounding rectangle which indicates that the */
/* remaining text can be drawn */
if ( pefw->rclDraw.xRight < pefw->rclText.xRight )
{
/* Next draw the highlighted text */
DrawTextString(pefw, pefw->iSelStart, pefw->iSelEnd,
EFDISPLAY_HIGHLIGHT);
/* Check to make sure that the right edge of the */
/* text just drawn falls within the text */
/* bounding rectangle which indicates that the */
/* remaining text can be drawn */
if ( pefw->rclDraw.xRight < pefw->rclText.xRight )
/* Lastly draw the normal text that appears */
/* after the highlighted selection */
DrawTextString(pefw, pefw->iSelEnd, iEnd,
EFDISPLAY_NORMAL);
}
}
/* Redisplay the cursor since all of the drawing */
/* is now complete */
WinShowCursor(pefw->hWnd, pefw->fCursorShown = TRUE);
}
#pragma subtitle(" Entry Field Control - Overtype Text Draw Procedure")
#pragma page( )
/* --- DrawOvertypeText ------------------------------- [ Private } --- */
/* */
/* This function is used to draw the text indicating the overtype */
/* location. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* BOOL fMoveRight; = Move Right Direction */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID DrawOvertypeText(PENTRYFWIN pefw, BOOL fMoveRight)
{
/* Check to see if the cursor is being shown and */
/* if so, hide it before drawing */
if ( pefw->fCursorShown )
WinShowCursor(pefw->hWnd, pefw->fCursorShown = FALSE);
/* Get the presentation space for the control */
/* place the colour table into RGB mode before */
/* performing any drawing */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
/* Check to see if any text to the right of the */
/* selection point or if not moving to the right */
/* just calculate the left edge */
if ( !fMoveRight && ((pefw->iSel + 1L) == pefw->cText) )
pefw->rclDraw.xLeft = lCalcDisplayPoint(pefw, pefw->iSel + 1);
else
{
/* Calculate the left drawing point for the */
/* text */
pefw->rclDraw.xLeft = pefw->ptlDraw.x = lCalcDisplayPoint(pefw, fMoveRight ? pefw->iSel - 1 : pefw->iSel + 1);
/* Calculate the right drawing point for the */
/* text */
pefw->rclDraw.xRight = lCalcDisplayPoint(pefw, fMoveRight ? pefw->iSel : pefw->iSel + 2);
/* Set the foreground and background colour for */
/* the text to be drawn. This is the normal */
/* text drawing colour. */
GpiSetColor(pefw->hPS, pefw->lClrText);
WinFillRect(pefw->hPS, &pefw->rclDraw, pefw->lClrBackground);
/* Draw the text */
GpiCharStringPosAt(pefw->hPS, &pefw->ptlDraw, &pefw->rclDraw, CHS_CLIP, 1L,
&pefw->szText[fMoveRight ? pefw->iSel - 1 : pefw->iSel + 1], NULL);
}
/* Determine if the current selection point is */
/* not at the end of the text string which if */
/* the case need to draw overtype text character */
if ( pefw->iSel < pefw->cText )
{
/* Check to see if a move right performed which */
/* causes the display points to be adjusted for */
/* the action */
if ( fMoveRight )
{
pefw->rclDraw.xLeft = pefw->ptlDraw.x = pefw->rclDraw.xRight;
pefw->rclDraw.xRight = lCalcDisplayPoint(pefw, pefw->iSel + 1);
}
else
{
/* Just displaying the overtype point, find the */
/* display bounding rectangle for the character */
pefw->rclDraw.xRight = pefw->rclDraw.xLeft;
pefw->rclDraw.xLeft = pefw->ptlDraw.x = lCalcDisplayPoint(pefw, pefw->iSel);
}
/* Set the colour for the highlighted character */
GpiSetColor(pefw->hPS, pefw->lClrHilite);
WinFillRect(pefw->hPS, &pefw->rclDraw, pefw->lClrHiliteBackground);
/* Draw the highlighted character */
GpiCharStringPosAt(pefw->hPS, &pefw->ptlDraw, &pefw->rclDraw, CHS_CLIP,
1L, &pefw->szText[pefw->iSel], NULL);
}
/* Release the presentation space */
WinReleasePS(pefw->hPS);
/* Redisplay the cursor since all of the drawing */
/* is now complete */
WinShowCursor(pefw->hWnd, pefw->fCursorShown = TRUE);
}
#pragma subtitle(" Entry Field Control - Text Character Position Procedure")
#pragma page( )
/* --- SelectText ------------------------------------- [ Private } --- */
/* */
/* This function is used to determine where the mouse pointer */
/* has clicked in terms of the characters that compose the text */
/* of the entry field. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Data Pointer */
/* LONG iAnchor; = Anchor Position */
/* LONG iSelected; = New Selection Position */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID SelectText(PENTRYFWIN pefw, LONG iAnchor, LONG iSelected)
{
LONG iSelStart; /* Previous Selected Start */
LONG iSelEnd; /* Previous Selected End */
/* Check to see if the selection point specified */
/* is not the current selection point which if */
/* the case, just ignore selection request */
if ( iSelected != pefw->iSel )
{
/* Get the presentation space for the control */
/* place the colour table into RGB mode before */
/* performing any drawing */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd), 0L, LCOLF_RGB,
0L, 0L, (PLONG)NULL);
/* Save the current selection points */
iSelStart = pefw->iSelStart;
iSelEnd = pefw->iSelEnd;
/* Check to see if the anchor point is the */
/* current selection point which if the case */
/* need to remove any selection indicators */
if ( iSelected == iAnchor )
{
/* Redraw the revised text non-highlighting */
/* after setting the selection points to the */
/* new anchor point */
pefw->iSelStart = pefw->iSelEnd = iAnchor;
DrawSubText(pefw, iSelStart, iSelEnd);
}
else
/* Check to see if the anchor point is before */
/* the new selection point which if the case */
/* means that the movement is going from left */
/* to right generally */
if ( iSelected < iAnchor )
{
/* Save the new selection points */
pefw->iSelStart = iSelected;
pefw->iSelEnd = iAnchor;
/* Refresh the text display showing the new */
/* selection */
DrawSubText(pefw,
iSelStart < pefw->iSelStart ? iSelStart : pefw->iSelStart,
pefw->iSelEnd);
}
else
/* Anchor point is after the selection point, */
/* which means that the movement is going from */
/* right to left generally */
{
/* Save the new selection points */
pefw->iSelStart = iAnchor;
pefw->iSelEnd = iSelected;
/* Refresh the text display showing the new */
/* selection */
DrawSubText(pefw, pefw->iSelStart,
iSelEnd > pefw->iSelEnd ? iSelEnd : pefw->iSelEnd);
}
/* Release the presentation space */
WinReleasePS(pefw->hPS);
}
}
#pragma subtitle(" Entry Field Control - Entry Field Metrics Update Procedure")
#pragma page( )
/* --- RefreshMetrics --------------------------------- [ Private ] --- */
/* */
/* This function is used to update entry field metrics when */
/* a possible font change has occurred or when the style of */
/* the entry field has changed. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Private Data */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID RefreshMetrics(PENTRYFWIN pefw)
{
FONTMETRICS fm; /* Font Metrics */
/* Get the font metrics for the presentation */
/* space */
GpiQueryFontMetrics(pefw->hPS, sizeof(FONTMETRICS), &fm);
/* Check to see if any text defined currently */
/* for the entry field and if so, cause the */
/* display points array to be updated such that */
/* it properly reflects the revised font metrics */
/* differences that may have been caused due to */
/* a font change */
if ( pefw->cText )
{
/* Get the revised points array */
QueryCharPoints(pefw);
/* Calculate the new cursor position and force */
/* it to the new location */
pefw->xCursor = pefw->aptl[pefw->iSel].x + EFMARGIN_LEFT;
ShowCursor(pefw, pefw->iSel);
}
else
/* Set the cursor location for the start of the */
/* empty entry field */
pefw->xCursor = EFMARGIN_LEFT;
/* Calculate the new metrics for the entry field */
pefw->cxMargin = (pefw->cxChar = fm.lAveCharWidth) / 2L;
pefw->cyCursor = fm.lMaxBaselineExt;
pefw->yDesc = fm.lMaxDescender;
pefw->yCursor = EFMARGIN_BOTTOM;
/* Adjust the sizing of the entry field */
if ( (pefw->cx > 0L) && (pefw->cx > 0L) )
SizeEntryField(pefw);
}
#pragma subtitle(" Entry Field Control - Entry Field Control Data Decoding Procedure")
#pragma page( )
/* --- DecodeCtlData ---------------------------------- [ Private ] --- */
/* */
/* This function is used to process the entry field control data */
/* that may be provided when the entry field is first created. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Private Data */
/* MPARAM mp1; = Message Parameter 1 */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID DecodeCtlData(PENTRYFWIN pefw, MPARAM mp1)
{
PENTRYFCDATA pefcd; /* Entry Field Control Data Pointer */
/* Check to see if any control data specified */
/* in the first message parameter */
if ( (pefcd = (PENTRYFCDATA)PVOIDFROMMP(mp1)) == NULL )
/* No control data defined during the creation, */
/* set up the control for the default text limit */
pefw->cLimit = 1024L;
else
/* Data present, check to see if the control */
/* data the older 16-bit type or the newer */
/* 32-bit type by checking the size of the */
/* structure */
if ( pefcd->efd.cb == sizeof(ENTRYFDATA) )
{
/* 16-bit layout, get the maximum amount of text */
/* the control is to handle along with any */
/* predefined selections */
pefw->cLimit = pefcd->efd.cchEditLimit;
pefw->iSel = pefw->iSelStart = pefw->iAnchor = pefcd->efd.ichMinSel;
pefw->iSelEnd = pefcd->efd.ichMaxSel;
}
else
{
/* 32-bit layout, get the maximum amount of text */
/* the control is to handle along with any */
/* predefined selections */
pefw->cLimit = (LONG)pefcd->efd2.cchEditLimit;
pefw->iSel = pefw->iSelStart = pefw->iAnchor = (LONG)pefcd->efd2.ichMinSel;
pefw->iSelEnd = (LONG)pefcd->efd2.ichMaxSel;
}
}
#pragma subtitle(" Entry Field Control - Entry Field Message Processing Procedure")
#pragma page( )
/* --- mrBaseFieldHandler ----------------------------- [ Private ] --- */
/* */
/* This function is used to process the base messages for the */
/* entry field control window. */
/* */
/* Upon Entry: */
/* */
/* HWND hWnd; = Window Handle */
/* ULONG msg; = PM Message */
/* MPARAM mp1; = Message Parameter 1 */
/* MPARAM mp2; = Message Parameter 2 */
/* */
/* Upon Exit: */
/* */
/* mrBaseFieldHandler = Message Handling Result */
/* */
/* -------------------------------------------------------------------- */
MRESULT EXPENTRY mrBaseFieldHandler(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
#pragma info(nopar)
BOOL fChanged; /* Previous Changed Flag */
BOOL fInsertMode; /* Previous Insert Mode Flag */
BOOL fReadOnly; /* Previous Read Only Flag */
PCHAR pchClipText; /* Clipboard Text Pointer */
PENTRYFWIN pefw; /* Entry Field Internal Data Pointer */
register LONG n; /* Text Length Holder */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
switch ( msg )
{
/*********************************************************************/
/* Base message: EM_CLEAR */
/* mp1 = 0L; */
/* mp2 = 0L; */
/*********************************************************************/
case EM_CLEAR :
/* Check to make sure that the entry field is */
/* not read-only and that a selection has been */
/* made before trying to delete the text */
if ( !pefw->fReadOnly && (pefw->iSelStart != pefw->iSelEnd) )
{
DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, TRUE);
return(MRFROMLONG(TRUE));
}
else
return(MRFROMLONG(FALSE));
/*********************************************************************/
/* Base message: EM_COPY */
/* mp1 = 0L; */
/* mp2 = 0L; */
/*********************************************************************/
case EM_COPY :
/* Check to make sure that a selection within */
/* the text has been made before trying to copy */
/* the selection to the clipboard */
if ( (pefw->iSelStart != pefw->iSelEnd) )
{
/* Check to see if the entry field is unreadable */
/* which means that it is being used for some- */
/* thing like a password entry area. In this */
/* case do not allow the text to be copied to */
/* the clipboard. (Note: this differs from */
/* the OS/2 entry field in that it will allow */
/* you to copy the text to the clipboard) */
if ( pefw->flStyle & ES_UNREADABLE )
{
WinAlarm(HWND_DESKTOP, WA_ERROR);
return(MRFROMLONG(FALSE));
}
else
{
/* Allocate the shared memory for the text */
/* making sure that there is enough memory for */
/* the text plus the NULL terminating byte */
DosAllocSharedMem((PPVOID)(PVOID)&pchClipText, NULL,
(ULONG)(pefw->iSelEnd - pefw->iSelStart + 1),
fALLOCSHR);
/* Open and empty the clipboard before copying */
/* the selected text to the shared memory */
/* and placing the pointer on the clipboard */
WinOpenClipbrd(pefw->hAB);
WinEmptyClipbrd(pefw->hAB);
WinSetClipbrdData(pefw->hAB, (ULONG)pszCopyText(pefw, pchClipText,
pefw->iSelStart,
pefw->iSelEnd),
CF_TEXT, CFI_POINTER);
/* Close the clipboard to allow the copied text */
/* to be used by other processes as well as this */
/* one */
WinCloseClipbrd(pefw->hAB);
return(MRFROMLONG(TRUE));
}
}
else
return(MRFROMLONG(FALSE));
/*********************************************************************/
/* Base message: EM_CUT */
/* mp1 = 0L; */
/* mp2 = 0L; */
/*********************************************************************/
case EM_CUT :
/* Check to make sure that the entry field is */
/* not read-only and that a selection has been */
/* made before trying to cut the text from the */
/* entry field and place it on the system */
/* clipboard */
if ( !pefw->fReadOnly && (pefw->iSelStart != pefw->iSelEnd) )
{
/* Allocate the shared memory for the text */
/* making sure that there is enough memory for */
/* the text plus the NULL terminating byte */
DosAllocSharedMem((PPVOID)(PVOID)&pchClipText, NULL,
(ULONG)(pefw->iSelEnd - pefw->iSelStart + 1),
fALLOCSHR);
/* Open and empty the clipboard before copying */
/* the selected text to the shared memory */
/* and placing the pointer on the clipboard */
WinOpenClipbrd(pefw->hAB);
WinEmptyClipbrd(pefw->hAB);
WinSetClipbrdData(pefw->hAB,
(ULONG)pszCopyText(pefw, pchClipText, pefw->iSelStart, pefw->iSelEnd),
CF_TEXT, CFI_POINTER);
/* Close the clipboard to allow the copied text */
/* to be used by other processes as well as this */
/* one */
WinCloseClipbrd(pefw->hAB);
/* Delete the selected text */
DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, TRUE);
return(MRFROMLONG(TRUE));
}
else
return(MRFROMLONG(FALSE));
/*********************************************************************/
/* Base message: EM_PASTE */
/* mp1 = 0L; */
/* mp2 = 0L; */
/*********************************************************************/
case EM_PASTE :
/* Check to make sure that the entry field is */
/* not read-only */
if ( pefw->fReadOnly )
return(MRFROMLONG(FALSE));
else
{
/* Open the clipboard and then check to see if */
/* any text has been placed on it that can be */
/* pasted within the entry field */
WinOpenClipbrd(pefw->hAB);
if ( WinQueryClipbrdData(pefw->hAB, CF_TEXT) )
{
/* Text contained within the clipboard, get the */
/* pointer to the text */
if ( (pchClipText = (PCHAR)WinQueryClipbrdData(pefw->hAB, CF_TEXT)) != NULL )
/* Check to make sure that the selection within */
/* the clipboard will fit within the entry field */
if ( ((n = (LONG)strlen(pchClipText)) + pefw->cText) < pefw->cLimit )
{
/* Check to see if any text is currently */
/* selected which means that the text should be */
/* replaced by the text from the clipboard. If */
/* the case, delete the selected text. */
if ( pefw->iSelStart != pefw->iSelEnd )
DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, FALSE);
/* Paste the text into the entry field at the */
/* current selection point */
PasteText(pefw, pchClipText, n);
}
/* Finished with the clipboard, close it */
WinCloseClipbrd(pefw->hAB);
return(MRFROMLONG(TRUE));
}
else
/* No text within the clipboard, close it */
{
WinCloseClipbrd(pefw->hAB);
return(MRFROMLONG(FALSE));
}
}
/*********************************************************************/
/* Base message: EM_QUERYCHANGED */
/* mp1 = 0L; */
/* mp2 = 0L; */
/*********************************************************************/
case EM_QUERYCHANGED :
fChanged = pefw->fChanged;
pefw->fChanged = FALSE;
return(MRFROMLONG(fChanged));
/*********************************************************************/
/* Base message: EM_QUERYFIRSTCHAR */
/* mp1 = 0L; */
/* mp2 = 0L; */
/*********************************************************************/
case EM_QUERYFIRSTCHAR :
/* Return the offset to the first displayed */
/* character in the entry field */
return(MRFROMLONG(pefw->iOffset));
/*********************************************************************/
/* Base message: EM_QUERYREADONLY */
/* mp1 = 0L; */
/* mp2 = 0L; */
/*********************************************************************/
case EM_QUERYREADONLY :
/* Return the read-only status of the entry */
/* field */
return(MRFROMLONG(pefw->fReadOnly));
/*********************************************************************/
/* Base message: EM_QUERYSEL */
/* mp1 = 0L; */
/* mp2 = 0L; */
/*********************************************************************/
case EM_QUERYSEL :
/* Return the selection range */
return(MRFROM2SHORT(pefw->iSelStart, pefw->iSelEnd));
/*********************************************************************/
/* Base message: EM_SETFIRSTCHAR */
/* mp1 = MPFROMSHORT(sOffset); */
/* mp2 = 0L; */
/*********************************************************************/
case EM_SETFIRSTCHAR :
/* Check to make sure that the value specified */
/* for the message is within the text limits */
if ( ((LONG)(SHORT)SHORT1FROMMP(mp1) >= 0L) &&
((LONG)(SHORT)SHORT1FROMMP(mp1) <= pefw->cText) )
{
/* Check to see if the requested starting point */
/* is the current offset in which case nothing */
/* needs to be done */
if ( pefw->iOffset != (LONG)(SHORT)SHORT1FROMMP(mp1) )
{
/* New offset being defined, save the new value */
pefw->iOffset = (LONG)(SHORT)SHORT1FROMMP(mp1);
/* Get the presentation space handle for the */
/* entry field and place it in RGB mode before */
/* causing the text to be redrawn showing the */
/* new offset */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
}
return(MRFROMLONG(TRUE));
}
else
return(MRFROMLONG(FALSE));
/*********************************************************************/
/* Base message: EM_SETINSERTMODE */
/* mp1 = MPFROMSHORT(usInsert); */
/* mp2 = 0L; */
/*********************************************************************/
case EM_SETINSERTMODE :
/* Determine the current insert mode and save */
/* since it is returned */
if ( pefw->fOvertype )
fInsertMode = FALSE;
else
fInsertMode = TRUE;
/* Determine the new insert mode and save the */
/* overtype equivalent */
if ( (BOOL)SHORT1FROMMP(mp1) )
pefw->fOvertype = FALSE;
else
pefw->fOvertype = TRUE;
/* Update the internal OS/2 PM insert mode to */
/* reflect the change */
WinSetSysValue(HWND_DESKTOP, SV_INSERTMODE,
(LONG)(BOOL)SHORT1FROMMP(mp1));
/* Check to see if the overtype character needs */
/* to be redrawn do to the change of the insert */
/* mode */
if ( fInsertMode != (BOOL)SHORT1FROMMP(mp1) )
{
GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
}
return(MRFROMLONG(fInsertMode));
/*********************************************************************/
/* Base message: EM_SETREADONLY */
/* mp1 = MPFROMSHORT(usReadOnly); */
/* mp2 = 0L; */
/*********************************************************************/
case EM_SETREADONLY :
fReadOnly = pefw->fReadOnly;
pefw->fReadOnly = (BOOL)SHORT1FROMMP(mp1);
return(MRFROMLONG(fReadOnly));
/*********************************************************************/
/* Base message: EM_SETSEL */
/* mp1 = MPFROM2SHORT(usMinSel, usMaxSel); */
/* mp2 = 0L; */
/*********************************************************************/
case EM_SETSEL :
if ( ((LONG)(SHORT)SHORT1FROMMP(mp1) >= 0L) &&
((LONG)(SHORT)SHORT1FROMMP(mp1) <= (LONG)(SHORT)SHORT2FROMMP(mp1)) )
{
/* Check to see if the selection range is */
/* different in which case need to reflect the */
/* new range otherwise just ignore the request */
if ( (pefw->iSelStart != (LONG)(SHORT)SHORT1FROMMP(mp1)) &&
(pefw->iSelEnd != (LONG)(SHORT)SHORT2FROMMP(mp1)) )
{
/* New selection range being specified, save the */
/* starting value */
pefw->iSelStart = (LONG)(SHORT)SHORT1FROMMP(mp1);
/* Check the ending selection value to make sure */
/* that if it is greater than the amount of text */
/* contained within the entry field, the range */
/* ends at the end of the text */
if ( (pefw->iSelEnd = (LONG)(SHORT)SHORT2FROMMP(mp1)) > pefw->cText )
pefw->iSelEnd = pefw->cText;
/* Get the presentation space handle for the */
/* entry field and place it in RGB mode before */
/* causing the text to be redrawn showing the */
/* new selection */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
}
return(MRFROMLONG(TRUE));
}
else
return(MRFROMLONG(FALSE));
/*********************************************************************/
/* Base message: EM_SETTEXTLIMIT */
/* mp1 = MPFROMSHORT(sTextLimit); */
/* mp2 = 0L; */
/*********************************************************************/
case EM_SETTEXTLIMIT :
/* Check to make sure that the text limit */
/* specified is within the current text holder */
/* limits */
if ( ((LONG)(SHORT)SHORT1FROMMP(mp1) >= 0L) &&
((LONG)(SHORT)SHORT1FROMMP(mp1) < 1024L) )
{
/* New limit within control limits, save the */
/* value internally */
pefw->cLimit = (LONG)(SHORT)SHORT1FROMMP(mp1);
return(MRFROMLONG(TRUE));
}
else
/* Requested text limit too high, inform the */
/* owner of the problem */
{
mrNotifyEFOwner(pefw, EN_MEMERROR);
return(MRFROMLONG(FALSE));
}
}
return(0L);
}
#pragma info(par)
#pragma subtitle(" Entry Field Control - Exception Handler Routine")
#pragma page( )
/* --- EntryFieldExceptionHandler --------------------- [ Private ] --- */
/* */
/* This function is used process exceptions under 2.x and to, */
/* depending on the exception, provide a method of performing */
/* lazy pointer validation for the data types. */
/* */
/* Upon Entry: */
/* */
/* PEXCEPTIONREPORTRECORD pxcptrepr; = Report Record */
/* PEXCEPTIONREGISTRATIONRECORD pxcptregr; = Registration Record */
/* PCONTEXTRECORD pcr; = Context Record */
/* PVOID sysinfo; = System Reserved */
/* */
/* Upon Exit: */
/* */
/* EntryFieldExceptionHandler = Exception Handling Value */
/* */
/* -------------------------------------------------------------------- */
APIRET APIENTRY EntryFieldExceptionHandler(PEXCEPTIONREPORTRECORD pxcptrepr,
PEXCEPTIONREGISTRATIONRECORD pxcptregr,
PCONTEXTRECORD pcr, PVOID sysinfo)
{
#pragma info(nopar)
if ( (EH_EXIT_UNWIND & pxcptrepr->fHandlerFlags) ||
(EH_UNWINDING & pxcptrepr->fHandlerFlags) ||
(EH_NESTED_CALL & pxcptrepr->fHandlerFlags) )
return(XCPT_CONTINUE_SEARCH);
if ( pxcptrepr->ExceptionNum == XCPT_ACCESS_VIOLATION )
longjmp((INT *)jBuf, 1);
return(XCPT_CONTINUE_SEARCH);
}
#pragma info(par)
#pragma subtitle(" Entry Field Control - Delete Text Routine")
#pragma page( )
/* --- DeleteText ------------------------------------- [ Private ] --- */
/* */
/* This function is used delete the selected range of text from */
/* the entry field and to save the deleted text within the undo */
/* buffer for later retrieval if required. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Private Data */
/* LONG iSelStart; = Deletion Start Index */
/* LONG iSelEnd; = Deletion End Index */
/* BOOL fRedraw; = Redraw Flag */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID DeleteText(PENTRYFWIN pefw, LONG iSelStart, LONG iSelEnd,
BOOL fRedraw)
{
register LONG n; /* Length Value */
EXCEPTIONREGISTRATIONRECORD xcptregr; /* Exception Record */
/* Check to make sure that the selection start */
/* is not after the end of the text */
if ( iSelStart < pefw->cText )
{
/* Register exception handler that is used for */
/* the lazy pointer validation tests */
xcptregr.prev_structure = NULL;
xcptregr.ExceptionHandler = &EntryFieldExceptionHandler;
DosSetExceptionHandler(&xcptregr);
if ( !setjmp(jBuf) )
{
/* Check to make sure that the ending range for */
/* the text to be deleted does not exceed the */
/* current text in which case make the ending */
/* selection value the text limits */
if ( iSelEnd > pefw->cText )
iSelEnd = pefw->cText;
/* Copy the selected range of text to the undo */
/* buffer */
memcpy(pefw->szUndo, &pefw->szText[iSelStart],
(UINT)(n = iSelEnd - iSelStart));
pefw->szUndo[n] = 0;
/* Check to see if the selection was to the end */
/* of the text in which case NULL terminate the */
/* text string at the selection starting point */
if ( iSelEnd == pefw->cText )
pefw->szText[iSelStart] = 0;
else
/* Move up the text that was after the selection */
memmove(&pefw->szText[iSelStart], &pefw->szText[iSelEnd],
(UINT)(pefw->cText - iSelEnd + 1));
/* Update the text length */
pefw->cText -= n;
/* Set the new selection point to the starting */
/* location where the previous selection started */
pefw->iSel = pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = iSelStart;
/* Get the presentation space handle for the */
/* entry field */
pefw->hPS = WinGetPS(pefw->hWnd);
/* Get the new point array for the text string */
QueryCharPoints(pefw);
if ( pefw->cText && pefw->iOffset && (pefw->aptl[pefw->cText].x < pefw->rclText.xRight) )
{
pefw->iOffset = 0L;
if ( !fRedraw )
{
/* Deletion changes need to be redrawn, place */
/* the colour table into RGB mode and draw the */
/* revised text string within the entry field */
/* so as to reflect the changes made */
GpiCreateLogColorTable(pefw->hPS, 0L, LCOLF_RGB,
0L, 0L, (PLONG)NULL);
DrawText(pefw);
}
}
else
{
GpiCreateLogColorTable(pefw->hPS, 0L, LCOLF_RGB,
0L, 0L, (PLONG)NULL);
if ( pefw->fCursorShown )
WinShowCursor(pefw->hWnd, pefw->fCursorShown = FALSE);
WinFillRect(pefw->hPS, &pefw->rcl, pefw->lClrBackground);
}
/* Check to see if the changes should be redrawn */
if ( fRedraw )
{
/* Deletion changes need to be redrawn, place */
/* the colour table into RGB mode and draw the */
/* revised text string within the entry field */
/* so as to reflect the changes made */
GpiCreateLogColorTable(pefw->hPS, 0L, LCOLF_RGB,
0L, 0L, (PLONG)NULL);
DrawText(pefw);
/* Notify the owner that changes have occurred */
mrNotifyEFOwner(pefw, EN_CHANGE);
}
/* Release the presentation space handle */
WinReleasePS(pefw->hPS);
}
/* Remove the exception handle since the lazy */
/* pointer evaluation is done */
DosUnsetExceptionHandler(&xcptregr);
}
}
#pragma subtitle(" Entry Field Control - Copy Text Routine")
#pragma page( )
/* --- pszCopyText ------------------------------------ [ Private ] --- */
/* */
/* This function is used to copy the text selection to the */
/* supplied buffer. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Private Data */
/* PSZ pszBuffer; = Copy Buffer */
/* LONG iSelStart; = Deletion Start Index */
/* LONG iSelEnd; = Deletion End Index */
/* */
/* Upon Exit: */
/* */
/* pszCopyText = Address of pszBuffer */
/* */
/* -------------------------------------------------------------------- */
static PSZ pszCopyText(PENTRYFWIN pefw, PSZ pszBuffer, LONG iSelStart,
LONG iSelEnd)
{
register LONG i; /* Length Holder */
EXCEPTIONREGISTRATIONRECORD xcptregr; /* Exception Record */
/* Check to make sure that the selection start */
/* is not after the end of the text */
if ( iSelStart < pefw->cText )
{
/* Register exception handler that is used for */
/* the lazy pointer validation tests */
xcptregr.prev_structure = NULL;
xcptregr.ExceptionHandler = &EntryFieldExceptionHandler;
DosSetExceptionHandler(&xcptregr);
if ( !setjmp(jBuf) )
{
/* Check to make sure that the ending range for */
/* the text to be deleted does not exceed the */
/* current text in which case make the ending */
/* selection value the text limits */
if ( iSelEnd > pefw->cText )
iSelEnd = pefw->cText;
/* Check to make sure that the start of the */
/* selection is not after the selection end */
/* which would be incorrect */
if ( iSelStart < iSelEnd )
{
/* Copy the text from the internal text buffer */
/* to the supplied buffer */
memcpy(pszBuffer,
(PSZ)(pefw->flStyle & ES_UNREADABLE ?
&pefw->szPassword[iSelStart] :
&pefw->szText[iSelStart]), (UINT)(i = iSelEnd - iSelStart));
pszBuffer[i] = 0;
}
else
/* No text to copy, make the supplied buffer */
/* reflect the condition */
pszBuffer[0] = 0;
}
/* Remove the exception handle since the lazy */
/* pointer evaluation is done */
DosUnsetExceptionHandler(&xcptregr);
}
return(pszBuffer);
}
#pragma subtitle(" Entry Field Control - Paste Text Routine")
#pragma page( )
/* --- PasteText -------------------------------------- [ Private ] --- */
/* */
/* This function is used process exceptions under 2.x and to, */
/* depending on the exception, provide a method of performing */
/* lazy pointer validation for the data types. */
/* */
/* Upon Entry: */
/* */
/* PENTRYFWIN pefw; = Entry Field Private Data */
/* PSZ pszInsText; = Copy Buffer */
/* */
/* Upon Exit: */
/* */
/* Nothing */
/* */
/* -------------------------------------------------------------------- */
static VOID PasteText(PENTRYFWIN pefw, PSZ pszInsText, LONG cLen)
{
PSZ pszBuffer; /* Text Buffer Pointer */
EXCEPTIONREGISTRATIONRECORD xcptregr; /* Exception Record */
/* Register exception handler that is used for */
/* the lazy pointer validation tests */
xcptregr.prev_structure = NULL;
xcptregr.ExceptionHandler = &EntryFieldExceptionHandler;
DosSetExceptionHandler(&xcptregr);
if ( !setjmp(jBuf) )
{
/* Check to see which text buffer should be used */
/* since the entry field allows for unreadable */
/* display */
if ( pefw->flStyle & ES_UNREADABLE )
pszBuffer = pefw->szPassword;
else
pszBuffer = pefw->szText;
/* Check to see if the insertion point is before */
/* the end of the string */
if ( pefw->iSel < pefw->cText )
{
/* Text being inserted within the entry field */
/* string, open up exactly the space required */
/* to allow the new text to be inserted */
memmove(&pszBuffer[pefw->iSel + cLen], &pszBuffer[pefw->iSel],
(UINT)((pefw->cText + cLen) - pefw->iSel));
/* Check to see if a full string is being */
/* inserted or just a character. In either */
/* case, insert the text appropriately. */
if ( cLen > 1L )
memmove(&pszBuffer[pefw->iSel], pszInsText, (UINT)cLen);
else
pszBuffer[pefw->iSel] = pszInsText[0];
/* Update the insert selection point along with */
/* the text length */
pefw->iSel += cLen;
pefw->cText += cLen;
}
else
{
/* Text being concatonated to the end of the */
/* entry field string, check to see which */
/* concatonation method should be used */
if ( cLen > 1L )
strncat(pszBuffer, pszInsText, (UINT)cLen + 1);
else
{
pszBuffer[pefw->iSel] = pszInsText[0];
pszBuffer[pefw->iSel + 1L] = 0;
}
/* Update the insert selection point along with */
/* the text length */
pefw->iSel = pefw->cText += cLen;
}
/* Update the selection indices */
pefw->iSelEnd = pefw->iSelStart = pefw->iAnchor = pefw->iSel;
/* Insertion changes need to be redrawn, place */
/* the colour table into RGB mode and draw the */
/* revised text string within the entry field */
/* so as to reflect the changes made */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
/* Calculate the new display points for the text */
/* string */
QueryCharPoints(pefw);
/* Check to see if the new cursor position will */
/* be outside the range of the entry field which */
/* means that the text will need to be scrolled */
if ( fScrollRight(pefw) )
{
/* Check to see if the scrolling is within */
/* limits, making sure that the scrolled text */
/* is properly shown */
if ( (pefw->iOffset += pefw->cScroll) > pefw->cText )
pefw->iOffset = pefw->cText;
DrawText(pefw);
/* Notify of the owner of the entry field that */
/* the entry field was scrolled */
mrNotifyEFOwner(pefw, EN_SCROLL);
}
else
/* No scrolling required, update the text */
/* displayed within the entry field to reflect */
/* the text added */
DrawTextString(pefw, 0L, pefw->cText, FALSE);
/* Release the presentation space */
WinReleasePS(pefw->hPS);
/* Inform the owner of the entry field that a */
/* change in the contents has occurred */
mrNotifyEFOwner(pefw, EN_CHANGE);
/* Show the cursor in the new location to */
/* reflection the new insertion point */
ShowCursor(pefw, pefw->iSel);
}
/* Remove the exception handle since the lazy */
/* pointer evaluation is done */
DosUnsetExceptionHandler(&xcptregr);
}
/************************************************************************/
/************************************************************************/
/* */
/* Module Public Functions */
/* */
/************************************************************************/
/************************************************************************/
#pragma subtitle(" Entry Field Control - Entry Field Registration Procedure")
#pragma page( )
/* --- fRegisterEntryField ----------------------------- [ Public ] --- */
/* */
/* This function is used to register the Entry Field for the */
/* application with PM. */
/* */
/* Upon Entry: */
/* */
/* HAB hAB; = Anchor Block Handle */
/* */
/* Upon Exit: */
/* */
/* fRegisterEntryField = TRUE : Entry Field Registration */
/* Successfull */
/* = FALSE : Entry Field Registration Failed */
/* */
/* -------------------------------------------------------------------- */
BOOL EXPENTRY fRegisterEntryField(HAB hAB)
{
/* Register the replace entry field class */
if ( WinRegisterClass(hAB, "EntryFieldWindow", (PFNWP)EntryWndProc,
CS_SYNCPAINT | CS_SIZEREDRAW | CS_PARENTCLIP | CS_CLIPCHILDREN,
USER_RESERVED) )
return(TRUE);
else
return(FALSE);
}
#pragma subtitle(" Entry Field Control - Entry Field Window Procedure")
#pragma page( )
/* --- EntryWndProc ------------------------------------ [ Public ] --- */
/* */
/* This function is used to process the messages for the entry */
/* field control window. */
/* */
/* Upon Entry: */
/* */
/* HWND hWnd; = Window Handle */
/* ULONG msg; = PM Message */
/* MPARAM mp1; = Message Parameter 1 */
/* MPARAM mp2; = Message Parameter 2 */
/* */
/* Upon Exit: */
/* */
/* EntryWndProc = Message Handling Result */
/* */
/* -------------------------------------------------------------------- */
MRESULT EXPENTRY EntryWndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
HHEAPMEM hHeap; /* Heap Handle */
HWND hwndHelp; /* Help Window Handle */
LONG iSelCurrent; /* Current Selection Pointer */
PCHAR pchClipText; /* Clipboard Text Pointer */
PCREATESTRUCT pcrst; /* Create Structure Pointer */
PENTRYFWIN pefw; /* Entry Field Internal Data Pointer */
POINTL ptl; /* Display Point */
PSWP pswp; /* Size Window Position Pointer */
PWNDPARAMS pwprm; /* Window Parameters Pointer */
RECTL rclPaint; /* Display Rectangle */
ULONG flStyle; /* Style Flags */
register LONG n; /* Length Counter */
EXCEPTIONREGISTRATIONRECORD xcptregr; /* Exception Record */
switch ( msg )
{
/************************************************************************/
/************************************************************************/
/* */
/* Part 1: Control creation coding */
/* */
/************************************************************************/
/************************************************************************/
/*********************************************************************/
/* Control creation */
/*********************************************************************/
case WM_CREATE :
/* Allocate space for the internal control data */
/* as well as a small heap. Save the address of */
/* the internal control data in the control's */
/* reserved memory to allow it to be referenced */
/* as required by the control. */
WinSetWindowPtr(hWnd, QUCWP_WNDP,
(PVOID)(pefw = (PENTRYFWIN)HeapMalloc(hHeap = HeapAlloc(4096UL, 4096UL),
sizeof(ENTRYFWIN))));
pefw->hHeap = hHeap;
/* Get the control's creation structure address */
/* to copy the relevant information such as the */
/* size, position and text of the control into */
/* the internal control data */
pcrst = (PCREATESTRUCT)PVOIDFROMMP(mp2);
/* Save the owner and parent of the control so */
/* notification messages can be sent back to */
/* the proper locations within the owning */
/* application */
pefw->hAB = WinQueryAnchorBlock(hWnd);
pefw->hWnd = hWnd;
pefw->hwndOwner = pcrst->hwndOwner;
pefw->hwndParent = pcrst->hwndParent;
pefw->id = pcrst->id;
if ( pcrst->pszText )
memcpy(pefw->szText, pcrst->pszText,
(UINT)((pefw->cText = (LONG)strlen(pcrst->pszText)) + 1));
/* Save the size of the Entry Field along with */
/* the current style */
pefw->cx = pcrst->cx;
pefw->cy = pcrst->cy;
if ( (pefw->flStyle = pcrst->flStyle) & ES_READONLY )
pefw->fReadOnly = TRUE;
/* Get the default colours for the entry field */
pefw->lClrText = lGetPresParam(hWnd, PP_FOREGROUNDCOLOR,
PP_FOREGROUNDCOLORINDEX,
SYSCLR_OUTPUTTEXT);
pefw->lClrBorder = lGetPresParam(hWnd, PP_BORDERCOLOR,
PP_BORDERCOLORINDEX,
SYSCLR_BUTTONDARK);
pefw->lClrBackground = lGetPresParam(hWnd, PP_BACKGROUNDCOLOR,
PP_BACKGROUNDCOLORINDEX,
SYSCLR_ENTRYFIELD);
pefw->lClrHilite = lGetPresParam(hWnd, PP_HILITEFOREGROUNDCOLOR,
PP_HILITEFOREGROUNDCOLORINDEX,
SYSCLR_HILITEFOREGROUND);
pefw->lClrHiliteBackground = lGetPresParam(hWnd, PP_HILITEBACKGROUNDCOLOR,
PP_HILITEBACKGROUNDCOLORINDEX,
SYSCLR_HILITEBACKGROUND);
/* Get the text pointer shape for use when the */
/* pointer is within the confines of the entry */
/* field rectangle */
pefw->hptr = WinQuerySysPointer(HWND_DESKTOP, SPTR_TEXT, FALSE);
/* Get the font metrics to determine the height */
/* and width of a character */
if ( pefw->cText )
pefw->iSel = pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = 0L;
pefw->hPS = WinGetPS(hWnd);
RefreshMetrics(pefw);
WinReleasePS(pefw->hPS);
/* Calculate the scroll rates */
pefw->ulScrollRateStart = WinQuerySysValue(HWND_DESKTOP, SV_SCROLLRATE) * 4UL;
pefw->ulScrollRate = WinQuerySysValue(HWND_DESKTOP, SV_SCROLLRATE) * 2UL;
/* Determine the current insertion mode */
if ( !WinQuerySysValue(HWND_DESKTOP, SV_INSERTMODE) )
pefw->fOvertype = TRUE;
/* Decode the control data for the control */
DecodeCtlData(pefw, mp1);
break;
/************************************************************************/
/************************************************************************/
/* */
/* Part 2: Control activation */
/* */
/************************************************************************/
/************************************************************************/
/*********************************************************************/
/* Control being activated/deactivated */
/*********************************************************************/
case WM_ACTIVATE :
if ( (hwndHelp = WinQueryHelpInstance(hWnd)) != (HWND)NULL )
/* When the window is being activated or */
/* deactivated, make sure that the control */
/* responds properly to help requests when it */
/* has the focus */
if ( SHORT1FROMMP(mp1) )
WinSendMsg(hwndHelp, HM_SET_ACTIVE_WINDOW,
MPFROMHWND(WinQueryWindow(hWnd, QW_PARENT)),
MPFROMHWND(WinQueryWindow(hWnd, QW_PARENT)));
else
WinSendMsg(hwndHelp, HM_SET_ACTIVE_WINDOW, 0L, 0L);
break;
/*********************************************************************/
/* Control receiving/losing focus */
/*********************************************************************/
case WM_SETFOCUS :
/* Get the Entry Field information pointer from */
/* the reserved memory of the window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* When the window is being activated or */
/* deactivated, make sure that the control */
/* responds properly to help requests when it */
/* has the focus */
if ( SHORT1FROMMP(mp2) )
{
/* Notify the owner of the Entry Field that that */
/* Entry Field is gaining focus */
mrNotifyEFOwner(pefw, EN_SETFOCUS);
if ( !pefw->fFocus )
{
/* Check to see if the insert mode has changed */
/* since the last time the control received */
/* focus */
if ( !WinQuerySysValue(HWND_DESKTOP, SV_INSERTMODE) )
pefw->fOvertype = TRUE;
/* Determine if some text has been selected */
/* within the entry field and if the case add */
/* the highlighting */
if ( pefw->iSelStart != pefw->iSelEnd )
{
GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd), 0L,
LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
}
/* Create the cursor where the current insertion */
/* point is */
WinCreateCursor(hWnd, pefw->xCursor, pefw->yCursor,
0L, pefw->cyCursor, CURSOR_SOLID | CURSOR_FLASH, NULL);
WinShowCursor(hWnd, pefw->fCursorShown = TRUE);
}
/* Set the focus flag */
pefw->fFocus = TRUE;
}
else
/* Focus being lost, only update internal flags */
/* if the control has received focus previously */
if ( pefw->fFocus && (HWNDFROMMP(mp1) != pefw->hwndPopupEdit) )
{
/* Notify the owner of the entry field that that */
/* entry field is losing focus */
mrNotifyEFOwner(pefw, EN_KILLFOCUS);
/* Destroy the cursor */
WinDestroyCursor(hWnd);
/* Clear the focus flags */
pefw->fCursorShown = pefw->fFocus = FALSE;
/* Determine if some text has been selected */
/* within the entry field and if the case remove */
/* the highlighting */
if ( (pefw->iSelStart != pefw->iSelEnd) || pefw->fOvertype )
{
GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd), 0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
}
}
break;
/************************************************************************/
/************************************************************************/
/* */
/* Part 3: Control sizing */
/* */
/************************************************************************/
/************************************************************************/
/*********************************************************************/
/* Control changing size or position */
/*********************************************************************/
case WM_ADJUSTWINDOWPOS :
pswp = (PSWP)PVOIDFROMMP(mp1);
if ( (pswp->fl & SWP_SIZE) && (pswp->cx > 0) && (pswp->cx > 0) )
/* Get the address of the control info from the */
/* control's reserved memory and save the new */
/* size of the control */
{
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
pefw->cx = pswp->cx;
pefw->cy = pswp->cy;
if ( (pswp->cx > 0L) && (pswp->cy > 0L) )
SizeEntryField(pefw);
}
break;
/*********************************************************************/
/* Convert position query */
/*********************************************************************/
case WM_QUERYCONVERTPOS :
return(MRFROMLONG(QCP_NOCONVERT));
/*********************************************************************/
/* Control changing size */
/*********************************************************************/
case WM_SIZE :
/* Get the address of the control info from the */
/* control's reserved memory and save the new */
/* size of the control */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
pefw->cx = (LONG)(SHORT)SHORT1FROMMP(mp2);
pefw->cy = (LONG)(SHORT)SHORT2FROMMP(mp2);
if ( ((LONG)(SHORT)SHORT1FROMMP(mp2) > 0L) &&
((LONG)(SHORT)SHORT2FROMMP(mp2) > 0L) )
SizeEntryField(pefw);
break;
/************************************************************************/
/************************************************************************/
/* */
/* Part 3: Mouse interface */
/* */
/************************************************************************/
/************************************************************************/
/*********************************************************************/
/* Button 1 click */
/*********************************************************************/
case WM_BUTTON1DOWN :
/* Get the Entry Field information pointer from */
/* the reserved memory of the window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Make sure that the entry field has focus */
if ( !pefw->fFocus )
WinSetFocus(HWND_DESKTOP, hWnd);
/* Check to see if the entry field has any text */
/* before trying to interprete the mouse */
/* position */
if ( pefw->cText )
{
/* Get the mouse hot-spot and check to see if it */
/* is within the bounds of the entry field */
ptl.x = (LONG)SHORT1FROMMP(mp1);
ptl.y = (LONG)SHORT2FROMMP(mp1);
if ( WinPtInRect(pefw->hAB, &pefw->rcl, &ptl) )
{
/* Mouse hot-spot within the entry field, set */
/* the mouse movement flags */
pefw->fScrollStart = pefw->fCapture = pefw->fBtnDown = TRUE;
/* Locate the character where the mouse pointer */
/* has been clicked */
FINDCHARACTER((LONG)SHORT1FROMMP(mp1));
/* Check to see if the extended selection using */
/* the shift key is being performed */
if ( !((ULONG)WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x0008000UL) )
{
/* Normal selection being performed, save the */
/* location where the mouse was clicked as being */
/* the new selection point */
pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = pefw->iSel;
/* Get the presentation space for the entry */
/* field and draw the changes made due to the */
/* button click */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd), 0L,
LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
}
else
/* Extended mouse selection being performed, */
/* select the text */
SelectText(pefw, pefw->iAnchor, pefw->iSel);
/* Capture the mouse input while the mouse */
/* is pressed to make sure that the button */
/* release is registered even if the mouse */
/* pointer is outside the confines of the entry */
/* field */
WinSetCapture(HWND_DESKTOP, hWnd);
/* Display the mouse cursor in the new location */
/* as reflected by the mouse pointer position */
if ( pefw->fCursorShown )
WinCreateCursor(hWnd, pefw->xCursor, pefw->yCursor,
0L, 0L, CURSOR_SETPOS, NULL);
}
}
return(MRFROMLONG(TRUE));
/*********************************************************************/
/* Button 1 double click */
/*********************************************************************/
case WM_BUTTON1DBLCLK :
/* Get the entry field information pointer from */
/* the reserved memory of the window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
return(MRFROMLONG(TRUE));
/*********************************************************************/
/* Button 1 released */
/*********************************************************************/
case WM_BUTTON1UP :
/* Get the entry field information pointer from */
/* the reserved memory of the window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Check to see if the mouse is being captured */
/* and if the case, release the capture */
if ( pefw->fCapture && (WinQueryCapture(HWND_DESKTOP) == hWnd) )
{
WinSetCapture(HWND_DESKTOP, (HWND)NULL);
pefw->fCapture = FALSE;
}
/* Clear the button down flag now that the */
/* has been released */
pefw->fBtnDown = FALSE;
/* See if the scroll timer is active and if the */
/* case, stop it since it is no longer required */
if ( pefw->fTimer )
{
pefw->fTimer = FALSE;
WinStopTimer(pefw->hAB, hWnd, TID_SCROLL);
}
/* Check to see if in overtype mode in which */
/* case the overtype character needs to be */
/* displayed only if there is no text selection */
if ( pefw->fOvertype && (pefw->iSelStart == pefw->iSelEnd) )
{
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawSubText(pefw, pefw->iSel, pefw->iSel + 1L);
WinReleasePS(pefw->hPS);
}
/* Show the cursor in the new location */
ShowCursor(pefw, pefw->iSel);
return(MRFROMLONG(TRUE));
/*********************************************************************/
/* Button 2 clicked */
/*********************************************************************/
case WM_BUTTON2DOWN :
/* Get the entry field information pointer from */
/* the reserved memory of the window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
if ( !pefw->hwndPopupEdit )
pefw->hwndPopupEdit = WinLoadMenu(hWnd, (HMODULE)hmodDLL, IDM_POPUPEDIT);
if ( pefw->hwndPopupEdit )
{
WinOpenClipbrd(pefw->hAB);
if ( WinQueryClipbrdFmtInfo(pefw->hAB, CF_TEXT, &flStyle) )
WinSendMsg(pefw->hwndPopupEdit, MM_SETITEMATTR, MPFROM2SHORT(IDM_PASTE, TRUE),
MPFROM2SHORT(MIA_DISABLED, 0));
else
WinSendMsg(pefw->hwndPopupEdit, MM_SETITEMATTR, MPFROM2SHORT(IDM_PASTE, TRUE),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
WinCloseClipbrd(pefw->hAB);
if ( pefw->iSelEnd == pefw->iSelStart )
{
WinSendMsg(pefw->hwndPopupEdit, MM_SETITEMATTR, MPFROM2SHORT(IDM_CUT, TRUE),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
WinSendMsg(pefw->hwndPopupEdit, MM_SETITEMATTR, MPFROM2SHORT(IDM_COPY, TRUE),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
}
else
{
WinSendMsg(pefw->hwndPopupEdit, MM_SETITEMATTR, MPFROM2SHORT(IDM_CUT, TRUE),
MPFROM2SHORT(MIA_DISABLED, 0));
WinSendMsg(pefw->hwndPopupEdit, MM_SETITEMATTR, MPFROM2SHORT(IDM_COPY, TRUE),
MPFROM2SHORT(MIA_DISABLED, 0));
}
WinPopupMenu(hWnd, hWnd, pefw->hwndPopupEdit, SHORT1FROMMP(mp1), SHORT2FROMMP(mp1), IDM_CUT,
PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_VCONSTRAIN | PU_HCONSTRAIN);
}
break;
/*********************************************************************/
/* Button 2 clicked */
/* Button 3 clicked */
/*********************************************************************/
case WM_BUTTON2DBLCLK :
case WM_BUTTON3DOWN :
case WM_BUTTON3DBLCLK :
WinSetActiveWindow(HWND_DESKTOP, hWnd);
break;
/*********************************************************************/
/* Process mouse movement over the entry field */
/*********************************************************************/
case WM_MOUSEMOVE :
/* Get the entry field information pointer from */
/* the reserved memory of the window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Send the WM_CONTROLPOINTER message to the */
/* owner of the control to allow the owner of */
/* control to change the pointer shape from the */
/* current defined arrow shape */
if ( WinIsWindowEnabled(hWnd) )
WinSetPointer(HWND_DESKTOP,
(HPOINTER)WinSendMsg(pefw->hwndOwner,
WM_CONTROLPOINTER,
MPFROMLONG(pefw->id),
MPFROMLONG(pefw->hptr)));
/* Check to see if the mouse left button is */
/* depressed which means the user is drag- */
/* selecting the text within the entry field */
if ( pefw->fBtnDown )
/* Check to see if any text contained within the */
/* entry field. When no text in the entry field */
/* the dragging should be ignored since there is */
/* nothing to select. */
if ( pefw->cText )
{
/* Check to se if the mouse pointer is within */
/* the bounds of the entry field horizontally */
/* which means the timer scroll is no longer */
/* needed since the points can be mapped with */
/* the current mouse pointer position */
if ( ((LONG)(SHORT)SHORT1FROMMP(mp1) >= pefw->rcl.xLeft) &&
((LONG)(SHORT)SHORT1FROMMP(mp1) <= pefw->rcl.xRight) )
{
/* Check to see if the scroll timer is being */
/* used and if the case, turn it off */
if ( pefw->fTimer )
{
WinStopTimer(pefw->hAB, hWnd, TID_SCROLL);
pefw->fTimer = FALSE;
}
}
else
/* Mouse pointer is not within the horizontal */
/* bounds of the entry field, turn on the scroll */
/* timer only if auto scrolling is specified for */
/* the control */
if ( pefw->flStyle & ES_AUTOSCROLL )
{
/* Start the timer off slowly for the start of */
/* scrolling and faster if scrolling has already */
/* be started */
WinStartTimer(pefw->hAB, hWnd, TID_SCROLL,
pefw->fScrollStart ? pefw->ulScrollRateStart : pefw->ulScrollRate);
pefw->fTimer = TRUE;
}
/* Check the current selected character against */
/* the recorded one and if different, reflect */
/* the selection change and move the cursor to */
/* the new location */
if ( (iSelCurrent = lFindCharacterIndex(pefw, (LONG)(SHORT)SHORT1FROMMP(mp1))) != pefw->iSel )
{
SelectText(pefw, pefw->iAnchor, iSelCurrent);
FINDCHARACTER((LONG)(SHORT)SHORT1FROMMP(mp1));
ShowCursor(pefw, pefw->iAnchor);
}
}
return(MRFROMLONG(TRUE));
/*********************************************************************/
/* Process timer notification */
/*********************************************************************/
case WM_TIMER :
/* Check to make sure that the timer is the */
/* scroll timer for the entry field when mouse */
/* capture has been started during the drag */
/* operation of the mouse and the mouse pointer */
/* is outside the entry field display area */
if ( SHORT1FROMMP(mp1) == TID_SCROLL )
{
/* Get the address of the control info from the */
/* control's reserved memory */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Get the current mouse pointer position */
WinQueryPointerPos(HWND_DESKTOP, &ptl);
/* Convert the mouse pointer position, which is */
/* in desktop co-ordinates to the entry field */
/* co-ordinates */
WinMapWindowPoints(HWND_DESKTOP, hWnd, &ptl, 1L);
/* Check to see if the mouse pointer is inside */
/* the display rectangle in which case the timer */
/* should be stopped to allow the normal */
/* mouse handling to be performed */
if ( WinPtInRect(pefw->hAB, &pefw->rcl, &ptl) )
{
pefw->fTimer = FALSE;
WinStopTimer(pefw->hAB, hWnd, TID_SCROLL);
}
else
{
/* Check to see if this is the starting of the */
/* timer scrolling in which case the scrolling */
/* rate should be made faster */
if ( pefw->fScrollStart )
{
if ( pefw->fTimer )
{
WinStopTimer(pefw->hAB, hWnd, TID_SCROLL);
WinStartTimer(pefw->hAB, hWnd, TID_SCROLL,
pefw->ulScrollRate);
}
pefw->fScrollStart = FALSE;
}
/* Check to see if the mouse pointer is to the */
/* right of the entry field which means that */
/* scrolling is being performed from left to */
/* right */
if ( ptl.x > pefw->rcl.xRight )
/* Check to see if there is any text further to */
/* right edge of the entry field that cannot be */
/* seen and should be scrolled */
if ( FALLOWSCROLLRIGHT(pefw) )
{
/* Scrolling of text required, update the offset */
/* shift factor making sure that it does not go */
/* beyond the end of the text */
if ( (pefw->iOffset += pefw->cScroll) > pefw->cText )
pefw->iOffset = pefw->cText;
/* Update the selection end point making sure */
/* that it does not go beyond the end of the */
/* text */
if ( (pefw->iSelEnd += pefw->cScroll) > pefw->cText )
pefw->iSelEnd = pefw->cText;
/* Get the presentation space handle for the */
/* entry field and place the colour table into */
/* RGB mode before drawing the selected text */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
/* Inform the owner of the entry field that the */
/* contents have been scrolled */
mrNotifyEFOwner(pefw, EN_SCROLL);
/* Move the cursor to the new location */
ShowCursor(pefw, pefw->iAnchor);
}
else
/* No scrolling required but check to make sure */
/* the end selection point is shifted */
if ( pefw->iSelEnd < pefw->cText )
{
/* Update the end point for the newly selected */
/* text */
++pefw->iSelEnd;
/* Get the presentation space handle for the */
/* entry field and place the colour table into */
/* RGB mode before drawing the selected text */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
ShowCursor(pefw, pefw->iAnchor);
}
else
/* No further selection necessary, but make sure */
/* that the selection point is at the end of the */
/* selection field */
pefw->iSel = pefw->iSelEnd;
else
/* Mouse is to the left of the entry field, */
/* scrolling is being performed from the right */
/* to left. Check to make sure that further */
/* scrolling can be permitted to the left. */
if ( pefw->iOffset )
{
/* Scrolling of text required, update the offset */
/* shift factor making sure that it does not go */
/* beyond the start of the text */
if ( (pefw->iOffset -= pefw->cScroll) < 0 )
pefw->iOffset = 0L;
/* Update the selection end point making sure */
/* that it does not go beyond the start of the */
/* text */
if ( (pefw->iSelStart -= pefw->cScroll) < 0 )
pefw->iSelStart = 0L;
/* Get the presentation space handle for the */
/* entry field and place the colour table into */
/* RGB mode before drawing the selected text */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
/* Inform the owner of the entry field that the */
/* contents have been scrolled */
mrNotifyEFOwner(pefw, EN_SCROLL);
/* Move the cursor to the new location */
ShowCursor(pefw, pefw->iAnchor);
}
else
pefw->iSel = pefw->iSelStart;
}
}
else
/* Check to see if the timer is for the flashing */
/* of the cursor in which case make sure that */
/* the message gets through to the default */
/* window procedure otherwise it will not flash */
if ( SHORT1FROMMP(mp1) == TID_CURSOR )
return(WinDefWindowProc(hWnd, msg, mp1, mp2));
break;
/*********************************************************************/
/* Popup Menu Selections */
/*********************************************************************/
case WM_COMMAND :
switch ( SHORT1FROMMP(mp1) )
{
case IDM_CUT :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Allocate the shared memory for the text */
/* making sure that there is enough memory for */
/* the text plus the NULL terminating byte */
DosAllocSharedMem((PPVOID)(PVOID)&pchClipText, NULL,
(ULONG)(pefw->iSelEnd -
pefw->iSelStart + 1),
fALLOCSHR);
/* Open and empty the clipboard before copying */
/* the selected text to the shared memory */
/* and placing the pointer on the clipboard */
WinOpenClipbrd(pefw->hAB);
WinEmptyClipbrd(pefw->hAB);
WinSetClipbrdData(pefw->hAB,
(ULONG)pszCopyText(pefw,
pchClipText,
pefw->iSelStart,
pefw->iSelEnd),
CF_TEXT, CFI_POINTER);
/* Close the clipboard to allow the copied text */
/* to be used by other processes as well as this */
/* one */
WinCloseClipbrd(pefw->hAB);
/* Delete the selected text */
DeleteText(pefw, pefw->iSelStart,
pefw->iSelEnd, TRUE);
break;
case IDM_COPY :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Allocate the shared memory for the text */
/* making sure that there is enough memory for */
/* the text plus the NULL terminating byte */
DosAllocSharedMem((PPVOID)(PVOID)&pchClipText, NULL,
(ULONG)(pefw->iSelEnd -
pefw->iSelStart + 1),
fALLOCSHR);
/* Open and empty the clipboard before copying */
/* the selected text to the shared memory */
/* and placing the pointer on the clipboard */
WinOpenClipbrd(pefw->hAB);
WinEmptyClipbrd(pefw->hAB);
WinSetClipbrdData(pefw->hAB,
(ULONG)pszCopyText(pefw,
pchClipText,
pefw->iSelStart,
pefw->iSelEnd),
CF_TEXT, CFI_POINTER);
/* Close the clipboard to allow the copied text */
/* to be used by other processes as well as this */
/* one */
WinCloseClipbrd(pefw->hAB);
break;
case IDM_PASTE :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Open the clipboard and then check to see if */
/* any text has been placed on it that can be */
/* pasted within the entry field */
WinOpenClipbrd(pefw->hAB);
/* Text contained within the clipboard, get the */
/* pointer to the text */
if ( (pchClipText = (PCHAR)WinQueryClipbrdData(pefw->hAB, CF_TEXT)) != NULL )
/* Check to make sure that the selection within */
/* the clipboard will fit within the entry field */
if ( ((n = (LONG)strlen(pchClipText)) + pefw->cText - (pefw->iSelEnd - pefw->iSelStart)) < pefw->cLimit )
{
/* Check to see if any text is currently */
/* selected which means that the text should be */
/* replaced by the text from the clipboard. If */
/* the case, delete the selected text. */
if ( pefw->iSelStart != pefw->iSelEnd )
DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, FALSE);
/* Paste the text into the entry field at the */
/* current selection point */
PasteText(pefw, pchClipText, n);
}
/* Finished with the clipboard, close it */
WinCloseClipbrd(pefw->hAB);
break;
}
break;
/************************************************************************/
/************************************************************************/
/* */
/* Part 4: Keyboard interface */
/* */
/************************************************************************/
/************************************************************************/
/************************************************************************/
/************************************************************************/
/* */
/************************************************************************/
/************************************************************************/
/* The keystrokes processed by an entry field control are: */
/* */
/* Left arrow Move the cursor one character to the left. */
/* Right arrow Move the cursor one character to the right. */
/* Shift+Left arrow Extend the selection by one character to the */
/* left. */
/* Shift+Right arrow Extend the selection by one character to the */
/* right. */
/* Home Move the cursor to the beginning of the text.*/
/* End Move the cursor to the end of the text. */
/* Backspace Delete the character to the left of the */
/* cursor. */
/* Delete When the selection is an insertion point, */
/* delete the character to the right of the */
/* cursor, otherwise delete the current */
/* selection, but do not put it in the */
/* clipboard. */
/* Shift+Del Cut the current selection to the clipboard. */
/* Shift+Ins Replace the current selection with the text */
/* contents from the clipboard. */
/* Ctrl+Del Delete to the end of the field. */
/* Ctrl+Ins Copy the current selection to the clipboard. */
/* */
/* If the control contains more text than can be shown, the */
/* actions defined above that move the cursor cause the text to be */
/* scrolled. The amount of scrolling varies from key to key, and */
/* the position of the text within the control varies for the same */
/* cursor position. */
/************************************************************************/
/************************************************************************/
/* */
/************************************************************************/
/************************************************************************/
/*********************************************************************/
/* Key being pressed */
/*********************************************************************/
/* Keyboard character received */
case WM_CHAR :
/* Only act on key down requests therefore if a */
/* key up event, ignore it */
if ( CHARMSG(&msg)->fs & KC_KEYUP )
break;
/* Check for virtual key presses first */
if ( CHARMSG(&msg)->fs & KC_VIRTUALKEY )
switch ( CHARMSG(&msg)->vkey )
{
/*********************************************************/
/*********************************************************/
/* Home */
/*********************************************************/
/*********************************************************/
case VK_HOME :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Check to see if an offset shift being used */
/* and if there is, set it along with the */
/* selections to the first character in the text */
/* string and redraw the text in the entry field */
if ( pefw->iOffset )
{
pefw->iOffset = pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = pefw->iSel = 0L;
/* Get a presentation space handle for the entry */
/* field, turn the colour table to RGB mode and */
/* redraw the entry field text */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
mrNotifyEFOwner(pefw, EN_SCROLL);
}
else
/* No offset shift being used, but check to see */
/* if any text has been selected in which case */
/* it needs to be deselected and the selection */
/* placed at the first character in the text */
/* string forcing the text to be redrawn as well */
if ( pefw->iSelStart != pefw->iSelEnd )
{
pefw->iOffset = pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = pefw->iSel = 0L;
/* Get a presentation space handle for the entry */
/* field, turn the colour table to RGB mode and */
/* redraw the entry field text */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
}
else
/* No shift offset or text is selected, just */
/* make sure that the cursor is at the beginning */
/* of the entry field */
pefw->iSel = 0L;
ShowCursor(pefw, 0L);
return(MRFROMLONG(TRUE));
/*********************************************************/
/*********************************************************/
/* End */
/*********************************************************/
/*********************************************************/
case VK_END :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Check to see if the right part of the text */
/* within the entry field is visible and if it */
/* isn't, scroll the text to make it visible */
if ( pefw->aptl[pefw->cText].x > pefw->rclText.xRight )
{
/* Set the cursor selection point to be just */
/* after the last character in the text string */
pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = pefw->iSel = pefw->cText;
/* Determine the offset value that should be */
/* used making sure that it is within limits */
if ( (pefw->iOffset = pefw->cText - pefw->cScroll * 2L) < 0L )
pefw->iOffset = 0L;
/* Get a presentation space handle for the entry */
/* field, turn the colour table to RGB mode and */
/* redraw the entry field text */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
mrNotifyEFOwner(pefw, EN_SCROLL);
}
else
if ( pefw->iSelStart != pefw->iSelEnd )
{
pefw->iSelStart = pefw->iSelEnd = pefw->iAnchor = pefw->iSel = pefw->cText;
pefw->iOffset = 0L;
/* Get a presentation space handle for the entry */
/* field, turn the colour table to RGB mode and */
/* redraw the entry field text */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
}
else
/* No shift offset or text is selected, just */
/* make sure that the cursor is at the end of */
/* entry field */
pefw->iSel = pefw->cText;
ShowCursor(pefw, pefw->cText);
return(MRFROMLONG(TRUE));
/*********************************************************/
/*********************************************************/
/* Backspace */
/*********************************************************/
/*********************************************************/
case VK_BACKSPACE :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Check to see if the entry field is read-only */
/* which means that any editing requests have to */
/* be ignored */
if ( pefw->fReadOnly )
return(MRFROMLONG(FALSE));
else
{
/* Check to see if any text has been selected */
/* which in this case, the backspace operates */
/* exactly like the Del key, only the selected */
/* text is deleted */
if ( pefw->iSelStart != pefw->iSelEnd )
DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, TRUE);
else
/* No text has been selected, delete the */
/* character that reside prior to the cursor */
/* location unless the cursor is at the */
/* beginning of the text */
if ( pefw->iSel )
DeleteText(pefw, pefw->iSel - 1, pefw->iSel, TRUE);
ShowCursor(pefw, pefw->iSel);
return(MRFROMLONG(TRUE));
}
/*********************************************************/
/*********************************************************/
/* Del */
/* Ctrl+Del */
/* Shift+Del */
/*********************************************************/
/*********************************************************/
case VK_DELETE :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Check to see if the entry field is read-only */
/* which means that any editing requests have to */
/* be ignored */
if ( pefw->fReadOnly )
return(MRFROMLONG(FALSE));
else
{
/* Check to see if Ctrl+Del is being pressed, */
/* which means that the text from the cursor */
/* position to the end of the text string should */
/* be deleted */
if ( CHARMSG(&msg)->fs & KC_CTRL )
DeleteText(pefw, pefw->iSelStart, pefw->cText, TRUE);
else
/* Check to see if the Shift+Del is being */
/* pressed, which is the convention for cutting */
/* text from the entry field */
if ( (CHARMSG(&msg)->fs & KC_SHIFT) &&
(pefw->iSelStart != pefw->iSelEnd) )
{
/* Allocate the shared memory for the text */
/* making sure that there is enough memory for */
/* the text plus the NULL terminating byte */
DosAllocSharedMem((PPVOID)(PVOID)&pchClipText, NULL,
(ULONG)(pefw->iSelEnd -
pefw->iSelStart + 1),
fALLOCSHR);
/* Open and empty the clipboard before copying */
/* the selected text to the shared memory */
/* and placing the pointer on the clipboard */
WinOpenClipbrd(pefw->hAB);
WinEmptyClipbrd(pefw->hAB);
WinSetClipbrdData(pefw->hAB,
(ULONG)pszCopyText(pefw,
pchClipText,
pefw->iSelStart,
pefw->iSelEnd),
CF_TEXT, CFI_POINTER);
/* Close the clipboard to allow the copied text */
/* to be used by other processes as well as this */
/* one */
WinCloseClipbrd(pefw->hAB);
/* Delete the selected text */
DeleteText(pefw, pefw->iSelStart,
pefw->iSelEnd, TRUE);
}
else
/* Just the Del key is being pressed, check to */
/* see if any text is selected which is to be */
/* deleted */
if ( pefw->iSelStart != pefw->iSelEnd )
DeleteText(pefw, pefw->iSelStart,
pefw->iSelEnd, TRUE);
else
/* No text has been selected, just delete the */
/* character immediately to the right of the */
/* cursor */
DeleteText(pefw, pefw->iSel,
pefw->iSel + 1, TRUE);
ShowCursor(pefw, pefw->iSel);
return(MRFROMLONG(TRUE));
}
/*********************************************************/
/*********************************************************/
/* Left */
/*********************************************************/
/*********************************************************/
case VK_LEFT :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
if ( pefw->iSel )
{
if ( (pefw->aptl[--pefw->iSel].x - pefw->aptl[pefw->iOffset].x) < EFMARGIN_LEFT )
{
if ( (pefw->iOffset -= pefw->cScroll) < 0L )
pefw->iOffset = 0L;
/* Get a presentation space handle for the entry */
/* field, turn the colour table to RGB mode and */
/* redraw the entry field text */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
mrNotifyEFOwner(pefw, EN_SCROLL);
}
else
if ( pefw->fOvertype && (pefw->iSelStart == pefw->iSelEnd) )
DrawOvertypeText(pefw, EFMOVE_LEFT);
ShowCursor(pefw, pefw->iSel);
}
return(MRFROMLONG(TRUE));
/*********************************************************/
/*********************************************************/
/* Right */
/*********************************************************/
/*********************************************************/
case VK_RIGHT :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
if ( pefw->iSel < pefw->cText )
{
if ( (pefw->aptl[++pefw->iSel].x - pefw->aptl[pefw->iOffset].x) > pefw->rclText.xRight )
{
if ( FALLOWSCROLLRIGHT(pefw) )
{
if ( (pefw->iOffset += pefw->cScroll) > pefw->cText )
pefw->iOffset = pefw->cText;
/* Get a presentation space handle for the entry */
/* field, turn the colour table to RGB mode and */
/* redraw the entry field text */
GpiCreateLogColorTable(pefw->hPS = WinGetPS(pefw->hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawText(pefw);
WinReleasePS(pefw->hPS);
mrNotifyEFOwner(pefw, EN_SCROLL);
}
}
else
if ( pefw->fOvertype && (pefw->iSelStart == pefw->iSelEnd) )
DrawOvertypeText(pefw, EFMOVE_RIGHT);
ShowCursor(pefw, pefw->iSel);
}
return(MRFROMLONG(TRUE));
/*********************************************************/
/*********************************************************/
/* Ins */
/* Ctrl+Ins */
/* Shift+Ins */
/*********************************************************/
/*********************************************************/
case VK_INSERT :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Check to make sure that a selection within */
/* the text has been made before trying to copy */
/* the selection to the clipboard */
if ( (CHARMSG(&msg)->fs & KC_CTRL) &&
(pefw->iSelEnd != pefw->iSelStart) )
{
/* Check to see if the entry field is unreadable */
/* which means that it is being used for some- */
/* thing like a password entry area. In this */
/* case do not allow the text to be copied to */
/* the clipboard. (Note: this differs from */
/* the OS/2 entry field in that it will allow */
/* you to copy the text to the clipboard) */
if ( pefw->flStyle & ES_UNREADABLE )
WinAlarm(HWND_DESKTOP, WA_ERROR);
else
{
/* Allocate the shared memory for the text */
/* making sure that there is enough memory for */
/* the text plus the NULL terminating byte */
DosAllocSharedMem((PPVOID)(PVOID)&pchClipText, NULL,
(ULONG)(pefw->iSelEnd - pefw->iSelStart + 1), fALLOCSHR);
/* Open and empty the clipboard before copying */
/* the selected text to the shared memory */
/* and placing the pointer on the clipboard */
WinOpenClipbrd(pefw->hAB);
WinEmptyClipbrd(pefw->hAB);
WinSetClipbrdData(pefw->hAB,
(ULONG)pszCopyText(pefw, pchClipText, pefw->iSelStart, pefw->iSelEnd),
CF_TEXT, CFI_POINTER);
/* Close the clipboard to allow the copied text */
/* to be used by other processes as well as this */
/* one */
WinCloseClipbrd(pefw->hAB);
}
}
else
/* Check to see if the entry field is read-only */
/* which means that any editing requests have to */
/* be ignored */
if ( (CHARMSG(&msg)->fs & KC_SHIFT) && !pefw->fReadOnly )
{
/* Open the clipboard and then check to see if */
/* any text has been placed on it that can be */
/* pasted within the entry field */
WinOpenClipbrd(pefw->hAB);
if ( WinQueryClipbrdData(pefw->hAB, CF_TEXT) )
/* Text contained within the clipboard, get the */
/* pointer to the text */
if ( (pchClipText = (PCHAR)WinQueryClipbrdData(pefw->hAB, CF_TEXT)) != NULL )
/* Check to make sure that the selection within */
/* the clipboard will fit within the entry field */
if ( ((n = (LONG)strlen(pchClipText)) + pefw->cText -
(pefw->iSelEnd - pefw->iSelStart)) < pefw->cLimit )
{
/* Check to see if any text is currently */
/* selected which means that the text should be */
/* replaced by the text from the clipboard. If */
/* the case, delete the selected text. */
if ( pefw->iSelStart != pefw->iSelEnd )
DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd, FALSE);
/* Paste the text into the entry field at the */
/* current selection point */
PasteText(pefw, pchClipText, n);
}
/* Finished with the clipboard, close it */
WinCloseClipbrd(pefw->hAB);
}
else
{
if ( pefw->fOvertype )
{
pefw->fOvertype = FALSE;
if ( pefw->iSelStart == pefw->iSelEnd )
{
GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawSubText(pefw, pefw->iSel, pefw->iSel + 1);
WinReleasePS(pefw->hPS);
}
}
else
{
pefw->fOvertype = TRUE;
if ( pefw->iSelStart == pefw->iSelEnd )
{
GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
DrawSubText(pefw, pefw->iSel, pefw->iSel + 1);
WinReleasePS(pefw->hPS);
}
mrNotifyEFOwner(pefw, EN_INSERTMODETOGGLE);
}
}
return(WinDefWindowProc(hWnd, msg, mp1, mp2));
/*********************************************************/
/*********************************************************/
/* Down */
/* Up */
/*********************************************************/
/*********************************************************/
case VK_DOWN :
case VK_UP :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Down or up arrow key pressed, determine */
/* which control is the previous/next entry and */
/* set the focus on that control */
WinSetFocus(HWND_DESKTOP,
WinEnumDlgItem(pefw->hwndOwner, hWnd,
(ULONG)(CHARMSG(&msg)->vkey == VK_DOWN ?
EDI_NEXTGROUPITEM :
EDI_PREVGROUPITEM)));
return(MRFROMLONG(TRUE));
/*********************************************************/
/*********************************************************/
/* Tab */
/* Shift+Tab */
/*********************************************************/
/*********************************************************/
case VK_TAB :
case VK_BACKTAB :
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* TAB or Shift+TAB key pressed, determine which */
/* control is the previous/next tab stop and set */
/* the focus on that control */
WinSetFocus(HWND_DESKTOP,
WinEnumDlgItem(pefw->hwndOwner, hWnd,
(ULONG)(CHARMSG(&msg)->vkey == VK_TAB ?
EDI_NEXTTABITEM :
EDI_PREVTABITEM)));
return(MRFROMLONG(TRUE));
}
else
/* Process normal character input */
if ( CHARMSG(&msg)->fs & KC_CHAR )
{
/* Get the entry field data pointer from the */
/* window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Check to see if the entry field is read-only */
/* which means that any editing requests have to */
/* be ignored */
if ( pefw->fReadOnly )
return(MRFROMLONG(FALSE));
else
{
/* Check to see if the entry field input limit */
/* has been met in which case the keystroke */
/* should simply be discarded if the owner of */
/* control does not return a TRUE response to */
/* the overflow notification */
if ( pefw->cText >= pefw->cLimit )
if ( LONGFROMMR(mrNotifyEFOwner(pefw, EN_OVERFLOW)) == TRUE )
{
if ( pefw->cText >= pefw->cLimit )
{
WinAlarm(HWND_DESKTOP, WA_ERROR);
return(MRFROMLONG(TRUE));
}
}
else
{
WinAlarm(HWND_DESKTOP, WA_ERROR);
return(MRFROMLONG(TRUE));
}
/* Check to see if any text has been selected */
/* which means that the selected text is */
/* to be replaced with the keystroke character */
if ( pefw->iSelStart != pefw->iSelEnd )
DeleteText(pefw, pefw->iSelStart, pefw->iSelEnd,
FALSE);
else
/* No preselected text, now check to see if the */
/* entry field is in overtype mode which means */
/* that the character immediately to the right */
/* of the cursor is to be replaced with the */
/* keystroke character */
if ( pefw->fOvertype && (pefw->iSel < pefw->cText) )
DeleteText(pefw, pefw->iSel, pefw->iSel + 1L,
FALSE);
/* Save the keystroke within the text buffer */
/* and then insert the text into the entry */
/* field */
pefw->szInput[0] = (BYTE)CHARMSG(&msg)->chr;
PasteText(pefw, pefw->szInput, 1L);
/* Check to see if the text limit has been */
/* reached in which case the auto tab style */
/* should be checked for and if present, cause */
/* the focus to move from the entry field to the */
/* next tabable control */
if ( (pefw->flStyle & ES_AUTOTAB) &&
(pefw->cText == pefw->cLimit) )
WinSetFocus(HWND_DESKTOP,
WinEnumDlgItem(pefw->hwndOwner, hWnd,
EDI_NEXTTABITEM));
return(MRFROMLONG(TRUE));
}
}
return(WinDefWindowProc(hWnd, msg, mp1, mp2));
/************************************************************************/
/************************************************************************/
/* */
/* Part 5: Control messages */
/* */
/************************************************************************/
/************************************************************************/
/*********************************************************************/
/* Base messages */
/*********************************************************************/
case EM_QUERYCHANGED :
case EM_QUERYSEL :
case EM_SETSEL :
case EM_SETTEXTLIMIT :
case EM_CUT :
case EM_COPY :
case EM_CLEAR :
case EM_PASTE :
case EM_QUERYFIRSTCHAR :
case EM_SETFIRSTCHAR :
case EM_QUERYREADONLY :
case EM_SETREADONLY :
case EM_SETINSERTMODE :
mrBaseFieldHandler(hWnd, msg, mp1, mp2);
break;
/*********************************************************************/
/* Extended messages */
/*********************************************************************/
/************************************************************************/
/************************************************************************/
/* */
/* Part 6: Text manipulation */
/* */
/************************************************************************/
/************************************************************************/
/*********************************************************************/
/* Process window parameters query */
/*********************************************************************/
case WM_QUERYWINDOWPARAMS :
/* Get the address for the windows parameters */
/* structure */
if ( (pwprm = (PWNDPARAMS)PVOIDFROMMP(mp1)) != NULL )
{
/* Register exception handler that is used for */
/* the lazy pointer validation tests */
xcptregr.prev_structure = NULL;
xcptregr.ExceptionHandler = &EntryFieldExceptionHandler;
DosSetExceptionHandler(&xcptregr);
if ( !setjmp(jBuf) )
{
/* Text length being asked for, get the address */
/* of the text string stored in the heap */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Determine the type of query */
if ( pwprm->fsStatus & WPM_TEXT )
{
if ( pefw->flStyle & ES_UNREADABLE )
memcpy(pwprm->pszText, pefw->szPassword, (UINT)pefw->cText);
else
memcpy(pwprm->pszText, pefw->szText, (UINT)pefw->cText);
pefw->fChanged = FALSE;
}
if ( pwprm->fsStatus & WPM_CCHTEXT )
{
/* Place the length the string within the */
/* structure */
pwprm->cchText = (ULONG)pefw->cText;
pefw->fChanged = FALSE;
}
if ( pwprm->fsStatus & WPM_CBCTLDATA )
{
/* Set the control data length to zero */
pwprm->cbCtlData = 0;
pefw->fChanged = FALSE;
}
}
/* Remove the exception handle since the lazy */
/* pointer evaluation is done */
DosUnsetExceptionHandler(&xcptregr);
return(MRFROMLONG(TRUE));
}
break;
/* Process window parameters setting */
case WM_SETWINDOWPARAMS :
/* Get the address for the windows parameters */
/* structure */
if ( (pwprm = (PWNDPARAMS)PVOIDFROMMP(mp1)) != NULL )
{
/* Register exception handler that is used for */
/* the lazy pointer validation tests */
xcptregr.prev_structure = NULL;
xcptregr.ExceptionHandler = &EntryFieldExceptionHandler;
DosSetExceptionHandler(&xcptregr);
if ( !setjmp(jBuf) )
{
/* Check to see if the text for the control is */
/* being set */
if ( pwprm->fsStatus & WPM_TEXT )
{
/* Text being set, get the address of the text */
/* string stored in the heap */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Check to see if any text is being set */
if ( pwprm->cchText )
/* Check to make sure that the text that is to */
/* be set is not greater than the memory */
/* allocated */
if ( pwprm->cchText > 1023UL )
{
memcpy(pefw->szText, pwprm->pszText, 1023);
pefw->szText[pefw->cText = 1023] = 0;
}
else
{
memcpy(pefw->szText, pwprm->pszText, pwprm->cchText);
pefw->szText[pefw->cText = (LONG)pwprm->cchText] = 0;
}
else
/* No text is being set, clear any existing text */
pefw->szText[pefw->cText = 0L] = 0;
GpiCreateLogColorTable(pefw->hPS = WinGetPS(hWnd),
0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
QueryCharPoints(pefw);
DrawText(pefw);
WinReleasePS(pefw->hPS);
mrNotifyEFOwner(pefw, EN_CHANGE);
}
}
/* Remove the exception handle since the lazy */
/* pointer evaluation is done */
DosUnsetExceptionHandler(&xcptregr);
}
break;
/************************************************************************/
/************************************************************************/
/* */
/* Part 7: Painting and display */
/* */
/************************************************************************/
/************************************************************************/
/*********************************************************************/
/* System colour/Presentation parameter change */
/*********************************************************************/
case WM_SYSCOLORCHANGE :
case WM_PRESPARAMCHANGED :
/* Get the Entry Field data pointer from the window */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Presentation parameters or system colours */
/* have changed, get the new values for the */
/* colours */
pefw->lClrText = lGetPresParam(hWnd, PP_FOREGROUNDCOLOR,
PP_FOREGROUNDCOLORINDEX,
SYSCLR_OUTPUTTEXT);
pefw->lClrBorder = lGetPresParam(hWnd, PP_BORDERCOLOR,
PP_BORDERCOLORINDEX,
SYSCLR_BUTTONDARK);
pefw->lClrBackground = lGetPresParam(hWnd, PP_BACKGROUNDCOLOR,
PP_BACKGROUNDCOLORINDEX,
SYSCLR_ENTRYFIELD);
pefw->lClrHilite = lGetPresParam(hWnd, PP_HILITEFOREGROUNDCOLOR,
PP_HILITEFOREGROUNDCOLORINDEX,
SYSCLR_HILITEFOREGROUND);
pefw->lClrHiliteBackground = lGetPresParam(hWnd, PP_HILITEBACKGROUNDCOLOR,
PP_HILITEBACKGROUNDCOLORINDEX,
SYSCLR_HILITEBACKGROUND);
/* Refresh the metrics for the control */
pefw->hPS = WinGetPS(hWnd);
RefreshMetrics(pefw);
WinReleasePS(pefw->hPS);
/* Cause the control to be repainted if it is */
/* visible */
if ( WinIsWindowShowing(hWnd) )
WinInvalidateRect(hWnd, &pefw->rcl, FALSE);
break;
/*********************************************************************/
/* Paint control */
/*********************************************************************/
case WM_PAINT :
/* Get the address of the control info from the */
/* control's reserved memory */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
/* Set the colour table to RGB mode */
if ( (pefw->hPS = WinBeginPaint(hWnd, (HPS)NULL, &rclPaint)) != (HPS)NULL )
{
/* Check to see if a style change has occurred */
/* and if the case, save the new style */
/* internally and refresh the control metrics */
if ( ((flStyle = WinQueryWindowULong(hWnd, QWL_STYLE)) &
0x0000ffffUL) != (pefw->flStyle & 0x0000ffffUL) )
{
pefw->flStyle = flStyle;
RefreshMetrics(pefw);
}
/* Place the colour table into RGB mode */
GpiCreateLogColorTable(pefw->hPS, 0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);
/* Erase the rectangle for the control */
WinFillRect(pefw->hPS, &pefw->rcl, pefw->lClrBackground);
/* Check to see if a margin for the entry field */
/* is desired and if so, draw it */
if ( pefw->flStyle & ES_MARGIN )
{
/* First set the colour of the border and then */
/* draw the inside edge of the border. The */
/* border follows the typical 3D effect of */
/* one line being dark and the second line being */
/* light. */
GpiSetColor(pefw->hPS, RGB_WHITE);
GpiMove(pefw->hPS, pefw->aptlInside);
GpiPolyLine(pefw->hPS, 4L, &pefw->aptlInside[1]);
/* Having drawn the inside edge, now draw the */
/* outside edge of the border */
GpiSetColor(pefw->hPS, pefw->lClrBorder);
GpiMove(pefw->hPS, pefw->aptlOutside);
GpiPolyLine(pefw->hPS, 4L, &pefw->aptlOutside[1]);
}
/* Check to see if any text needs to be drawn */
/* and if present, draw it */
if ( pefw->szText[0] )
DrawText(pefw);
WinEndPaint(pefw->hPS);
}
break;
/************************************************************************/
/************************************************************************/
/* */
/* Part 8: Control destruction coding */
/* */
/************************************************************************/
/************************************************************************/
/*********************************************************************/
/* Control being destroyed, perform clean-up */
/*********************************************************************/
case WM_DESTROY :
/* Get the address of the control info from the */
/* control's reserved memory and release the */
/* heap. */
pefw = (PENTRYFWIN)WinQueryWindowPtr(hWnd, QUCWP_WNDP);
if ( pefw->hwndPopupEdit )
WinDestroyWindow(pefw->hwndPopupEdit);
HeapRelease(pefw->hHeap);
break;
/* Default message processing */
default :
return(WinDefWindowProc(hWnd, msg, mp1, mp2));
}
return(0L);
}