Wed Jan 31 10:58:00 1996 Alexandre Julliard <julliard@sunsite.unc.edu> * [configure.in] Added --with-dll option to build libwine.so. * [controls/listbox.c] Fixed ListBoxDirectory(), DlgDirSelect() and DlgDirList(). Hopefully their behavior is correct now. * [controls/menu.c] Use SEGPTRs in ChangeMenu(), InsertMenu(), AppendMenu() and ModifyMenu() for the item data, to avoid corrupting the pointer for owner-drawn items. * [controls/static.c] Attempt to load OEM icons for SS_ICON controls. Probably not entirely correct. Don't clip the text output. * [files/directory.c] Add temp dir and Windows dir to environment. * [files/dos_fs.c] Fixed a few path handling bugs in DOSFS_GetUnixFileName(). Cache last used directory in DOSFS_FindNext() to avoid quadratic search time. * [files/drive.c] New format for drives configuration in wine.conf; allows specifying the type, label and serial number of a drive. * [files/file.c] New function FILE_OpenUnixFile to make sure we don't open a directory instead of a file. Fixed DOSFS_GetUnixFileName() check_last flag in FILE_MakeDir(). * [files/profile.c] Rewrote profile handling. Should be closer to Windows behavior now. New function PROFILE_GetWineIniString() to get a string from wine.conf. Support environment variables in wine.conf. * [loader/task.c] Fixed the order of deletion in TASK_DeleteTask() to avoid memory corruption. * [memory/global.c] Create a discarded block on GlobalAlloc() if the size is 0; thanks to John Harvey for noticing this. * [memory/local.c] LOCAL_GetHeap: make sure the pointer is valid before checking magic number. * [misc/main.c] Moved profile and registry saving to ExitWindows(), so we don't try to save them in case of a crash. * [miscemu/int21.c] INT21_GetFreeDiskSpace: try to compute the cluster size from the filesystem size instead of hard-coding it to 64. Fixed functions 0x3f and 0x40 to use _hread and _hwrite to allow reading or writing 65535 bytes (thanks to Bruce Milner for this one). * [windows/message.c] Fixed bug in linked-list handling in MSG_DeleteQueue(). Simplified SetMessageQueue(). * [wine.ini] [wine.man] Updated for new drives configuration format. Tue Jan 30 11:24:46 1996 William Magro <wmagro@tc.cornell.edu> * [controls/edit.c] Implemented ES_PASSWORD style, EM_SETPASSWORDCHAR and EM_GETPASSWORDCHAR messages. * [controls/widgets.c] Adjusted class creation flags to better match values Windows uses. * [include/windows.h] Fixed ES_NOHIDESEL typo. * [loader/ne_image.c] Added detection for zero offset in RADDR fixups. Quicken was in an infinite loop here. Mon Jan 29 20:12:22 1996 Albrecht Kleine <kleine@ak.sax.de> * [files/dos_fs.c] Bugfix: range error in month value (0..11 set to 1..12). * [windows/caret.c] Changed ROP2-mode to R2_NOTXORPEN in CARET_Callback for pulsed appearance of the caret. * [windows/mdi.c] [include/mdi.h] Changed MDITile(): added a new parameter WORD wParam for WM_MDITILE second tiling method (MDITILE_HORIZONTAL in wParam) as used in Win3.1 Sun Jan 28 14:20:00 1996 Cameron Heide <heide@ee.ualberta.ca> * [miscemu/int2f.c] Added a small bit of MSCDEX emulation. * [windows/alias.c] ALIAS_RegisterAlias was returning the hash value when it should have been returning the record number. Sat Jan 27 10:53:51 1996 Jim Peterson <jspeter@birch.ee.vt.edu> * [include/shell.h] [include/wintypes.h] Moved definition of HKEY and LPHKEY types to include/wintypes.h. Declared FONTENUMPROC in wintypes.h. * [include/windows.h] Added definition of KERNINGPAIR and LPKERNINGPAIR types. Added declarations for CopyCursor(), CopyIcon(), EnumFontFamilies(), ExtractIcon(), FatalAppExit(), FindExecutable(), GetClipCursor(), GetKerningPairs(), GetQueueStatus(), GetRasterizerCaps(), IsGDIObject(), IsMenu(), IsTask(), RegCloseKey(), RegCreateKey(), RegDeleteKey(), RegEnumKey(), RegOpenKey(), RegQueryValue(), RegSetValue(), ResetDC(), ShellExecute(), SystemParametersInfo(), and wsprintf(). * [tools/makehtml.pl] [documentation/apiw.index] New files that scan windows.h, commdlg.h, and toolhelp.h and output an HTML sorted list with optional links to www.willows.com and a tally of unimplemented APIW functions. * [objects/cursoricon.c] Added Win32 versions of CopyIcon() and CopyCursor() for use in libwine. * [win32/resource.c] [win32/winprocs.c] Added '#include "libres.h"' and explicit declarations of windows procs in order to avoid warnings. * [windows/utility.c] Added Win32 version of MulDiv() for libwine. * [*/*] [include/windows.h] Changed several function declarations to comply more strictly to the windows API (without, hopefully, altering their functionality). * [controls/menu.c] Made the return value of CheckMenuItem be the previous state of the menu item if it was found, otherwise -1 as specified in the SDK. This conflicts with the APIW specification, which says it should return TRUE if successful, otherwise FALSE. * [include/windows.h] Added obsolete WM_SIZE message wParam names for compatibility. Added WinHelp() command constants, even though they are not yet supported. * [rc/winerc.c] Tidied up transform_binary_file(). In argument checking, flattened any invalid characters specified with the prefix argument. * [library/libres.c] Made FindResource() case-insensitive when parameter 'name' is a string. Sat Jan 27 02:30 1996 Uwe Bonnes <bon@elektron.ikp.physik.th-darmstadt.de * [files/drive.c] If root "/" is given in wine.conf, use it as last resort. * [files/file.c] Report ER_AccessDenied it disk ist not writable More Debug Output * [miscemu/int21.c] Squeezed some bugs in ExtendedOpenCreateFile * [windows/winpos.c] Some windows may not be moved or resized. We are missing some structures to be exact, but the approach should help in some cases and make things worse in much fewer. Fri Jan 26 10:24:00 1996 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk> * [loader/pe_image.c] fixup_imports: Find builtins for Borland style entries, too Fri Jan 26 10:24:00 1996 Martin von Loewis <loewis@informatik.hu-berlin.de> * [controls/menu.c] LoadMenu: branch to Win32 for PE modules * [if1632/gdi.spec][if1632/kernel32.spec][if1632/user32.spec] DeleteObject, GetPixel, SetPixel,WritePrivateProfileStringA, WriteProfileStringA, EmptyClipboard, EnableMenuItem, EnableScrollBar, EnableWindow, InvalidateRect, SetWindowTextA, WinHelpA: new relays DrawTextA, MoveToEx, GetClientRect, InvalidateRect, LoadBitmapA/W, LoadAcceleratorsA/W, LoadMenu[Indirect]A/W, LoadStringA/W: changed to convert parameters or naming convention * [include/kernel32.h][include/wintypes.h] moved WCHAR, defined LPWSTR * [include/string32.h][win32/string32.c][include/struct32.h] New files * [loader/module.h] LoadModule: exit after returning from PE_LoadModule * [loader/pe_image.c] my_wcstombs: isascii does not work on Linux for Unicode PE_LoadImage: Handle directories * [misc/user32.c] USER32_RECT32to16, USER32_RECT16to32: new functions implemented new user32 relays * [misc/newfns.c] WIN32_WinHelpA: new function * [win32/param32.c] New file * [win32/resource.c] GetResDirEntry: added support for named entries WIN32_LoadAcceleratorsW: invoke *32 resource functions WIN32_LoadBitmapA: convert name to unicode if appropriate WIN32_ParseMenu: new function implemented new resource functions from user32.spec Wed Jan 24 18:09:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu> * [objects/cursoricon.c] GetIconId() and LoadIconHandler() functions. * [windows/mdi.c] Better maximization support, TranslateMDISysAccel() function, misc improvements. * [windows/defwnd.c] Fix for WM_WINDOWPOSCHANGED message handler. * [windows/winpos.c] Rewrote WindowFromPoint() function. Sun Jan 21 1996 17:05:09 Marcus Meissner <msmeissn@faui01.informatik.uni-erlangen.de> * [include/toolhelp.h] [misc/toolhelp.c] Added Notify(Un)Register, but no callbacks yet. Fri Jan 19 01:43:37 1996 Victor Schneider <root@tailor.roman.org> * [Makefile.in] Added target for libwine.so.1.0. * [library/winmain.c] For WINELIBDLL, _WinMain just returns hInstance instead of calling WinMain(). * [misc/main.c] For WINELIBDLL, renamed main() to _wine_main() for calling from the stub main function. * [library/winestub.c] (new file) Provides a stub main() function for using libwine.so. Tue Jan 16 11:04:34 1996 Anand Kumria <akumria@ozemail.com.au> * [winsocket.c] Fix EPERM problem. * [global.c] Attempt to do some sanity checking in MemManInfo(). * [Changelog] Fix changelog oversight for previous entry.
3007 lines
75 KiB
C
3007 lines
75 KiB
C
/*
|
|
* Edit control
|
|
*
|
|
* Copyright David W. Metcalfe, 1994
|
|
*
|
|
* Release 3, July 1994
|
|
* April 1995 bug fixes (William Magro)
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <windows.h>
|
|
#include "instance.h"
|
|
#include "local.h"
|
|
#include "win.h"
|
|
#include "class.h"
|
|
#include "stackframe.h" /* for MAKE_SEGPTR */
|
|
#include "user.h"
|
|
#include "stddebug.h"
|
|
#include "debug.h"
|
|
#include "xmalloc.h"
|
|
|
|
|
|
#ifdef WINELIB32
|
|
#define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
|
|
SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
|
|
MAKEWPARAM(GetDlgCtrlID(hWndCntrl),wNotifyCode), \
|
|
(LPARAM)hWndCntrl );
|
|
#else
|
|
#define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
|
|
SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
|
|
GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
|
|
#endif
|
|
|
|
#define MAXTEXTLEN 30000 /* maximum text buffer length */
|
|
#define EDITLEN 1024 /* starting length for multi-line control */
|
|
#define ENTRYLEN 256 /* starting length for single line control */
|
|
#define GROWLENGTH 64 /* buffers grow by this much */
|
|
|
|
typedef struct
|
|
{
|
|
int wlines; /* number of lines of text */
|
|
int wtop; /* top line that is displayed */
|
|
int wleft; /* left pixel that is displayed */
|
|
unsigned int textlen; /* text buffer length */
|
|
int textwidth; /* width of longest line in pixels */
|
|
RECT fmtrc; /* rectangle in which to format text */
|
|
int txtht; /* height of text line in pixels */
|
|
HANDLE hText; /* handle to text buffer */
|
|
INT *CharWidths; /* widths of chars in font */
|
|
unsigned int *textptrs; /* list of line offsets */
|
|
char *BlankLine; /* to fill blank lines quickly */
|
|
int CurrCol; /* current column */
|
|
int CurrLine; /* current line */
|
|
int WndCol; /* current window column */
|
|
int WndRow; /* current window row */
|
|
BOOL TextChanged; /* TRUE if text has changed */
|
|
BOOL PaintBkgd; /* paint control background */
|
|
unsigned int MaxTextLen; /* maximum text buffer length */
|
|
int SelBegLine; /* beginning line of selection */
|
|
int SelBegCol; /* beginning column of selection */
|
|
int SelEndLine; /* ending line of selection */
|
|
int SelEndCol; /* ending column of selection */
|
|
HFONT hFont; /* handle of current font (if not default) */
|
|
HANDLE hDeletedText; /* handle to deleted text buffer for undo */
|
|
int DeletedLength; /* length of deleted text */
|
|
int DeletedCurrLine; /* starting line from which text was deleted */
|
|
int DeletedCurrCol; /* starting col from which text was deleted */
|
|
int NumTabStops; /* number of tab stops in buffer hTabStops */
|
|
unsigned short *TabStops;/* tab stops buffer */
|
|
BOOL HaveFocus; /* TRUE if this edit has the focus */
|
|
int ClientWidth; /* computed from the window's ClientRect */
|
|
int ClientHeight; /* ditto */
|
|
char PasswordChar; /* The password character */
|
|
} EDITSTATE;
|
|
|
|
#define EditBufStartLen(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE \
|
|
? EDITLEN : ENTRYLEN)
|
|
#define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
|
|
#define SelMarked(es) ((es)->SelBegLine != 0 || (es)->SelBegCol != 0 || \
|
|
(es)->SelEndLine != 0 || (es)->SelEndCol != 0)
|
|
#define ROUNDUP(numer, denom) (((numer) % (denom)) \
|
|
? ((((numer) + (denom)) / (denom)) * (denom)) \
|
|
: (numer) + (denom))
|
|
|
|
/* "line" dimension for horizontal scroll */
|
|
#define HSCROLLDIM(es) ((es)->ClientWidth / 3)
|
|
|
|
/* macros to access window styles */
|
|
#define IsMultiLine(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE)
|
|
#define IsVScrollBar(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & WS_VSCROLL)
|
|
#define IsHScrollBar(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & WS_HSCROLL)
|
|
|
|
/* internal variables */
|
|
static BOOL TextMarking; /* TRUE if text marking in progress */
|
|
static BOOL ButtonDown; /* TRUE if left mouse button down */
|
|
static int ButtonRow; /* row in text buffer when button pressed */
|
|
static int ButtonCol; /* col in text buffer when button pressed */
|
|
|
|
#define SWAP_INT(x,y) do { int temp = (x); (x) = (y); (y) = temp; } while(0)
|
|
|
|
/*********************************************************************
|
|
* EDIT_HeapAlloc
|
|
*
|
|
* Allocate the specified number of bytes on the specified local heap.
|
|
*/
|
|
static HLOCAL EDIT_HeapAlloc(HWND hwnd, int bytes, WORD flags)
|
|
{
|
|
HLOCAL ret;
|
|
|
|
ret = LOCAL_Alloc( WIN_GetWindowInstance(hwnd), flags, bytes );
|
|
if (!ret)
|
|
printf("EDIT_HeapAlloc: Out of heap-memory\n");
|
|
return ret;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_HeapLock
|
|
*
|
|
* Return the address of the memory pointed to by the handle.
|
|
*/
|
|
static void *EDIT_HeapLock(HWND hwnd, HANDLE handle)
|
|
{
|
|
HINSTANCE hinstance = WIN_GetWindowInstance( hwnd );
|
|
#if defined(WINELIB)
|
|
return LOCAL_Lock( hinstance, handle );
|
|
#else
|
|
HANDLE offs;
|
|
|
|
if (handle == 0) return 0;
|
|
offs = LOCAL_Lock( hinstance, handle );
|
|
return PTR_SEG_OFF_TO_LIN( hinstance, offs );
|
|
#endif
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_HeapUnlock
|
|
*/
|
|
static void EDIT_HeapUnlock(HWND hwnd, HANDLE handle)
|
|
{
|
|
if (handle == 0) return;
|
|
LOCAL_Unlock( WIN_GetWindowInstance( hwnd ), handle );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_HeapReAlloc
|
|
*
|
|
* Reallocate the memory pointed to by the handle.
|
|
*/
|
|
static HLOCAL EDIT_HeapReAlloc(HWND hwnd, HANDLE handle, int bytes)
|
|
{
|
|
return LOCAL_ReAlloc( WIN_GetWindowInstance(hwnd), handle, bytes,
|
|
LMEM_FIXED );
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* EDIT_HeapFree
|
|
*
|
|
* Frees the memory pointed to by the handle.
|
|
*/
|
|
static void EDIT_HeapFree(HWND hwnd, HANDLE handle)
|
|
{
|
|
LOCAL_Free( WIN_GetWindowInstance(hwnd), handle );
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* EDIT_HeapSize
|
|
*
|
|
* Return the size of the given object on the local heap.
|
|
*/
|
|
static unsigned int EDIT_HeapSize(HWND hwnd, HANDLE handle)
|
|
{
|
|
return LOCAL_Size( WIN_GetWindowInstance(hwnd), handle );
|
|
}
|
|
|
|
/********************************************************************
|
|
* EDIT_RecalcSize
|
|
*
|
|
* Sets the ClientWidth/ClientHeight fields of the EDITSTATE
|
|
* Called on WM_SIZE and WM_SetFont messages
|
|
*/
|
|
static void EDIT_RecalcSize(HWND hwnd, EDITSTATE *es)
|
|
{
|
|
RECT rect;
|
|
GetClientRect(hwnd,&rect);
|
|
es->ClientWidth = rect.right > rect.left ? rect.right - rect.left : 0;
|
|
es->ClientHeight = rect.bottom > rect.top ? (rect.bottom - rect.top) / es->txtht : 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_GetEditState
|
|
*/
|
|
static EDITSTATE *EDIT_GetEditState(HWND hwnd)
|
|
{
|
|
return (EDITSTATE *)GetWindowLong(hwnd,0);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_GetNextTabStop
|
|
*
|
|
* Return the next tab stop beyond _pcol_.
|
|
*/
|
|
static int EDIT_GetNextTabStop(HWND hwnd, int pcol)
|
|
{
|
|
int i;
|
|
int baseUnitWidth = LOWORD(GetDialogBaseUnits());
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (es->NumTabStops == 0)
|
|
return ROUNDUP(pcol, 8 * baseUnitWidth);
|
|
if (es->NumTabStops == 1)
|
|
return ROUNDUP(pcol, es->TabStops[0] * baseUnitWidth / 4);
|
|
for (i = 0; i < es->NumTabStops; i++)
|
|
{
|
|
if (es->TabStops[i] * baseUnitWidth / 4 >= pcol)
|
|
return es->TabStops[i] * baseUnitWidth / 4;
|
|
}
|
|
return pcol;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_CharWidth
|
|
*
|
|
* Return the width of the given character in pixels.
|
|
* The current column offset in pixels _pcol_ is required to calculate
|
|
* the width of a tab.
|
|
*/
|
|
static int EDIT_CharWidth(HWND hwnd, short ch, int pcol)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (ch == VK_TAB) return EDIT_GetNextTabStop(hwnd, pcol) - pcol;
|
|
return es->CharWidths[ch];
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_ClearTextPointers
|
|
*
|
|
* Clear and initialize text line pointer array.
|
|
*/
|
|
static void EDIT_ClearTextPointers(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
dprintf_edit( stddeb, "EDIT_ClearTextPointers\n" );
|
|
es->textptrs = xrealloc(es->textptrs, sizeof(int));
|
|
es->textptrs[0] = 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_BuildTextPointers
|
|
*
|
|
* Build array of pointers to text lines.
|
|
*/
|
|
static void EDIT_BuildTextPointers(HWND hwnd)
|
|
{
|
|
char *text, *cp;
|
|
unsigned int off, len, line;
|
|
EDITSTATE *es;
|
|
|
|
es = EDIT_GetEditState(hwnd);
|
|
text = EDIT_HeapLock(hwnd, es->hText);
|
|
|
|
es->textwidth = 0;
|
|
if (IsMultiLine(hwnd)) {
|
|
es->wlines = 0;
|
|
cp = text;
|
|
while ((cp = strchr(cp,'\n')) != NULL) {
|
|
es->wlines++; cp++;
|
|
}
|
|
} else es->wlines = 1;
|
|
|
|
dprintf_edit( stddeb, "EDIT_BuildTextPointers: realloc\n" );
|
|
es->textptrs = xrealloc(es->textptrs, (es->wlines + 2) * sizeof(int));
|
|
|
|
cp = text;
|
|
dprintf_edit(stddeb,"BuildTextPointers: %d lines, pointer %p\n",
|
|
es->wlines, es->textptrs);
|
|
|
|
/* advance through text buffer */
|
|
line = 0;
|
|
while (*cp)
|
|
{
|
|
off = cp - text; /* offset of beginning of line */
|
|
dprintf_edit(stddeb,"BuildTextPointers: line %d offs %d\n", line, off);
|
|
es->textptrs[line] = off;
|
|
line++;
|
|
len = 0;
|
|
|
|
/* advance through current line */
|
|
while (*cp && *cp != '\n')
|
|
{
|
|
len += EDIT_CharWidth(hwnd, (BYTE)*cp, len);
|
|
/* width of line in pixels */
|
|
cp++;
|
|
}
|
|
es->textwidth = MAX(es->textwidth, len);
|
|
if (*cp)
|
|
cp++; /* skip '\n' */
|
|
}
|
|
off = cp - text;
|
|
es->textptrs[line] = off;
|
|
EDIT_HeapUnlock(hwnd, es->hText);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_ModTextPointers
|
|
*
|
|
* Modify text pointers from a specified position.
|
|
*/
|
|
static void EDIT_ModTextPointers(HWND hwnd, int lineno, int var)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
for(;lineno < es->wlines; lineno++) es->textptrs[lineno] += var;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_TextLine
|
|
*
|
|
* Return a pointer to the text in the specified line.
|
|
*/
|
|
static char *EDIT_TextLine(HWND hwnd, int sel)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
char *text = EDIT_HeapLock(hwnd, es->hText);
|
|
|
|
if (sel > es->wlines) return NULL;
|
|
dprintf_edit(stddeb,"EDIT_TextLine: text %p, line %d offs %d\n",
|
|
text, sel, es->textptrs[sel]);
|
|
return text + es->textptrs[sel];
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_GetTextLine
|
|
*
|
|
* Get a copy of the text in the specified line.
|
|
*/
|
|
static char *EDIT_GetTextLine(HWND hwnd, int selection)
|
|
{
|
|
int len;
|
|
char *cp, *cp1;
|
|
|
|
dprintf_edit(stddeb,"GetTextLine %d\n", selection);
|
|
cp1 = EDIT_TextLine(hwnd, selection);
|
|
|
|
/* Find end of line */
|
|
cp = strchr( cp1, '\r' );
|
|
if (cp == NULL) len = strlen(cp1);
|
|
else len = cp - cp1;
|
|
|
|
/* store selected line and return handle */
|
|
cp = xmalloc( len + 1 );
|
|
strncpy( cp, cp1, len);
|
|
cp[len] = 0;
|
|
return cp;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_StrWidth
|
|
*
|
|
* Return length of string _str_ of length _len_ characters in pixels.
|
|
* The current column offset in pixels _pcol_ is required to calculate
|
|
* the width of a tab.
|
|
*/
|
|
static int EDIT_StrWidth(HWND hwnd, unsigned char *str, int len, int pcol)
|
|
{
|
|
int i, plen = 0;
|
|
|
|
for (i = 0; i < len; i++)
|
|
plen += EDIT_CharWidth(hwnd, (BYTE)(*(str + i)), pcol + plen);
|
|
|
|
dprintf_edit(stddeb,"EDIT_StrWidth: returning %d, len=%d\n", plen,len);
|
|
return plen;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_LineLength
|
|
*
|
|
* Return length of line _num_ in characters.
|
|
*/
|
|
static int EDIT_LineLength(HWND hwnd, int num)
|
|
{
|
|
char *cp = EDIT_TextLine(hwnd, num);
|
|
char *cp1;
|
|
|
|
if(!cp)return 0;
|
|
cp1 = strchr(cp, '\r');
|
|
return cp1 ? (cp1 - cp) : strlen(cp);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_GetStr
|
|
*
|
|
* Return sub-string starting at pixel _off_ of length _len_ pixels.
|
|
* If _off_ is part way through a character, the negative offset of
|
|
* the beginning of the character is returned in _diff_, else _diff_
|
|
* will be zero.
|
|
*/
|
|
static HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff)
|
|
{
|
|
HANDLE hStr;
|
|
char *str;
|
|
int ch = 0, i = 0, j, s_i=0;
|
|
int ch1;
|
|
|
|
dprintf_edit(stddeb,"EDIT_GetStr lp='%s' off=%d len=%d\n", lp, off, len);
|
|
|
|
if (off < 0) off = 0;
|
|
while (i < off)
|
|
{
|
|
s_i = i;
|
|
i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
|
|
ch++;
|
|
}
|
|
/* if stepped past _off_, go back a character */
|
|
if (i > off)
|
|
{
|
|
i = s_i;
|
|
ch--;
|
|
}
|
|
*diff = off - i;
|
|
ch1 = ch;
|
|
while (i < len + off)
|
|
{
|
|
if (*(lp + ch) == '\r' || *(lp + ch) == '\n')
|
|
break;
|
|
i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
|
|
ch++;
|
|
}
|
|
|
|
hStr = EDIT_HeapAlloc(hwnd, ch - ch1 + 3, LMEM_FIXED);
|
|
str = (char *)EDIT_HeapLock(hwnd, hStr);
|
|
for (i = ch1, j = 0; i < ch; i++, j++)
|
|
str[j] = lp[i];
|
|
str[j] = '\0';
|
|
dprintf_edit(stddeb,"EDIT_GetStr: returning %s\n", str);
|
|
return hStr;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_WriteText
|
|
*
|
|
* Write text to a window
|
|
* lp - text line
|
|
* off - offset in text line (in pixels)
|
|
* len - length from off (in pixels)
|
|
* row - line in window
|
|
* col - column in window
|
|
* rc - rectangle in which to display line
|
|
* blank - blank remainder of line?
|
|
* reverse - reverse color of line?
|
|
*/
|
|
static void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
|
|
int col, RECT *rc, BOOL blank, BOOL reverse)
|
|
{
|
|
HDC hdc;
|
|
HANDLE hStr;
|
|
char *str, *cp, *cp1;
|
|
int diff=0, num_spaces, tabwidth, scol;
|
|
HRGN hrgnClip;
|
|
COLORREF oldTextColor, oldBkgdColor;
|
|
HFONT oldfont;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
dprintf_edit(stddeb,"EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse);
|
|
|
|
if( off < 0 ) {
|
|
len += off;
|
|
col -= off;
|
|
off = 0;
|
|
}
|
|
|
|
hdc = GetDC(hwnd);
|
|
hStr = EDIT_GetStr(hwnd, lp, off, len, &diff);
|
|
str = (char *)EDIT_HeapLock(hwnd, hStr);
|
|
hrgnClip = CreateRectRgnIndirect(rc);
|
|
SelectClipRgn(hdc, hrgnClip);
|
|
|
|
if (es->hFont)
|
|
oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
|
|
else
|
|
oldfont = 0; /* -Wall does not see the use of if */
|
|
|
|
#ifdef WINELIB32
|
|
SendMessage(GetParent(hwnd), WM_CTLCOLOREDIT, (WPARAM)hdc, (LPARAM)hwnd);
|
|
#else
|
|
SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WPARAM)hdc,
|
|
MAKELPARAM(hwnd, CTLCOLOR_EDIT));
|
|
#endif
|
|
|
|
if (reverse)
|
|
{
|
|
oldBkgdColor = GetBkColor(hdc);
|
|
oldTextColor = GetTextColor(hdc);
|
|
SetBkColor(hdc, oldTextColor);
|
|
SetTextColor(hdc, oldBkgdColor);
|
|
}
|
|
else /* -Wall does not see the use of if */
|
|
oldTextColor = oldBkgdColor = 0;
|
|
|
|
if (strlen(es->BlankLine) < (es->ClientWidth / es->CharWidths[32]) + 2)
|
|
{
|
|
dprintf_edit( stddeb, "EDIT_WriteText: realloc\n" );
|
|
es->BlankLine = xrealloc(es->BlankLine,
|
|
(es->ClientWidth / es->CharWidths[32]) + 2);
|
|
memset(es->BlankLine, ' ', (es->ClientWidth / es->CharWidths[32]) + 2);
|
|
es->BlankLine[(es->ClientWidth / es->CharWidths[32]) + 1] = 0;
|
|
}
|
|
|
|
if ((es->PasswordChar && GetWindowLong( hwnd, GWL_STYLE ) & ES_PASSWORD))
|
|
{
|
|
int len = strlen(str);
|
|
char *buff = xmalloc( len+1 );
|
|
memset( buff, es->PasswordChar, len );
|
|
buff[len] = '\0';
|
|
TextOut( hdc, col - diff, row * es->txtht, buff, len );
|
|
}
|
|
else if (!(cp = strchr(str, VK_TAB)))
|
|
TextOut(hdc, col - diff, row * es->txtht, str, strlen(str));
|
|
else
|
|
{
|
|
TextOut(hdc, col - diff, row * es->txtht, str, (int)(cp - str));
|
|
scol = EDIT_StrWidth(hwnd, str, (int)(cp - str), 0);
|
|
tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
|
|
num_spaces = tabwidth / es->CharWidths[32] + 1;
|
|
TextOut(hdc, scol, row * es->txtht, es->BlankLine, num_spaces);
|
|
cp++;
|
|
scol += tabwidth;
|
|
|
|
while ((cp1 = strchr(cp, VK_TAB)))
|
|
{
|
|
TextOut(hdc, scol, row * es->txtht, cp, (int)(cp1 - cp));
|
|
scol += EDIT_StrWidth(hwnd, cp, (int)(cp1 - cp), scol);
|
|
tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
|
|
num_spaces = tabwidth / es->CharWidths[32] + 1;
|
|
TextOut(hdc, scol, row * es->txtht, es->BlankLine, num_spaces);
|
|
cp = ++cp1;
|
|
scol += tabwidth;
|
|
}
|
|
|
|
TextOut(hdc, scol, row * es->txtht, cp, strlen(cp));
|
|
}
|
|
|
|
if (reverse)
|
|
{
|
|
SetBkColor(hdc, oldBkgdColor);
|
|
SetTextColor(hdc, oldTextColor);
|
|
}
|
|
|
|
/* blank out remainder of line if appropriate */
|
|
if (blank)
|
|
{
|
|
if ((rc->right - col) > len)
|
|
{
|
|
num_spaces = (rc->right - col - len) / es->CharWidths[32];
|
|
TextOut(hdc, col + len, row * es->txtht, es->BlankLine, num_spaces);
|
|
}
|
|
}
|
|
|
|
if (es->hFont)
|
|
SelectObject(hdc, (HANDLE)oldfont);
|
|
|
|
EDIT_HeapFree(hwnd, hStr);
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_WriteTextLine
|
|
*
|
|
* Write the line of text at offset _y_ in text buffer to a window.
|
|
*/
|
|
static void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
|
|
{
|
|
int len = 0;
|
|
unsigned char *lp;
|
|
int lnlen, lnlen1;
|
|
int col, off = 0;
|
|
int sbl, sel, sbc, sec;
|
|
RECT rc;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
/* initialize rectangle if NULL, else copy */
|
|
if (rect)
|
|
CopyRect(&rc, rect);
|
|
else
|
|
GetClientRect(hwnd, &rc);
|
|
|
|
dprintf_edit(stddeb,"WriteTextLine %d\n", y);
|
|
|
|
/* make sure y is inside the window */
|
|
if (y < es->wtop || y > (es->wtop + es->ClientHeight))
|
|
{
|
|
dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is not a displayed line\n", y);
|
|
return;
|
|
}
|
|
|
|
/* make sure rectangle is within window */
|
|
if (rc.left >= es->ClientWidth - 1)
|
|
{
|
|
dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.left (%ld) is greater than right edge\n",
|
|
(LONG)rc.left);
|
|
return;
|
|
}
|
|
if (rc.right <= 0)
|
|
{
|
|
dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.right (%ld) is less than left edge\n",
|
|
(LONG)rc.right);
|
|
return;
|
|
}
|
|
if (y - es->wtop < (rc.top / es->txtht) ||
|
|
y - es->wtop > (rc.bottom / es->txtht))
|
|
{
|
|
dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is outside window\n", y);
|
|
return;
|
|
}
|
|
|
|
/* get the text and length of line */
|
|
lp = EDIT_GetTextLine( hwnd, y );
|
|
if (lp == NULL) return;
|
|
|
|
lnlen = EDIT_StrWidth( hwnd, lp, strlen(lp), 0 );
|
|
lnlen1 = lnlen;
|
|
|
|
/* build the line to display */
|
|
if (lnlen < (es->wleft + rc.left))
|
|
{
|
|
lnlen = 0;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
off += es->wleft;
|
|
lnlen -= off;
|
|
}
|
|
|
|
if (lnlen > rc.left)
|
|
{
|
|
off += rc.left;
|
|
lnlen = lnlen1 - off;
|
|
}
|
|
len = MIN(lnlen, rc.right - rc.left);
|
|
|
|
if (SelMarked(es))
|
|
{
|
|
sbl = es->SelBegLine;
|
|
sel = es->SelEndLine;
|
|
sbc = es->SelBegCol;
|
|
sec = es->SelEndCol;
|
|
|
|
/* put lowest marker first */
|
|
if (sbl > sel)
|
|
{
|
|
SWAP_INT(sbl, sel);
|
|
SWAP_INT(sbc, sec);
|
|
}
|
|
if (sbl == sel && sbc > sec)
|
|
SWAP_INT(sbc, sec);
|
|
|
|
if (y < sbl || y > sel)
|
|
EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
|
|
TRUE, FALSE);
|
|
else if (y > sbl && y < sel)
|
|
EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
|
|
TRUE, TRUE);
|
|
else if (y == sbl)
|
|
{
|
|
col = EDIT_StrWidth(hwnd, lp, sbc, 0);
|
|
if (col > (es->wleft + rc.left))
|
|
{
|
|
len = MIN(col - off, rc.right - off);
|
|
EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
|
|
rc.left, &rc, FALSE, FALSE);
|
|
off = col;
|
|
}
|
|
if (y == sel)
|
|
{
|
|
col = EDIT_StrWidth(hwnd, lp, sec, 0);
|
|
if (col < (es->wleft + rc.right))
|
|
{
|
|
len = MIN(col - off, rc.right - off);
|
|
EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
|
|
off - es->wleft, &rc, FALSE, TRUE);
|
|
off = col;
|
|
len = MIN(lnlen - off, rc.right - off);
|
|
EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
|
|
off - es->wleft, &rc, TRUE, FALSE);
|
|
}
|
|
else
|
|
{
|
|
len = MIN(lnlen - off, rc.right - off);
|
|
EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
|
|
off - es->wleft, &rc, TRUE, TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
len = MIN(lnlen - off, rc.right - off);
|
|
if (col < (es->wleft + rc.right))
|
|
EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
|
|
off - es->wleft, &rc, TRUE, TRUE);
|
|
}
|
|
}
|
|
else if (y == sel)
|
|
{
|
|
col = EDIT_StrWidth(hwnd, lp, sec, 0);
|
|
if (col < (es->wleft + rc.right))
|
|
{
|
|
len = MIN(col - off, rc.right - off);
|
|
EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
|
|
off - es->wleft, &rc, FALSE, TRUE);
|
|
off = col;
|
|
len = MIN(lnlen - off, rc.right - off);
|
|
EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
|
|
off - es->wleft, &rc, TRUE, FALSE);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
|
|
TRUE, FALSE);
|
|
|
|
free( lp );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_ComputeVScrollPos
|
|
*
|
|
* Compute the vertical scroll bar position from the window
|
|
* position and text width.
|
|
*/
|
|
static int EDIT_ComputeVScrollPos(HWND hwnd)
|
|
{
|
|
int vscrollpos;
|
|
INT minpos, maxpos;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
GetScrollRange(hwnd, SB_VERT, &minpos, &maxpos);
|
|
|
|
if (es->wlines > es->ClientHeight)
|
|
vscrollpos = (double)(es->wtop) / (double)(es->wlines -
|
|
es->ClientHeight) * (maxpos - minpos);
|
|
else
|
|
vscrollpos = minpos;
|
|
|
|
return vscrollpos;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_ComputeHScrollPos
|
|
*
|
|
* Compute the horizontal scroll bar position from the window
|
|
* position and text width.
|
|
*/
|
|
static int EDIT_ComputeHScrollPos(HWND hwnd)
|
|
{
|
|
int hscrollpos;
|
|
INT minpos, maxpos;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
GetScrollRange(hwnd, SB_HORZ, &minpos, &maxpos);
|
|
|
|
if (es->textwidth > es->ClientWidth)
|
|
hscrollpos = (double)(es->wleft) / (double)(es->textwidth -
|
|
es->ClientWidth) * (maxpos - minpos);
|
|
else
|
|
hscrollpos = minpos;
|
|
|
|
return hscrollpos;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_KeyHScroll
|
|
*
|
|
* Scroll text horizontally using cursor keys.
|
|
*/
|
|
static void EDIT_KeyHScroll(HWND hwnd, WORD opt)
|
|
{
|
|
int hscrollpos;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (opt == SB_LINEDOWN)
|
|
{
|
|
es->wleft += HSCROLLDIM(es);
|
|
es->WndCol -= HSCROLLDIM(es);
|
|
}
|
|
else
|
|
{
|
|
if (es->wleft == 0)
|
|
return;
|
|
if (es->wleft - HSCROLLDIM(es) < 0)
|
|
{
|
|
es->WndCol += es->wleft;
|
|
es->wleft = 0;
|
|
}
|
|
else
|
|
{
|
|
es->wleft -= HSCROLLDIM(es);
|
|
es->WndCol += HSCROLLDIM(es);
|
|
}
|
|
}
|
|
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
UpdateWindow(hwnd);
|
|
|
|
if (IsHScrollBar(hwnd))
|
|
{
|
|
hscrollpos = EDIT_ComputeHScrollPos(hwnd);
|
|
SetScrollPos(hwnd, SB_HORZ, hscrollpos, TRUE);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_KeyVScrollLine
|
|
*
|
|
* Scroll text vertically by one line using keyboard.
|
|
*/
|
|
static void EDIT_KeyVScrollLine(HWND hwnd, WORD opt)
|
|
{
|
|
RECT rc;
|
|
int y, vscrollpos;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (!IsMultiLine(hwnd))
|
|
return;
|
|
|
|
if (opt == SB_LINEDOWN)
|
|
{
|
|
/* move down one line */
|
|
if (es->wtop + es->ClientHeight >= es->wlines)
|
|
return;
|
|
es->wtop++;
|
|
}
|
|
else
|
|
{
|
|
/* move up one line */
|
|
if (es->wtop == 0)
|
|
return;
|
|
--es->wtop;
|
|
}
|
|
|
|
if (IsWindowVisible(hwnd))
|
|
{
|
|
/* adjust client bottom to nearest whole line */
|
|
GetClientRect(hwnd, &rc);
|
|
rc.bottom = (rc.bottom / es->txtht) * es->txtht;
|
|
|
|
if (opt == SB_LINEUP)
|
|
{
|
|
/* move up one line (scroll window down) */
|
|
ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
|
|
/* write top line */
|
|
EDIT_WriteTextLine(hwnd, NULL, es->wtop);
|
|
es->WndRow++;
|
|
}
|
|
else
|
|
{
|
|
/* move down one line (scroll window up) */
|
|
ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
|
|
/* write bottom line */
|
|
y = (((rc.bottom - rc.top) / es->txtht) - 1);
|
|
EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
|
|
--es->WndRow;
|
|
}
|
|
}
|
|
|
|
/* reset the vertical scroll bar */
|
|
if (IsVScrollBar(hwnd))
|
|
{
|
|
vscrollpos = EDIT_ComputeVScrollPos(hwnd);
|
|
SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_End
|
|
*
|
|
* End key: move to end of line.
|
|
*/
|
|
static void EDIT_End(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
while (*CurrChar && *CurrChar != '\r')
|
|
{
|
|
es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
|
|
es->CurrCol++;
|
|
}
|
|
|
|
if (es->WndCol >= es->ClientWidth)
|
|
{
|
|
es->wleft = es->WndCol - es->ClientWidth + HSCROLLDIM(es);
|
|
es->WndCol -= es->wleft;
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_Home
|
|
*
|
|
* Home key: move to beginning of line.
|
|
*/
|
|
static void EDIT_Home(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
es->CurrCol = es->WndCol = 0;
|
|
if (es->wleft != 0)
|
|
{
|
|
es->wleft = 0;
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_StickEnd
|
|
*
|
|
* Stick the cursor to the end of the line.
|
|
*/
|
|
static void EDIT_StickEnd(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
int len = EDIT_LineLength(hwnd, es->CurrLine);
|
|
char *cp = EDIT_TextLine(hwnd, es->CurrLine);
|
|
int currpel;
|
|
|
|
es->CurrCol = MIN(len, es->CurrCol);
|
|
es->WndCol = MIN(EDIT_StrWidth(hwnd, cp, len, 0) - es->wleft, es->WndCol);
|
|
currpel = EDIT_StrWidth(hwnd, cp, es->CurrCol, 0);
|
|
|
|
if (es->wleft > currpel)
|
|
{
|
|
es->wleft = MAX(0, currpel - 20);
|
|
es->WndCol = currpel - es->wleft;
|
|
UpdateWindow(hwnd);
|
|
}
|
|
else if (currpel - es->wleft >= es->ClientWidth)
|
|
{
|
|
es->wleft = currpel - (es->ClientWidth - 5);
|
|
es->WndCol = currpel - es->wleft;
|
|
UpdateWindow(hwnd);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_Downward
|
|
*
|
|
* Cursor down key: move down one line.
|
|
*/
|
|
static void EDIT_Downward(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
dprintf_edit(stddeb,"EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n",
|
|
es->WndRow, es->wtop, es->wlines);
|
|
|
|
if (IsMultiLine(hwnd) && (es->WndRow + es->wtop + 1 < es->wlines))
|
|
{
|
|
es->CurrLine++;
|
|
if (es->WndRow == es->ClientHeight - 1)
|
|
{
|
|
es->WndRow++;
|
|
EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN);
|
|
}
|
|
else
|
|
es->WndRow++;
|
|
EDIT_StickEnd(hwnd);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_Upward
|
|
*
|
|
* Cursor up key: move up one line.
|
|
*/
|
|
static void EDIT_Upward(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (IsMultiLine(hwnd) && es->CurrLine != 0)
|
|
{
|
|
--es->CurrLine;
|
|
if (es->WndRow == 0)
|
|
{
|
|
--es->WndRow;
|
|
EDIT_KeyVScrollLine(hwnd, SB_LINEUP);
|
|
}
|
|
else
|
|
--es->WndRow;
|
|
EDIT_StickEnd(hwnd);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_Forward
|
|
*
|
|
* Cursor right key: move right one character position.
|
|
*/
|
|
static void EDIT_Forward(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (*CurrChar == '\0')
|
|
return;
|
|
|
|
if (*CurrChar == '\r')
|
|
{
|
|
if (es->CurrLine < (es->wlines - 1))
|
|
{
|
|
EDIT_Home(hwnd);
|
|
EDIT_Downward(hwnd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
|
|
es->CurrCol++;
|
|
if (es->WndCol >= es->ClientWidth)
|
|
EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_Backward
|
|
*
|
|
* Cursor left key: move left one character position.
|
|
*/
|
|
static void EDIT_Backward(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (es->CurrCol)
|
|
{
|
|
--es->CurrCol;
|
|
if (*CurrChar == VK_TAB)
|
|
es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar),
|
|
EDIT_StrWidth(hwnd,
|
|
EDIT_TextLine(hwnd, es->CurrLine),
|
|
es->CurrCol, 0));
|
|
else
|
|
es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), 0);
|
|
if (es->WndCol < 0)
|
|
EDIT_KeyHScroll(hwnd, SB_LINEUP);
|
|
}
|
|
else if (IsMultiLine(hwnd) && es->CurrLine != 0)
|
|
{
|
|
EDIT_Upward(hwnd);
|
|
EDIT_End(hwnd);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_KeyVScrollPage
|
|
*
|
|
* Scroll text vertically by one page using keyboard.
|
|
*/
|
|
static void EDIT_KeyVScrollPage(HWND hwnd, WORD opt)
|
|
{
|
|
int vscrollpos;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (IsMultiLine(hwnd))
|
|
{
|
|
if (opt == SB_PAGEUP)
|
|
{
|
|
if (es->wtop > es->ClientHeight) es->wtop -= es->ClientHeight;
|
|
}
|
|
else
|
|
{
|
|
if (es->wtop + es->ClientHeight < es->wlines)
|
|
{
|
|
es->wtop += es->ClientHeight;
|
|
if (es->wtop > es->wlines - es->ClientHeight)
|
|
es->wtop = es->wlines - es->ClientHeight;
|
|
}
|
|
}
|
|
if (es->wtop < 0)
|
|
es->wtop = 0;
|
|
|
|
es->CurrLine = es->wtop + es->WndRow;
|
|
EDIT_StickEnd(hwnd);
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
|
|
/* reset the vertical scroll bar */
|
|
if (IsVScrollBar(hwnd))
|
|
{
|
|
vscrollpos = EDIT_ComputeVScrollPos(hwnd);
|
|
SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef SUPERFLUOUS_FUNCTIONS
|
|
/*********************************************************************
|
|
* EDIT_KeyVScrollDoc
|
|
*
|
|
* Scroll text to top and bottom of document using keyboard.
|
|
*/
|
|
static void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt)
|
|
{
|
|
int vscrollpos;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (!IsMultiLine(hwnd))
|
|
return;
|
|
|
|
if (opt == SB_TOP)
|
|
es->wtop = es->wleft = 0;
|
|
else if (es->wtop + es->ClientHeight < es->wlines)
|
|
{
|
|
es->wtop = es->wlines - es->ClientHeight;
|
|
es->wleft = 0;
|
|
}
|
|
|
|
es->CurrLine = es->wlines;
|
|
es->WndRow = es->wlines - es->wtop;
|
|
EDIT_End(hwnd);
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
|
|
/* reset the vertical scroll bar */
|
|
if (IsVScrollBar(hwnd))
|
|
{
|
|
vscrollpos = EDIT_ComputeVScrollPos(hwnd);
|
|
SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*********************************************************************
|
|
* EDIT_DelKey
|
|
*
|
|
* Delete character to right of cursor.
|
|
*/
|
|
static void EDIT_DelKey(HWND hwnd)
|
|
{
|
|
RECT rc;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
char *currchar = CurrChar;
|
|
BOOL repaint = *currchar == '\n';
|
|
|
|
if (IsMultiLine(hwnd) && *currchar == '\n' && *(currchar + 1) == '\0')
|
|
return;
|
|
strcpy(currchar, currchar + 1);
|
|
NOTIFY_PARENT(hwnd, EN_UPDATE);
|
|
|
|
if (repaint)
|
|
{
|
|
EDIT_BuildTextPointers(hwnd);
|
|
GetClientRect(hwnd, &rc);
|
|
rc.top = es->WndRow * es->txtht;
|
|
InvalidateRect(hwnd, &rc, FALSE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
else
|
|
{
|
|
EDIT_ModTextPointers(hwnd, es->CurrLine + 1, -1);
|
|
EDIT_WriteTextLine(hwnd, NULL, es->WndRow + es->wtop);
|
|
}
|
|
|
|
es->TextChanged = TRUE;
|
|
NOTIFY_PARENT(hwnd, EN_CHANGE);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_VScrollLine
|
|
*
|
|
* Scroll text vertically by one line using scrollbars.
|
|
*/
|
|
static void EDIT_VScrollLine(HWND hwnd, WORD opt)
|
|
{
|
|
RECT rc;
|
|
int y;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
dprintf_edit(stddeb,"EDIT_VScrollLine: direction=%d\n", opt);
|
|
|
|
if (opt == SB_LINEDOWN)
|
|
{
|
|
/* move down one line */
|
|
if (es->wtop + es->ClientHeight >= es->wlines)
|
|
return;
|
|
es->wtop++;
|
|
}
|
|
else
|
|
{
|
|
/* move up one line */
|
|
if (es->wtop == 0)
|
|
return;
|
|
--es->wtop;
|
|
}
|
|
|
|
if (IsWindowVisible(hwnd))
|
|
{
|
|
/* adjust client bottom to nearest whole line */
|
|
GetClientRect(hwnd, &rc);
|
|
rc.bottom = (rc.bottom / es->txtht) * es->txtht;
|
|
|
|
if (opt == SB_LINEUP)
|
|
{
|
|
/* move up one line (scroll window down) */
|
|
ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
|
|
/* write top line */
|
|
EDIT_WriteTextLine(hwnd, NULL, es->wtop);
|
|
es->WndRow++;
|
|
}
|
|
else
|
|
{
|
|
/* move down one line (scroll window up) */
|
|
ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
|
|
/* write bottom line */
|
|
y = ((rc.bottom - rc.top / es->txtht) - 1);
|
|
EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
|
|
--es->WndRow;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* EDIT_VScrollPage
|
|
*
|
|
* Scroll text vertically by one page using keyboard.
|
|
*/
|
|
static void EDIT_VScrollPage(HWND hwnd, WORD opt)
|
|
{
|
|
int vscrollpos;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (opt == SB_PAGEUP)
|
|
{
|
|
if (es->wtop)
|
|
es->wtop -= es->ClientHeight;
|
|
}
|
|
else
|
|
{
|
|
if (es->wtop + es->ClientHeight < es->wlines)
|
|
{
|
|
es->wtop += es->ClientHeight;
|
|
if (es->wtop > es->wlines - es->ClientHeight)
|
|
es->wtop = es->wlines - es->ClientHeight;
|
|
}
|
|
}
|
|
if (es->wtop < 0)
|
|
es->wtop = 0;
|
|
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
|
|
/* reset the vertical scroll bar */
|
|
if (IsVScrollBar(hwnd))
|
|
{
|
|
vscrollpos = EDIT_ComputeVScrollPos(hwnd);
|
|
SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_PixelToChar
|
|
*
|
|
* Convert a pixel offset in the given row to a character offset,
|
|
* adjusting the pixel offset to the nearest whole character if
|
|
* necessary.
|
|
*/
|
|
static int EDIT_PixelToChar(HWND hwnd, int row, int *pixel)
|
|
{
|
|
int ch = 0, i = 0, s_i = 0;
|
|
char *text;
|
|
|
|
dprintf_edit(stddeb,"EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel);
|
|
|
|
text = EDIT_TextLine(hwnd, row);
|
|
while (i < *pixel)
|
|
{
|
|
s_i = i;
|
|
i += EDIT_CharWidth(hwnd, (BYTE)(*(text + ch)), i);
|
|
ch++;
|
|
}
|
|
|
|
/* if stepped past _pixel_, go back a character */
|
|
if (i - *pixel)
|
|
{
|
|
i = s_i;
|
|
--ch;
|
|
}
|
|
*pixel = i;
|
|
return ch;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_ClearText
|
|
*
|
|
* Clear text from text buffer.
|
|
*/
|
|
static void EDIT_ClearText(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
unsigned int blen = EditBufStartLen(hwnd) + 2;
|
|
char *text;
|
|
|
|
dprintf_edit(stddeb,"EDIT_ClearText %d\n",blen);
|
|
/*#ifndef WINELIB*/
|
|
es->hText = EDIT_HeapReAlloc(hwnd, es->hText, blen);
|
|
text = EDIT_HeapLock(hwnd, es->hText);
|
|
memset(text, 0, blen);
|
|
/*#endif*/
|
|
es->textlen = 0;
|
|
es->wlines = 0;
|
|
es->CurrLine = es->CurrCol = 0;
|
|
es->WndRow = es->WndCol = 0;
|
|
es->wleft = es->wtop = 0;
|
|
es->textwidth = 0;
|
|
es->TextChanged = FALSE;
|
|
/*#ifndef WINELIB*/
|
|
EDIT_ClearTextPointers(hwnd);
|
|
/*#endif*/
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_GetLineCol
|
|
*
|
|
* Return line and column in text buffer from character offset.
|
|
*/
|
|
static void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
|
|
{
|
|
int lineno;
|
|
char *cp, *cp1;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
char *text = EDIT_HeapLock(hwnd, es->hText);
|
|
|
|
/* check for (0,0) */
|
|
if (!off || !es->wlines)
|
|
{
|
|
*line = 0;
|
|
*col = 0;
|
|
return;
|
|
}
|
|
|
|
if (off < 0 || off > strlen(text)) off = strlen(text);
|
|
cp1 = text;
|
|
for (lineno = 0; lineno < es->wlines; lineno++)
|
|
{
|
|
cp = text + es->textptrs[lineno];
|
|
if (off == (int)(cp - text))
|
|
{
|
|
*line = lineno;
|
|
*col = 0;
|
|
return;
|
|
}
|
|
if (off < (int)(cp - text))
|
|
break;
|
|
cp1 = cp;
|
|
}
|
|
*line = lineno - 1;
|
|
*col = off - (int)(cp1 - text);
|
|
#if 0
|
|
if (*(text + *col) == '\0')
|
|
(*col)--;
|
|
#endif
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_ClearSel
|
|
*
|
|
* Clear the current selection.
|
|
*/
|
|
static void EDIT_ClearSel(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
es->SelBegLine = es->SelBegCol = 0;
|
|
es->SelEndLine = es->SelEndCol = 0;
|
|
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_SaveDeletedText
|
|
*
|
|
* Save deleted text in deleted text buffer.
|
|
*/
|
|
static void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len,
|
|
int line, int col)
|
|
{
|
|
char *text;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
dprintf_edit( stddeb, "EDIT_SaveDeletedText\n" );
|
|
if (!es->hDeletedText)
|
|
es->hDeletedText = GlobalAlloc( GMEM_MOVEABLE, len );
|
|
else
|
|
es->hDeletedText = GlobalReAlloc(es->hDeletedText, len, GMEM_MOVEABLE);
|
|
if (!es->hDeletedText) return;
|
|
text = (char *)GlobalLock(es->hDeletedText);
|
|
memcpy(text, deltext, len);
|
|
GlobalUnlock(es->hDeletedText);
|
|
es->DeletedLength = len;
|
|
es->DeletedCurrLine = line;
|
|
es->DeletedCurrCol = col;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_DeleteSel
|
|
*
|
|
* Delete the current selected text (if any)
|
|
*/
|
|
static void EDIT_DeleteSel(HWND hwnd)
|
|
{
|
|
char *bbl, *bel;
|
|
int len;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (SelMarked(es))
|
|
{
|
|
bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
|
|
bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
|
|
len = (int)(bel - bbl);
|
|
EDIT_SaveDeletedText(hwnd, bbl, len, es->SelBegLine, es->SelBegCol);
|
|
es->TextChanged = TRUE;
|
|
strcpy(bbl, bel);
|
|
|
|
es->CurrLine = es->SelBegLine;
|
|
es->CurrCol = es->SelBegCol;
|
|
es->WndRow = es->SelBegLine - es->wtop;
|
|
if (es->WndRow < 0)
|
|
{
|
|
es->wtop = es->SelBegLine;
|
|
es->WndRow = 0;
|
|
}
|
|
es->WndCol = EDIT_StrWidth(hwnd, bbl - es->SelBegCol,
|
|
es->SelBegCol, 0) - es->wleft;
|
|
|
|
EDIT_BuildTextPointers(hwnd);
|
|
es->PaintBkgd = TRUE;
|
|
EDIT_ClearSel(hwnd);
|
|
}
|
|
}
|
|
|
|
#ifdef SUPERFLUOUS_FUNCTIONS
|
|
/*********************************************************************
|
|
* EDIT_TextLineNumber
|
|
*
|
|
* Return the line number in the text buffer of the supplied
|
|
* character pointer.
|
|
*/
|
|
static int EDIT_TextLineNumber(HWND hwnd, char *lp)
|
|
{
|
|
int lineno;
|
|
char *cp;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
char *text = EDIT_HeapLock(hwnd, es->hText);
|
|
|
|
for (lineno = 0; lineno < es->wlines; lineno++)
|
|
{
|
|
cp = text + es->textptrs[lineno];
|
|
if (cp == lp)
|
|
return lineno;
|
|
if (cp > lp)
|
|
break;
|
|
}
|
|
return lineno - 1;
|
|
}
|
|
#endif
|
|
|
|
/*********************************************************************
|
|
* EDIT_SetAnchor
|
|
*
|
|
* Set down anchor for text marking.
|
|
*/
|
|
static void EDIT_SetAnchor(HWND hwnd, int row, int col)
|
|
{
|
|
BOOL sel = FALSE;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (SelMarked(es))
|
|
{
|
|
sel = TRUE;
|
|
EDIT_ClearSel(hwnd);
|
|
}
|
|
es->SelBegLine = es->SelEndLine = row;
|
|
es->SelBegCol = es->SelEndCol = col;
|
|
if (sel)
|
|
{
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_WriteSel
|
|
*
|
|
* Display selection by reversing pixels in selected text.
|
|
* If end == -1, selection applies to end of line.
|
|
*/
|
|
static void EDIT_WriteSel(HWND hwnd, int y, int start, int end)
|
|
{
|
|
RECT rc, rcInvert;
|
|
int scol, ecol;
|
|
char *cp;
|
|
HDC hdc;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
dprintf_edit(stddeb,"EDIT_WriteSel: y=%d start=%d end=%d\n", y, start,end);
|
|
GetClientRect(hwnd, &rc);
|
|
|
|
/* make sure y is within the window */
|
|
if (y < es->wtop || y > (es->wtop + es->ClientHeight))
|
|
return;
|
|
|
|
/* get pointer to text */
|
|
cp = EDIT_TextLine(hwnd, y);
|
|
|
|
/* get length of line if end == -1 */
|
|
if (end == -1)
|
|
end = EDIT_LineLength(hwnd, y);
|
|
|
|
scol = EDIT_StrWidth(hwnd, cp, start, 0) - es->wleft;
|
|
if (scol > rc.right) return;
|
|
if (scol < rc.left) scol = rc.left;
|
|
ecol = EDIT_StrWidth(hwnd, cp, end, 0) - es->wleft;
|
|
if (ecol < rc.left) return;
|
|
if (ecol > rc.right) ecol = rc.right;
|
|
|
|
hdc = GetDC(hwnd);
|
|
rcInvert.left = scol;
|
|
rcInvert.top = (y - es->wtop) * es->txtht;
|
|
rcInvert.right = ecol;
|
|
rcInvert.bottom = (y - es->wtop + 1) * es->txtht;
|
|
InvertRect(hdc, (LPRECT) &rcInvert);
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_ExtendSel
|
|
*
|
|
* Extend selection to the given screen co-ordinates.
|
|
*/
|
|
static void EDIT_ExtendSel(HWND hwnd, INT x, INT y)
|
|
{
|
|
int bbl, bel, bbc, bec;
|
|
char *cp;
|
|
int len, line;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
dprintf_edit(stddeb,"EDIT_ExtendSel: x=%d, y=%d\n", x, y);
|
|
|
|
bbl = es->SelEndLine;
|
|
bbc = es->SelEndCol;
|
|
y = MAX(y,0);
|
|
if (IsMultiLine(hwnd))
|
|
{
|
|
if ((line = es->wtop + y / es->txtht) >= es->wlines)
|
|
line = es->wlines - 1;
|
|
}
|
|
else
|
|
line = 0;
|
|
|
|
cp = EDIT_TextLine(hwnd, line);
|
|
len = EDIT_LineLength(hwnd, line);
|
|
|
|
es->WndRow = y / es->txtht;
|
|
if (!IsMultiLine(hwnd))
|
|
es->WndRow = 0;
|
|
else if (es->WndRow > es->wlines - es->wtop - 1)
|
|
es->WndRow = es->wlines - es->wtop - 1;
|
|
es->CurrLine = es->wtop + es->WndRow;
|
|
es->SelEndLine = es->CurrLine;
|
|
|
|
es->WndCol = es->wleft + MAX(x,0);
|
|
if (es->WndCol > EDIT_StrWidth(hwnd, cp, len, 0))
|
|
es->WndCol = EDIT_StrWidth(hwnd, cp, len, 0);
|
|
es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
|
|
es->WndCol -= es->wleft;
|
|
es->SelEndCol = es->CurrCol;
|
|
|
|
bel = es->SelEndLine;
|
|
bec = es->SelEndCol;
|
|
|
|
/* return if no new characters to mark */
|
|
if (bbl == bel && bbc == bec)
|
|
return;
|
|
|
|
/* put lowest marker first */
|
|
if (bbl > bel)
|
|
{
|
|
SWAP_INT(bbl, bel);
|
|
SWAP_INT(bbc, bec);
|
|
}
|
|
if (bbl == bel && bbc > bec)
|
|
SWAP_INT(bbc, bec);
|
|
|
|
for (y = bbl; y <= bel; y++)
|
|
{
|
|
if (y == bbl && y == bel)
|
|
EDIT_WriteSel(hwnd, y, bbc, bec);
|
|
else if (y == bbl)
|
|
EDIT_WriteSel(hwnd, y, bbc, -1);
|
|
else if (y == bel)
|
|
EDIT_WriteSel(hwnd, y, 0, bec);
|
|
else
|
|
EDIT_WriteSel(hwnd, y, 0, -1);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_StopMarking
|
|
*
|
|
* Stop text marking (selection).
|
|
*/
|
|
static void EDIT_StopMarking(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
TextMarking = FALSE;
|
|
if (es->SelBegLine > es->SelEndLine)
|
|
{
|
|
SWAP_INT((es->SelBegLine), (es->SelEndLine));
|
|
SWAP_INT((es->SelBegCol), (es->SelEndCol));
|
|
}
|
|
if (es->SelBegLine == es->SelEndLine && es->SelBegCol > es->SelEndCol)
|
|
SWAP_INT((es->SelBegCol), (es->SelEndCol));
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_InsertText
|
|
*
|
|
* Insert text at current line and column.
|
|
*/
|
|
static void EDIT_InsertText(HWND hwnd, char *str, int len)
|
|
{
|
|
int plen;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
char *text = EDIT_HeapLock(hwnd, es->hText);
|
|
|
|
plen = strlen(text) + len;
|
|
if (plen + 1 > es->textlen)
|
|
{
|
|
dprintf_edit(stddeb,"InsertText: Realloc\n");
|
|
es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + len);
|
|
text = EDIT_HeapLock(hwnd, es->hText);
|
|
es->textlen = plen + 1;
|
|
}
|
|
memmove(CurrChar + len, CurrChar, strlen(CurrChar) + 1);
|
|
memcpy(CurrChar, str, len);
|
|
|
|
EDIT_BuildTextPointers(hwnd);
|
|
es->PaintBkgd = TRUE;
|
|
es->TextChanged = TRUE;
|
|
|
|
EDIT_GetLineCol(hwnd, (int)((CurrChar + len) - text), &(es->CurrLine),
|
|
&(es->CurrCol));
|
|
es->WndRow = es->CurrLine - es->wtop;
|
|
es->WndCol = EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
|
|
es->CurrCol, 0) - es->wleft;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_ClearDeletedText
|
|
*
|
|
* Clear deleted text buffer.
|
|
*/
|
|
static void EDIT_ClearDeletedText(HWND hwnd)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
GlobalFree(es->hDeletedText);
|
|
es->hDeletedText = 0;
|
|
es->DeletedLength = 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_CopyToClipboard
|
|
*
|
|
* Copy the specified text to the clipboard.
|
|
*/
|
|
static void EDIT_CopyToClipboard(HWND hwnd)
|
|
{
|
|
HANDLE hMem;
|
|
char *lpMem;
|
|
int i, len;
|
|
char *bbl, *bel;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
|
|
bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
|
|
len = (int)(bel - bbl);
|
|
|
|
hMem = GlobalAlloc(GHND, (DWORD)(len + 1));
|
|
lpMem = GlobalLock(hMem);
|
|
|
|
for (i = 0; i < len; i++)
|
|
*lpMem++ = *bbl++;
|
|
|
|
GlobalUnlock(hMem);
|
|
OpenClipboard(hwnd);
|
|
EmptyClipboard();
|
|
SetClipboardData(CF_TEXT, hMem);
|
|
CloseClipboard();
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EDIT_KeyTyped
|
|
*
|
|
* Process keystrokes that produce displayable characters.
|
|
*/
|
|
static void EDIT_KeyTyped(HWND hwnd, short ch)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
char *text = EDIT_HeapLock(hwnd, es->hText);
|
|
char *currchar;
|
|
RECT rc;
|
|
BOOL FullPaint = FALSE;
|
|
|
|
dprintf_edit(stddeb,"EDIT_KeyTyped: ch=%c\n", (char)ch);
|
|
|
|
/* delete selected text (if any) */
|
|
if (SelMarked(es))
|
|
EDIT_DeleteSel(hwnd);
|
|
|
|
/* currchar must be assigned after deleting the selection */
|
|
currchar = CurrChar;
|
|
|
|
/* test for typing at end of maximum buffer size */
|
|
if (currchar == text + es->MaxTextLen)
|
|
{
|
|
NOTIFY_PARENT(hwnd, EN_ERRSPACE);
|
|
return;
|
|
}
|
|
|
|
if (*currchar == '\0' && IsMultiLine(hwnd))
|
|
{
|
|
/* insert a newline at end of text */
|
|
*currchar = '\r';
|
|
*(currchar + 1) = '\n';
|
|
*(currchar + 2) = '\0';
|
|
EDIT_BuildTextPointers(hwnd);
|
|
}
|
|
|
|
/* insert the typed character */
|
|
if (text[es->textlen - 1] != '\0')
|
|
{
|
|
/* current text buffer is full */
|
|
if (es->textlen == es->MaxTextLen)
|
|
{
|
|
/* text buffer is at maximum size */
|
|
NOTIFY_PARENT(hwnd, EN_ERRSPACE);
|
|
return;
|
|
}
|
|
|
|
/* increase the text buffer size */
|
|
es->textlen += GROWLENGTH;
|
|
/* but not above maximum size */
|
|
if (es->textlen > es->MaxTextLen)
|
|
es->textlen = es->MaxTextLen;
|
|
dprintf_edit( stddeb, "EDIT_KeyTyped: realloc\n" );
|
|
es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + 2);
|
|
if (!es->hText)
|
|
NOTIFY_PARENT(hwnd, EN_ERRSPACE);
|
|
text = EDIT_HeapLock(hwnd, es->hText);
|
|
text[es->textlen - 1] = '\0';
|
|
currchar = CurrChar;
|
|
}
|
|
/* make space for new character and put char in buffer */
|
|
if (ch == '\n')
|
|
{
|
|
memmove(currchar + 2, currchar, strlen(currchar) + 1);
|
|
*currchar = '\r';
|
|
*(currchar + 1) = '\n';
|
|
EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 2);
|
|
}
|
|
else
|
|
{
|
|
memmove(currchar + 1, currchar, strlen(currchar) + 1);
|
|
*currchar = ch;
|
|
EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
|
|
}
|
|
es->TextChanged = TRUE;
|
|
NOTIFY_PARENT(hwnd, EN_UPDATE);
|
|
|
|
/* re-adjust textwidth, if necessary, and redraw line */
|
|
HideCaret(hwnd);
|
|
if (IsMultiLine(hwnd) && es->wlines > 1)
|
|
{
|
|
es->textwidth = MAX(es->textwidth,
|
|
EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
|
|
(int)(EDIT_TextLine(hwnd, es->CurrLine + 1) -
|
|
EDIT_TextLine(hwnd, es->CurrLine)), 0));
|
|
} else {
|
|
es->textwidth = MAX(es->textwidth,
|
|
EDIT_StrWidth(hwnd, text, strlen(text), 0));
|
|
}
|
|
|
|
if (ch == '\n')
|
|
{
|
|
if (es->wleft > 0)
|
|
FullPaint = TRUE;
|
|
es->wleft = 0;
|
|
EDIT_BuildTextPointers(hwnd);
|
|
EDIT_End(hwnd);
|
|
EDIT_Forward(hwnd);
|
|
|
|
/* invalidate rest of window */
|
|
GetClientRect(hwnd, &rc);
|
|
if (!FullPaint)
|
|
rc.top = es->WndRow * es->txtht;
|
|
InvalidateRect(hwnd, &rc, FALSE);
|
|
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
UpdateWindow(hwnd);
|
|
NOTIFY_PARENT(hwnd, EN_CHANGE);
|
|
return;
|
|
}
|
|
|
|
/* test end of window */
|
|
if (es->WndCol >= es->ClientWidth -
|
|
EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft))
|
|
{
|
|
/* TODO:- Word wrap to be handled here */
|
|
|
|
/* if (!(currchar == text + es->MaxTextLen - 2)) */
|
|
EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
|
|
}
|
|
es->WndCol += EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft);
|
|
es->CurrCol++;
|
|
EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
NOTIFY_PARENT(hwnd, EN_CHANGE);
|
|
dprintf_edit(stddeb,"KeyTyped O.K.\n");
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EM_UNDO message function
|
|
*/
|
|
static LONG EDIT_UndoMsg(HWND hwnd)
|
|
{
|
|
char *text;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (es->hDeletedText)
|
|
{
|
|
text = (char *)GlobalLock(es->hDeletedText);
|
|
es->CurrLine = es->DeletedCurrLine;
|
|
es->CurrCol = es->DeletedCurrCol;
|
|
EDIT_InsertText(hwnd, text, es->DeletedLength);
|
|
GlobalUnlock(es->hDeletedText);
|
|
EDIT_ClearDeletedText(hwnd);
|
|
|
|
es->SelBegLine = es->CurrLine;
|
|
es->SelBegCol = es->CurrCol;
|
|
EDIT_GetLineCol(hwnd, (int)((CurrChar + es->DeletedLength) - text),
|
|
&(es->CurrLine), &(es->CurrCol));
|
|
es->WndRow = es->CurrLine - es->wtop;
|
|
es->WndCol = EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
|
|
es->CurrCol, 0) - es->wleft;
|
|
es->SelEndLine = es->CurrLine;
|
|
es->SelEndCol = es->CurrCol;
|
|
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
return 1;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EM_SETHANDLE message function
|
|
*/
|
|
static void EDIT_SetHandleMsg(HWND hwnd, WPARAM wParam)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (IsMultiLine(hwnd))
|
|
{
|
|
es->hText = (HANDLE)wParam;
|
|
es->textlen = EDIT_HeapSize(hwnd, es->hText);
|
|
es->wlines = 0;
|
|
es->wtop = es->wleft = 0;
|
|
es->CurrLine = es->CurrCol = 0;
|
|
es->WndRow = es->WndCol = 0;
|
|
es->TextChanged = FALSE;
|
|
es->textwidth = 0;
|
|
es->SelBegLine = es->SelBegCol = 0;
|
|
es->SelEndLine = es->SelEndCol = 0;
|
|
dprintf_edit(stddeb, "EDIT_SetHandleMsg: handle %04lx, textlen=%d\n",
|
|
(DWORD)wParam, es->textlen);
|
|
|
|
EDIT_BuildTextPointers(hwnd);
|
|
es->PaintBkgd = TRUE;
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EM_SETTABSTOPS message function
|
|
*/
|
|
static LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
dprintf_edit( stddeb, "EDIT_SetTabStops\n" );
|
|
es->NumTabStops = wParam;
|
|
if (wParam == 0)
|
|
es->TabStops = xrealloc(es->TabStops, 2);
|
|
else if (wParam == 1)
|
|
{
|
|
es->TabStops = xrealloc(es->TabStops, 2);
|
|
es->TabStops[0] = LOWORD(lParam);
|
|
}
|
|
else
|
|
{
|
|
es->TabStops = xrealloc(es->TabStops, wParam * sizeof(*es->TabStops));
|
|
memcpy(es->TabStops, (unsigned short *)PTR_SEG_TO_LIN(lParam), wParam);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EM_GETLINE message function
|
|
*/
|
|
static LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
char *cp;
|
|
int len = 0;
|
|
unsigned char *buffer = (char *)PTR_SEG_TO_LIN(lParam);
|
|
|
|
/* the line wanted */
|
|
cp = EDIT_TextLine (hwnd, wParam);
|
|
len = EDIT_LineLength(hwnd, wParam);
|
|
|
|
/* if cp==NULL nothing will be copied - I hope */
|
|
if ((char *) NULL == cp && 0 != len) {
|
|
fprintf(stdnimp,"edit: EDIT_GetLineMsg cp == NULL && len != 0");
|
|
return 0L;
|
|
}
|
|
|
|
if (0>len)
|
|
fprintf(stdnimp,"edit: EDIT_GetLineMsg len < 0");
|
|
|
|
/* suggested reason for the following line:
|
|
never copy more than the buffer's size ?
|
|
I thought that this would make sense only if
|
|
the lstrcpyn fun was used instead of the gnu strncpy.
|
|
*/
|
|
len = MIN(len, (WORD)(*buffer));
|
|
|
|
if (0>len)
|
|
fprintf(stdnimp,"edit: EDIT_GetLineMsg len < 0 after MIN");
|
|
|
|
dprintf_edit( stddeb, "EDIT_GetLineMsg: %d %d, len %d\n", (int)(WORD)(*buffer), (int)(WORD)(*(char *)buffer), len);
|
|
lstrcpyn(buffer, cp, len);
|
|
|
|
return (LONG)len;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EM_GETSEL message function
|
|
*/
|
|
static LONG EDIT_GetSelMsg(HWND hwnd)
|
|
{
|
|
int so, eo;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
so = es->textptrs[es->SelBegLine] + es->SelBegCol;
|
|
eo = es->textptrs[es->SelEndLine] + es->SelEndCol;
|
|
|
|
return MAKELONG(so, eo);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EM_REPLACESEL message function
|
|
*/
|
|
static void EDIT_ReplaceSel(HWND hwnd, LONG lParam)
|
|
{
|
|
EDIT_DeleteSel(hwnd);
|
|
EDIT_InsertText(hwnd, (char *)PTR_SEG_TO_LIN(lParam),
|
|
strlen((char *)PTR_SEG_TO_LIN(lParam)));
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EM_LINEFROMCHAR message function
|
|
*/
|
|
static LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam)
|
|
{
|
|
int row, col;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (wParam == (WORD)-1)
|
|
return (LONG)(es->SelBegLine);
|
|
else
|
|
EDIT_GetLineCol(hwnd, wParam, &row, &col);
|
|
|
|
return (LONG)row;
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* EM_LINEINDEX message function
|
|
*/
|
|
static LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (wParam == (WORD)-1) wParam = es->CurrLine;
|
|
return es->textptrs[wParam];
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* EM_LINELENGTH message function
|
|
*/
|
|
static LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam)
|
|
{
|
|
int row, col, len;
|
|
int sbl, sbc, sel, sec;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (wParam == (WORD)-1)
|
|
{
|
|
if (SelMarked(es))
|
|
{
|
|
sbl = es->SelBegLine;
|
|
sbc = es->SelBegCol;
|
|
sel = es->SelEndLine;
|
|
sec = es->SelEndCol;
|
|
|
|
if (sbl > sel)
|
|
{
|
|
SWAP_INT(sbl, sel);
|
|
SWAP_INT(sbc, sec);
|
|
}
|
|
if (sbl == sel && sbc > sec)
|
|
SWAP_INT(sbc, sec);
|
|
|
|
if (sbc == sel)
|
|
{
|
|
len = es->textptrs[sbl + 1] - es->textptrs[sbl] - 1;
|
|
return len - sec - sbc;
|
|
}
|
|
|
|
len = es->textptrs[sel + 1] - es->textptrs[sel] - sec - 1;
|
|
return len + sbc;
|
|
}
|
|
else /* no selection marked */
|
|
{
|
|
len = es->textptrs[es->CurrLine + 1] - es->textptrs[es->CurrLine] - 1;
|
|
return len;
|
|
}
|
|
}
|
|
else /* line number specified */
|
|
{
|
|
EDIT_GetLineCol(hwnd, wParam, &row, &col);
|
|
len = es->textptrs[row + 1] - es->textptrs[row];
|
|
return len;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EM_SETSEL message function
|
|
*/
|
|
static void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
INT so, eo;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
so = LOWORD(lParam);
|
|
eo = HIWORD(lParam);
|
|
|
|
if (so == -1) /* if so == -1, clear selection */
|
|
{
|
|
EDIT_ClearSel(hwnd);
|
|
return;
|
|
}
|
|
|
|
if (so == eo) /* if so == eo, set caret only */
|
|
{
|
|
EDIT_GetLineCol(hwnd, (int) so, &(es->CurrLine), &(es->CurrCol));
|
|
es->WndRow = es->CurrLine - es->wtop;
|
|
|
|
if (!wParam)
|
|
{
|
|
if (es->WndRow < 0 || es->WndRow > es->ClientHeight)
|
|
{
|
|
es->wtop = es->CurrLine;
|
|
es->WndRow = 0;
|
|
}
|
|
es->WndCol = EDIT_StrWidth(hwnd,
|
|
EDIT_TextLine(hwnd, es->CurrLine),
|
|
es->CurrCol, 0) - es->wleft;
|
|
if (es->WndCol > es->ClientWidth)
|
|
{
|
|
es->wleft = es->WndCol;
|
|
es->WndCol = 0;
|
|
}
|
|
else if (es->WndCol < 0)
|
|
{
|
|
es->wleft += es->WndCol;
|
|
es->WndCol = 0;
|
|
}
|
|
}
|
|
}
|
|
else /* otherwise set selection */
|
|
{
|
|
if (eo >= 0 && so > eo) /* eo == -1 flag to extend to end of text */
|
|
{
|
|
INT tmp;
|
|
tmp = so;
|
|
so = eo;
|
|
eo = tmp;
|
|
}
|
|
|
|
EDIT_GetLineCol(hwnd, (int) so, &(es->SelBegLine), &(es->SelBegCol));
|
|
EDIT_GetLineCol(hwnd, (int) eo, &(es->SelEndLine), &(es->SelEndCol));
|
|
es->CurrLine = es->SelEndLine;
|
|
es->CurrCol = es->SelEndCol;
|
|
es->WndRow = es->SelEndLine - es->wtop;
|
|
|
|
if (!wParam) /* don't suppress scrolling of text */
|
|
{
|
|
if (es->WndRow < 0)
|
|
{
|
|
es->wtop = es->SelEndLine;
|
|
es->WndRow = 0;
|
|
}
|
|
else if (es->WndRow > es->ClientHeight)
|
|
{
|
|
es->wtop += es->WndRow - es->ClientHeight;
|
|
es->WndRow = es->ClientHeight;
|
|
}
|
|
es->WndCol = EDIT_StrWidth(hwnd,
|
|
EDIT_TextLine(hwnd, es->SelEndLine),
|
|
es->SelEndCol, 0) - es->wleft;
|
|
if (es->WndCol > es->ClientWidth)
|
|
{
|
|
es->wleft += es->WndCol - es->ClientWidth;
|
|
es->WndCol = es->ClientWidth;
|
|
}
|
|
else if (es->WndCol < 0)
|
|
{
|
|
es->wleft += es->WndCol;
|
|
es->WndCol = 0;
|
|
}
|
|
}
|
|
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_SETFONT
|
|
*/
|
|
static void EDIT_WM_SetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HDC hdc;
|
|
TEXTMETRIC tm;
|
|
HFONT oldfont;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
es->hFont = (HANDLE)wParam;
|
|
hdc = GetDC(hwnd);
|
|
oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
|
|
GetCharWidth(hdc, 0, 255, es->CharWidths);
|
|
GetTextMetrics(hdc, &tm);
|
|
es->txtht = tm.tmHeight + tm.tmExternalLeading;
|
|
SelectObject(hdc, (HANDLE)oldfont);
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
es->WndRow = (es->CurrLine - es->wtop) / es->txtht;
|
|
es->WndCol = EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
|
|
es->CurrCol, 0) - es->wleft;
|
|
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
es->PaintBkgd = TRUE;
|
|
if (lParam) UpdateWindow(hwnd);
|
|
EDIT_RecalcSize(hwnd,es);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_PASTE
|
|
*/
|
|
static void EDIT_WM_Paste(HWND hwnd)
|
|
{
|
|
HANDLE hClipMem;
|
|
char *lpClipMem;
|
|
|
|
OpenClipboard(hwnd);
|
|
if (!(hClipMem = GetClipboardData(CF_TEXT)))
|
|
{
|
|
/* no text in clipboard */
|
|
CloseClipboard();
|
|
return;
|
|
}
|
|
lpClipMem = GlobalLock(hClipMem);
|
|
EDIT_InsertText(hwnd, lpClipMem, strlen(lpClipMem));
|
|
GlobalUnlock(hClipMem);
|
|
CloseClipboard();
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_PAINT
|
|
*/
|
|
static void EDIT_WM_Paint(HWND hwnd)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
int y;
|
|
RECT rc;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
rc = ps.rcPaint;
|
|
|
|
dprintf_edit(stddeb,"WM_PAINT: rc=(%ld,%ld), (%ld,%ld)\n", (LONG)rc.left,
|
|
(LONG)rc.top, (LONG)rc.right, (LONG)rc.bottom);
|
|
|
|
if (es->PaintBkgd)
|
|
FillWindow(GetParent(hwnd), hwnd, hdc, (HBRUSH)CTLCOLOR_EDIT);
|
|
|
|
for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
|
|
{
|
|
if (y < (IsMultiLine(hwnd) ? es->wlines : 1) - es->wtop)
|
|
EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
|
|
}
|
|
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
|
|
static BOOL LOCAL_HeapExists(HANDLE ds)
|
|
{
|
|
/* There is always a local heap in WineLib */
|
|
#ifndef WINELIB
|
|
INSTANCEDATA *ptr = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( ds, 0 );
|
|
if (!ptr->heap) return 0;
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_NCCREATE
|
|
*/
|
|
static long EDIT_WM_NCCreate(HWND hwnd, LONG lParam)
|
|
{
|
|
CREATESTRUCT *createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
|
|
WND *wndPtr = WIN_FindWndPtr(hwnd);
|
|
EDITSTATE *es;
|
|
char *text = NULL;
|
|
HANDLE ds;
|
|
|
|
/* store pointer to local or global heap in window structure so that */
|
|
/* EDITSTATE structure itself can be stored on local heap */
|
|
/* allocate space for state variable structure */
|
|
es = xmalloc( sizeof(EDITSTATE) );
|
|
SetWindowLong( hwnd, 0, (LONG)es );
|
|
es->textptrs = xmalloc(sizeof(int));
|
|
es->CharWidths = xmalloc(256 * sizeof(INT));
|
|
es->ClientWidth = es->ClientHeight = 1;
|
|
/* --- text buffer */
|
|
es->MaxTextLen = MAXTEXTLEN + 1;
|
|
es->PasswordChar = '*';
|
|
/*
|
|
* Hack - If there is no local heap then hwnd should be a globalHeap block
|
|
* and the local heap needs to be initilised to the same size(minus something)
|
|
* as the global block
|
|
*/
|
|
ds = WIN_GetWindowInstance(hwnd);
|
|
|
|
if (!LOCAL_HeapExists(ds))
|
|
{
|
|
DWORD globalSize;
|
|
globalSize = GlobalSize(ds);
|
|
dprintf_edit(stddeb, "No local heap allocated global size is %ld 0x%lx\n",globalSize, globalSize);
|
|
/*
|
|
* I assume the local heap should start at 0
|
|
*/
|
|
LocalInit(ds, 0, globalSize);
|
|
/*
|
|
* Apparantly we should do an UnlockSegment here but i think this
|
|
* is because LocalInit is supposed to do a LockSegment. Since
|
|
* Local Init doesn't do this then it doesn't seem like a good idea to do the
|
|
* UnlockSegment here yet!
|
|
* UnlockSegment(hwnd);
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
if (!(createStruct->lpszName))
|
|
{
|
|
dprintf_edit( stddeb, "EDIT_WM_NCCREATE: lpszName == 0\n" );
|
|
es->textlen = EditBufStartLen(hwnd) + 1;
|
|
es->hText = EDIT_HeapAlloc(hwnd, es->textlen + 2, LMEM_MOVEABLE);
|
|
text = EDIT_HeapLock(hwnd, es->hText);
|
|
memset(text, 0, es->textlen + 2);
|
|
es->wlines = 0;
|
|
es->textwidth = 0;
|
|
EDIT_ClearTextPointers(hwnd);
|
|
if (IsMultiLine(hwnd)) strcpy(text, "\r\n");
|
|
EDIT_BuildTextPointers(hwnd);
|
|
}
|
|
else
|
|
{
|
|
char *windowName = (char *)PTR_SEG_TO_LIN( createStruct->lpszName );
|
|
dprintf_edit( stddeb, "EDIT_WM_NCCREATE: lpszName != 0\n" );
|
|
|
|
if (strlen(windowName) < EditBufStartLen(hwnd))
|
|
{
|
|
es->textlen = EditBufStartLen(hwnd) + 3;
|
|
es->hText = EDIT_HeapAlloc(hwnd, es->textlen + 2, LMEM_MOVEABLE);
|
|
if (es->hText)
|
|
{
|
|
text = EDIT_HeapLock(hwnd, es->hText);
|
|
if (text)
|
|
{
|
|
strcpy(text, windowName);
|
|
if(IsMultiLine(hwnd)) {
|
|
strcat(text, "\r\n");
|
|
}
|
|
*(text + es->textlen) = '\0';
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
es->textlen = strlen(windowName) + 3;
|
|
es->hText = EDIT_HeapAlloc(hwnd, es->textlen + 2, LMEM_MOVEABLE);
|
|
text = EDIT_HeapLock(hwnd, es->hText);
|
|
strcpy(text, windowName);
|
|
if(IsMultiLine(hwnd)) strcat(text, "\r\n");
|
|
*(text + es->textlen) = '\0';
|
|
}
|
|
if (text)
|
|
{
|
|
*(text + es->textlen + 1) = '\0';
|
|
EDIT_BuildTextPointers(hwnd);
|
|
}
|
|
}
|
|
|
|
/* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
|
|
/* the corresponding WS_* style is set */
|
|
if (createStruct->style & WS_VSCROLL)
|
|
wndPtr->dwStyle |= ES_AUTOVSCROLL;
|
|
if (createStruct->style & WS_HSCROLL)
|
|
wndPtr->dwStyle |= ES_AUTOHSCROLL;
|
|
|
|
/* remove the WS_CAPTION style if it has been set - this is really a */
|
|
/* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
|
|
if (wndPtr->dwStyle & WS_BORDER && wndPtr->dwStyle & WS_DLGFRAME)
|
|
wndPtr->dwStyle ^= WS_DLGFRAME;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_CREATE
|
|
*/
|
|
static long EDIT_WM_Create(HWND hwnd, LONG lParam)
|
|
{
|
|
HDC hdc;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
CLASS *classPtr;
|
|
TEXTMETRIC tm;
|
|
|
|
/* initialize state variable structure */
|
|
hdc = GetDC(hwnd);
|
|
|
|
/* --- char width array */
|
|
/* only initialise chars <= 32 as X returns strange widths */
|
|
/* for other chars */
|
|
memset(es->CharWidths, 0, 256 * sizeof(INT));
|
|
GetCharWidth(hdc, 32, 254, &es->CharWidths[32]);
|
|
|
|
/* --- other structure variables */
|
|
GetTextMetrics(hdc, &tm);
|
|
es->txtht = tm.tmHeight + tm.tmExternalLeading;
|
|
EDIT_RecalcSize(hwnd,es);
|
|
es->wtop = es->wleft = 0;
|
|
es->CurrCol = es->CurrLine = 0;
|
|
es->WndCol = es->WndRow = 0;
|
|
es->TextChanged = FALSE;
|
|
es->SelBegLine = es->SelBegCol = 0;
|
|
es->SelEndLine = es->SelEndCol = 0;
|
|
es->hFont = 0;
|
|
es->hDeletedText = 0;
|
|
es->DeletedLength = 0;
|
|
es->NumTabStops = 0;
|
|
es->TabStops = xmalloc( sizeof(short) );
|
|
|
|
/* allocate space for a line full of blanks to speed up */
|
|
/* line filling */
|
|
es->BlankLine = xmalloc( (es->ClientWidth / es->CharWidths[32]) + 2);
|
|
memset(es->BlankLine, ' ', (es->ClientWidth / es->CharWidths[32]) + 2);
|
|
es->BlankLine[(es->ClientWidth / es->CharWidths[32]) + 1] = 0;
|
|
|
|
/* set up text cursor for edit class */
|
|
{
|
|
char editname[] = "EDIT";
|
|
CLASS_FindClassByName( MAKE_SEGPTR(editname), 0, &classPtr);
|
|
classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM);
|
|
}
|
|
|
|
/* paint background on first WM_PAINT */
|
|
es->PaintBkgd = TRUE;
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
return 0L;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_VSCROLL
|
|
*/
|
|
static void EDIT_WM_VScroll(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (IsMultiLine(hwnd))
|
|
{
|
|
HideCaret(hwnd);
|
|
|
|
switch (wParam)
|
|
{
|
|
case SB_LINEUP:
|
|
case SB_LINEDOWN:
|
|
EDIT_VScrollLine(hwnd, wParam);
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
case SB_PAGEDOWN:
|
|
EDIT_VScrollPage(hwnd, wParam);
|
|
break;
|
|
}
|
|
}
|
|
|
|
SetCaretPos(es->WndCol, es->WndRow);
|
|
ShowCaret(hwnd);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_HSCROLL
|
|
*/
|
|
static void EDIT_WM_HScroll(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
switch (wParam)
|
|
{
|
|
case SB_LINEUP:
|
|
case SB_LINEDOWN:
|
|
HideCaret(hwnd);
|
|
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_SIZE
|
|
*/
|
|
static void EDIT_WM_Size(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
EDIT_RecalcSize(hwnd,es);
|
|
if (wParam != SIZE_MAXIMIZED && wParam != SIZE_RESTORED) return;
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
es->PaintBkgd = TRUE;
|
|
UpdateWindow(hwnd);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_LBUTTONDOWN
|
|
*/
|
|
static void EDIT_WM_LButtonDown(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
char *cp;
|
|
int len;
|
|
BOOL end = FALSE;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (SelMarked(es))
|
|
EDIT_ClearSel(hwnd);
|
|
|
|
es->WndRow = HIWORD(lParam) / es->txtht;
|
|
dprintf_edit( stddeb, "EDIT_LButtonDown: %04x %08lx, WndRow %d\n", wParam,
|
|
lParam, es->WndRow );
|
|
if (!IsMultiLine(hwnd)) es->WndRow = 0;
|
|
else if (es->WndRow > es->wlines - es->wtop - 1)
|
|
{
|
|
es->WndRow = es->wlines - es->wtop - 1;
|
|
end = TRUE;
|
|
}
|
|
es->CurrLine = es->wtop + es->WndRow;
|
|
|
|
cp = EDIT_TextLine(hwnd, es->CurrLine);
|
|
len = EDIT_LineLength(hwnd, es->CurrLine);
|
|
es->WndCol = LOWORD(lParam) + es->wleft;
|
|
if (end || es->WndCol > EDIT_StrWidth(hwnd, cp, len, 0))
|
|
es->WndCol = EDIT_StrWidth(hwnd, cp, len, 0);
|
|
dprintf_edit( stddeb, "EDIT_LButtonDown: CurrLine %d wtop %d wndcol %d\n",
|
|
es->CurrLine, es->wtop, es->WndCol);
|
|
es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
|
|
es->WndCol -= es->wleft;
|
|
|
|
ButtonDown = TRUE;
|
|
ButtonRow = es->CurrLine;
|
|
ButtonCol = es->CurrCol;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_MOUSEMOVE
|
|
*/
|
|
static void EDIT_WM_MouseMove(HWND hwnd, WORD wParam, LONG lParam)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
if (wParam != MK_LBUTTON)
|
|
return;
|
|
|
|
HideCaret(hwnd);
|
|
if (ButtonDown)
|
|
{
|
|
EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
|
|
TextMarking = TRUE;
|
|
ButtonDown = FALSE;
|
|
}
|
|
|
|
if (TextMarking)
|
|
{
|
|
EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
}
|
|
ShowCaret(hwnd);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_CHAR
|
|
*/
|
|
static void EDIT_WM_Char(HWND hwnd, WORD wParam)
|
|
{
|
|
dprintf_edit(stddeb,"EDIT_WM_Char: wParam=%c\n", (char)wParam);
|
|
|
|
switch (wParam)
|
|
{
|
|
case '\r':
|
|
case '\n':
|
|
if (!IsMultiLine(hwnd))
|
|
break;
|
|
wParam = '\n';
|
|
EDIT_KeyTyped(hwnd, wParam);
|
|
break;
|
|
|
|
case VK_TAB:
|
|
if (!IsMultiLine(hwnd))
|
|
break;
|
|
EDIT_KeyTyped(hwnd, wParam);
|
|
break;
|
|
|
|
default:
|
|
if (wParam >= 20 && wParam <= 254 && wParam != 127 )
|
|
EDIT_KeyTyped(hwnd, wParam);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_KEYDOWN
|
|
*/
|
|
static void EDIT_WM_KeyDown(HWND hwnd, WORD wParam)
|
|
{
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
dprintf_edit(stddeb,"EDIT_WM_KeyDown: key=%x\n", wParam);
|
|
|
|
HideCaret(hwnd);
|
|
switch (wParam)
|
|
{
|
|
case VK_UP:
|
|
if (SelMarked(es))
|
|
EDIT_ClearSel(hwnd);
|
|
if (IsMultiLine(hwnd))
|
|
EDIT_Upward(hwnd);
|
|
else
|
|
EDIT_Backward(hwnd);
|
|
break;
|
|
|
|
case VK_DOWN:
|
|
if (SelMarked(es))
|
|
EDIT_ClearSel(hwnd);
|
|
if (IsMultiLine(hwnd))
|
|
EDIT_Downward(hwnd);
|
|
else
|
|
EDIT_Forward(hwnd);
|
|
break;
|
|
|
|
case VK_RIGHT:
|
|
if (SelMarked(es))
|
|
EDIT_ClearSel(hwnd);
|
|
EDIT_Forward(hwnd);
|
|
break;
|
|
|
|
case VK_LEFT:
|
|
if (SelMarked(es))
|
|
EDIT_ClearSel(hwnd);
|
|
EDIT_Backward(hwnd);
|
|
break;
|
|
|
|
case VK_HOME:
|
|
if (SelMarked(es))
|
|
EDIT_ClearSel(hwnd);
|
|
EDIT_Home(hwnd);
|
|
break;
|
|
|
|
case VK_END:
|
|
if (SelMarked(es))
|
|
EDIT_ClearSel(hwnd);
|
|
EDIT_End(hwnd);
|
|
break;
|
|
|
|
case VK_PRIOR:
|
|
if (IsMultiLine(hwnd))
|
|
{
|
|
if (SelMarked(es))
|
|
EDIT_ClearSel(hwnd);
|
|
EDIT_KeyVScrollPage(hwnd, SB_PAGEUP);
|
|
}
|
|
break;
|
|
|
|
case VK_NEXT:
|
|
if (IsMultiLine(hwnd))
|
|
{
|
|
if (SelMarked(es))
|
|
EDIT_ClearSel(hwnd);
|
|
EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN);
|
|
}
|
|
break;
|
|
|
|
case VK_BACK:
|
|
if (SelMarked(es))
|
|
EDIT_DeleteSel(hwnd);
|
|
else
|
|
{
|
|
if (es->CurrCol == 0 && es->CurrLine == 0)
|
|
break;
|
|
EDIT_Backward(hwnd);
|
|
EDIT_DelKey(hwnd);
|
|
}
|
|
break;
|
|
|
|
case VK_DELETE:
|
|
if (SelMarked(es))
|
|
EDIT_DeleteSel(hwnd);
|
|
else
|
|
EDIT_DelKey(hwnd);
|
|
break;
|
|
}
|
|
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* WM_SETTEXT
|
|
*/
|
|
static LONG EDIT_WM_SetText(HWND hwnd, LONG lParam)
|
|
{
|
|
int len;
|
|
char *text,*settext;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
settext = PTR_SEG_TO_LIN( lParam );
|
|
dprintf_edit( stddeb,"WM_SetText, length %d\n",strlen(settext) );
|
|
if (strlen(settext) <= es->MaxTextLen)
|
|
{
|
|
len = settext != NULL ? strlen(settext) : 0;
|
|
EDIT_ClearText(hwnd);
|
|
es->textlen = len;
|
|
dprintf_edit( stddeb, "EDIT_WM_SetText: realloc\n" );
|
|
es->hText = EDIT_HeapReAlloc(hwnd, es->hText, len + 3);
|
|
text = EDIT_HeapLock(hwnd, es->hText);
|
|
if (lParam)
|
|
strcpy(text, (char *)PTR_SEG_TO_LIN(lParam));
|
|
text[len] = '\0';
|
|
text[len + 1] = '\0';
|
|
text[len + 2] = '\0';
|
|
EDIT_BuildTextPointers(hwnd);
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
es->PaintBkgd = TRUE;
|
|
es->TextChanged = TRUE;
|
|
return 0;
|
|
}
|
|
else
|
|
return EN_ERRSPACE;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* EditWndProc()
|
|
*/
|
|
LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LONG lResult = 0;
|
|
char *textPtr;
|
|
int len;
|
|
EDITSTATE *es = EDIT_GetEditState(hwnd);
|
|
|
|
switch (uMsg) {
|
|
case EM_CANUNDO:
|
|
lResult = (LONG)es->hDeletedText;
|
|
break;
|
|
|
|
case EM_EMPTYUNDOBUFFER:
|
|
EDIT_ClearDeletedText(hwnd);
|
|
break;
|
|
|
|
case EM_FMTLINES:
|
|
fprintf(stdnimp,"edit: EM_FMTLINES message received\n");
|
|
if (!wParam)
|
|
lResult = 1L;
|
|
else
|
|
lResult = 0L;
|
|
break;
|
|
|
|
case EM_GETFIRSTVISIBLELINE:
|
|
lResult = es->wtop;
|
|
break;
|
|
|
|
case EM_GETHANDLE:
|
|
lResult = (LONG)es->hText;
|
|
break;
|
|
|
|
case EM_GETLINE:
|
|
if (IsMultiLine(hwnd))
|
|
lResult = EDIT_GetLineMsg(hwnd, wParam, lParam);
|
|
else
|
|
lResult = 0L;
|
|
break;
|
|
|
|
case EM_GETLINECOUNT:
|
|
if (IsMultiLine(hwnd))
|
|
lResult = es->wlines;
|
|
else
|
|
lResult = 0L;
|
|
break;
|
|
|
|
case EM_GETMODIFY:
|
|
lResult = es->TextChanged;
|
|
break;
|
|
|
|
case EM_GETPASSWORDCHAR:
|
|
/* FIXME: is this the right place to return the character? */
|
|
lResult = es->PasswordChar;
|
|
break;
|
|
|
|
case EM_GETRECT:
|
|
GetWindowRect(hwnd, (LPRECT)PTR_SEG_TO_LIN(lParam));
|
|
break;
|
|
|
|
case EM_GETSEL:
|
|
lResult = EDIT_GetSelMsg(hwnd);
|
|
break;
|
|
|
|
case EM_GETWORDBREAKPROC:
|
|
fprintf(stdnimp,"edit: cannot process EM_GETWORDBREAKPROC message\n");
|
|
break;
|
|
|
|
case EM_LIMITTEXT:
|
|
if (wParam)
|
|
es->MaxTextLen = wParam;
|
|
else if (IsMultiLine(hwnd))
|
|
es->MaxTextLen = 65535;
|
|
else
|
|
es->MaxTextLen = 32767;
|
|
break;
|
|
|
|
case EM_LINEFROMCHAR:
|
|
lResult = EDIT_LineFromCharMsg(hwnd, wParam);
|
|
break;
|
|
|
|
case EM_LINEINDEX:
|
|
if (IsMultiLine(hwnd))
|
|
lResult = EDIT_LineIndexMsg(hwnd, wParam);
|
|
else
|
|
lResult = 0L;
|
|
break;
|
|
|
|
case EM_LINELENGTH:
|
|
lResult = EDIT_LineLengthMsg(hwnd, wParam);
|
|
break;
|
|
|
|
case EM_LINESCROLL:
|
|
fprintf(stdnimp,"edit: cannot process EM_LINESCROLL message\n");
|
|
break;
|
|
|
|
case EM_REPLACESEL:
|
|
HideCaret(hwnd);
|
|
EDIT_ReplaceSel(hwnd, lParam);
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
break;
|
|
|
|
case EM_SETHANDLE:
|
|
HideCaret(hwnd);
|
|
EDIT_SetHandleMsg(hwnd, wParam);
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
break;
|
|
|
|
case EM_SETMODIFY:
|
|
es->TextChanged = wParam;
|
|
break;
|
|
|
|
case EM_SETPASSWORDCHAR:
|
|
es->PasswordChar = (char) wParam;
|
|
break;
|
|
|
|
case EM_SETREADONLY:
|
|
fprintf(stdnimp,"edit: cannot process EM_SETREADONLY message\n");
|
|
break;
|
|
|
|
case EM_SETRECT:
|
|
case EM_SETRECTNP:
|
|
fprintf(stdnimp,"edit: cannot process EM_SETRECT(NP) message\n");
|
|
break;
|
|
|
|
case EM_SETSEL:
|
|
HideCaret(hwnd);
|
|
EDIT_SetSelMsg(hwnd, wParam, lParam);
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
break;
|
|
|
|
case EM_SETTABSTOPS:
|
|
lResult = EDIT_SetTabStopsMsg(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case EM_SETWORDBREAKPROC:
|
|
fprintf(stdnimp,"edit: cannot process EM_SETWORDBREAKPROC message\n");
|
|
break;
|
|
|
|
case EM_UNDO:
|
|
HideCaret(hwnd);
|
|
lResult = EDIT_UndoMsg(hwnd);
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
break;
|
|
|
|
case WM_GETDLGCODE:
|
|
return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
|
|
|
|
case WM_CHAR:
|
|
EDIT_WM_Char(hwnd, wParam);
|
|
break;
|
|
|
|
case WM_COPY:
|
|
EDIT_CopyToClipboard(hwnd);
|
|
EDIT_ClearSel(hwnd);
|
|
break;
|
|
|
|
case WM_CREATE:
|
|
lResult = EDIT_WM_Create(hwnd, lParam);
|
|
break;
|
|
|
|
case WM_CUT:
|
|
EDIT_CopyToClipboard(hwnd);
|
|
EDIT_DeleteSel(hwnd);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
free(es->textptrs);
|
|
free(es->CharWidths);
|
|
free(es->TabStops);
|
|
free(es->BlankLine);
|
|
EDIT_HeapFree(hwnd, es->hText);
|
|
free( EDIT_GetEditState(hwnd) );
|
|
break;
|
|
|
|
case WM_ENABLE:
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
break;
|
|
|
|
case WM_GETTEXT:
|
|
textPtr = EDIT_HeapLock(hwnd, es->hText);
|
|
len = strlen( textPtr );
|
|
if ((int)wParam > len)
|
|
{
|
|
strcpy((char *)PTR_SEG_TO_LIN(lParam), textPtr);
|
|
lResult = (DWORD)len ;
|
|
}
|
|
else
|
|
lResult = 0L;
|
|
EDIT_HeapUnlock(hwnd, es->hText);
|
|
break;
|
|
|
|
case WM_GETTEXTLENGTH:
|
|
textPtr = EDIT_HeapLock(hwnd, es->hText);
|
|
lResult = (DWORD)strlen(textPtr);
|
|
EDIT_HeapUnlock(hwnd, es->hText);
|
|
break;
|
|
|
|
case WM_HSCROLL:
|
|
EDIT_WM_HScroll(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
EDIT_WM_KeyDown(hwnd, wParam);
|
|
break;
|
|
|
|
case WM_KILLFOCUS:
|
|
es->HaveFocus = FALSE;
|
|
DestroyCaret();
|
|
if (SelMarked(es)) EDIT_ClearSel(hwnd);
|
|
NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
HideCaret(hwnd);
|
|
SetFocus(hwnd);
|
|
SetCapture(hwnd);
|
|
EDIT_WM_LButtonDown(hwnd, wParam, lParam);
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
if (GetCapture() != hwnd) break;
|
|
ReleaseCapture();
|
|
ButtonDown = FALSE;
|
|
if (TextMarking)
|
|
EDIT_StopMarking(hwnd);
|
|
break;
|
|
|
|
case WM_MOUSEMOVE:
|
|
if (es->HaveFocus)
|
|
EDIT_WM_MouseMove(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_MOVE:
|
|
lResult = 0;
|
|
break;
|
|
|
|
case WM_NCCREATE:
|
|
lResult = EDIT_WM_NCCreate(hwnd, lParam);
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
EDIT_WM_Paint(hwnd);
|
|
break;
|
|
|
|
case WM_PASTE:
|
|
EDIT_WM_Paste(hwnd);
|
|
break;
|
|
|
|
case WM_SETFOCUS:
|
|
es->HaveFocus = TRUE;
|
|
CreateCaret(hwnd, 0, 2, es->txtht);
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
NOTIFY_PARENT(hwnd, EN_SETFOCUS);
|
|
break;
|
|
|
|
case WM_SETFONT:
|
|
HideCaret(hwnd);
|
|
EDIT_WM_SetFont(hwnd, wParam, lParam);
|
|
SetCaretPos(es->WndCol, es->WndRow * es->txtht);
|
|
ShowCaret(hwnd);
|
|
break;
|
|
#if 0
|
|
case WM_SETREDRAW:
|
|
dprintf_edit(stddeb, "WM_SETREDRAW: hwnd=%d, wParam=%x\n",
|
|
hwnd, wParam);
|
|
lResult = 0;
|
|
break;
|
|
#endif
|
|
case WM_SETTEXT:
|
|
EDIT_WM_SetText(hwnd, lParam);
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
EDIT_WM_Size(hwnd, wParam, lParam);
|
|
lResult = 0;
|
|
break;
|
|
|
|
case WM_VSCROLL:
|
|
EDIT_WM_VScroll(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
default:
|
|
lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|