Skip to content
Snippets Groups Projects
edit.c 77.5 KiB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
/*
 * Edit control
 *
 * Copyright  David W. Metcalfe, 1994
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
 * Release 3, July 1994
Alexandre Julliard's avatar
Alexandre Julliard committed
 */

static char Copyright[] = "Copyright  David W. Metcalfe, 1994";

Alexandre Julliard's avatar
Alexandre Julliard committed
#include <stdio.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
#include <stdlib.h>
#include <string.h>
#include <windows.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
#include <heap.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "win.h"
#include "class.h"
#include "user.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "stddebug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
/* #define DEBUG_EDIT */
/* #undef  DEBUG_EDIT */
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "debug.h"

Alexandre Julliard's avatar
Alexandre Julliard committed

#define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
	SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
		 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));

Alexandre Julliard's avatar
Alexandre Julliard committed
#define MAXTEXTLEN 30000   /* maximum text buffer length */
Alexandre Julliard's avatar
Alexandre Julliard committed
#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 */

#define HSCROLLDIM (ClientWidth(wndPtr) / 3)
                           /* "line" dimension for horizontal scroll */

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 */
    HANDLE hCharWidths;      /* widths of chars in font */
    HANDLE hTextPtrs;        /* list of line offsets */
    HANDLE hBlankLine;       /* 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 */
Alexandre Julliard's avatar
Alexandre Julliard committed
    HFONT hFont;             /* handle of current font (if not default) */
    HANDLE hDeletedText;     /* handle to deleted txet 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 */
Alexandre Julliard's avatar
Alexandre Julliard committed
    int NumTabStops;         /* number of tab stops in buffer hTabStops */
    HANDLE hTabStops;        /* handle of tab stops buffer */
Alexandre Julliard's avatar
Alexandre Julliard committed
} EDITSTATE;


Alexandre Julliard's avatar
Alexandre Julliard committed
#define ClientWidth(wndPtr) \
	(wndPtr->rectClient.right > wndPtr->rectClient.left ? \
	wndPtr->rectClient.right - wndPtr->rectClient.left : 0)
#define ClientHeight(wndPtr, es) \
	(wndPtr->rectClient.bottom > wndPtr->rectClient.top ? \
	(wndPtr->rectClient.bottom - wndPtr->rectClient.top) / es->txtht : 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
#define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
			    ? EDITLEN : ENTRYLEN)
#define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
Alexandre Julliard's avatar
Alexandre Julliard committed
#define SelMarked(es) (es->SelBegLine != 0 || es->SelBegCol != 0 || \
		       es->SelEndLine != 0 || es->SelEndCol != 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
#define ROUNDUP(numer, denom) (((numer) % (denom)) \
			       ? ((((numer) + (denom)) / (denom)) * (denom)) \
			       : (numer) + (denom))
Alexandre Julliard's avatar
Alexandre Julliard committed

/* macros to access window styles */
#define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
#define IsAutoHScroll() (wndPtr->dwStyle & ES_AUTOHSCROLL)
#define IsMultiLine() (wndPtr->dwStyle & ES_MULTILINE)
#define IsVScrollBar() (wndPtr->dwStyle & WS_VSCROLL)
#define IsHScrollBar() (wndPtr->dwStyle & 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 */


LONG EditWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
long EDIT_NCCreateMsg(HWND hwnd, LONG lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
long EDIT_CreateMsg(HWND hwnd, LONG lParam);
void EDIT_ClearTextPointers(HWND hwnd);
void EDIT_BuildTextPointers(HWND hwnd);
void EDIT_ModTextPointers(HWND hwnd, int lineno, int var);
void EDIT_PaintMsg(HWND hwnd);
HANDLE EDIT_GetTextLine(HWND hwnd, int selection);
char *EDIT_TextLine(HWND hwnd, int sel);
Alexandre Julliard's avatar
Alexandre Julliard committed
int EDIT_StrLength(HWND hwnd, unsigned char *str, int len, int pcol);
Alexandre Julliard's avatar
Alexandre Julliard committed
int EDIT_LineLength(HWND hwnd, int num);
Alexandre Julliard's avatar
Alexandre Julliard committed
void EDIT_WriteTextLine(HWND hwnd, RECT *rc, int y);
void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row, 
		    int col, RECT *rc, BOOL blank, BOOL reverse);
Alexandre Julliard's avatar
Alexandre Julliard committed
HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff);
Alexandre Julliard's avatar
Alexandre Julliard committed
void EDIT_CharMsg(HWND hwnd, WORD wParam);
void EDIT_KeyTyped(HWND hwnd, short ch);
Alexandre Julliard's avatar
Alexandre Julliard committed
int EDIT_CharWidth(HWND hwnd, short ch, int pcol);
int EDIT_GetNextTabStop(HWND hwnd, int pcol);
Alexandre Julliard's avatar
Alexandre Julliard committed
void EDIT_Forward(HWND hwnd);
void EDIT_Downward(HWND hwnd);
void EDIT_Upward(HWND hwnd);
void EDIT_Backward(HWND hwnd);
void EDIT_End(HWND hwnd);
void EDIT_Home(HWND hwnd);
void EDIT_StickEnd(HWND hwnd);
void EDIT_KeyDownMsg(HWND hwnd, WORD wParam);
void EDIT_KeyHScroll(HWND hwnd, WORD opt);
void EDIT_KeyVScrollLine(HWND hwnd, WORD opt);
void EDIT_KeyVScrollPage(HWND hwnd, WORD opt);
void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt);
int EDIT_ComputeVScrollPos(HWND hwnd);
int EDIT_ComputeHScrollPos(HWND hwnd);
void EDIT_DelKey(HWND hwnd);
void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
void EDIT_VScrollLine(HWND hwnd, WORD opt);
void EDIT_VScrollPage(HWND hwnd, WORD opt);
void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam);
void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam);
void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam);
int EDIT_PixelToChar(HWND hwnd, int row, int *pixel);
LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam);
void EDIT_ClearText(HWND hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col);
void EDIT_DeleteSel(HWND hwnd);
void EDIT_ClearSel(HWND hwnd);
int EDIT_TextLineNumber(HWND hwnd, char *lp);
void EDIT_SetAnchor(HWND hwnd, int row, int col);
void EDIT_ExtendSel(HWND hwnd, int x, int y);
Alexandre Julliard's avatar
Alexandre Julliard committed
void EDIT_WriteSel(HWND hwnd, int y, int start, int end);
Alexandre Julliard's avatar
Alexandre Julliard committed
void EDIT_StopMarking(HWND hwnd);
LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
LONG EDIT_GetSelMsg(HWND hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
void EDIT_ReplaceSel(HWND hwnd, LONG lParam);
void EDIT_InsertText(HWND hwnd, char *str, int len);
Alexandre Julliard's avatar
Alexandre Julliard committed
LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam);
LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam);
void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam);
void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len, int line, 
			  int col);
void EDIT_ClearDeletedText(HWND hwnd);
LONG EDIT_UndoMsg(HWND hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
unsigned int EDIT_HeapAlloc(HWND hwnd, int bytes);
void *EDIT_HeapAddr(HWND hwnd, unsigned int handle);
unsigned int EDIT_HeapReAlloc(HWND hwnd, unsigned int handle, int bytes);
void EDIT_HeapFree(HWND hwnd, unsigned int handle);
unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle);
Alexandre Julliard's avatar
Alexandre Julliard committed
void EDIT_SetHandleMsg(HWND hwnd, WORD wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
void EDIT_CopyToClipboard(HWND hwnd);
void EDIT_PasteMsg(HWND hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
void swap(int *a, int *b);


LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
{
    LONG lResult = 0L;
    char *textPtr;
    int len;
    WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
    EDITSTATE *es = 
	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
Alexandre Julliard's avatar
Alexandre Julliard committed

    switch (uMsg) {
    case EM_CANUNDO:
Alexandre Julliard's avatar
Alexandre Julliard committed
	lResult = es->hDeletedText;
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;
	
Alexandre Julliard's avatar
Alexandre Julliard committed
    case EM_EMPTYUNDOBUFFER:
	EDIT_ClearDeletedText(hwnd);
	break;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case EM_FMTLINES:
Alexandre Julliard's avatar
Alexandre Julliard committed
	fprintf(stdnimp,"edit: EM_FMTLINES message received\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (!wParam)
	    lResult = 1L;
	else
	    lResult = 0L;
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_GETFIRSTVISIBLELINE:
	lResult = es->wtop;
	break;

    case EM_GETHANDLE:
Alexandre Julliard's avatar
Alexandre Julliard committed
	lResult = es->hText;
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_GETLINE:
	if (IsMultiLine())
	    lResult = EDIT_GetLineMsg(hwnd, wParam, lParam);
	else
	    lResult = 0L;
	break;

    case EM_GETLINECOUNT:
	if (IsMultiLine())
	    lResult = es->wlines;
	else
	    lResult = 0L;
	break;

    case EM_GETMODIFY:
	lResult = es->TextChanged;
	break;

    case EM_GETPASSWORDCHAR:
Alexandre Julliard's avatar
Alexandre Julliard committed
	fprintf(stdnimp,"edit: cannot process EM_GETPASSWORDCHAR message\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_GETRECT:
	GetWindowRect(hwnd, (LPRECT)lParam);
	break;

    case EM_GETSEL:
	lResult = EDIT_GetSelMsg(hwnd);
	break;

    case EM_GETWORDBREAKPROC:
Alexandre Julliard's avatar
Alexandre Julliard committed
	fprintf(stdnimp,"edit: cannot process EM_GETWORDBREAKPROC message\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_LIMITTEXT:
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (wParam)
	    es->MaxTextLen = wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
	else if (IsMultiLine())
	    es->MaxTextLen = 65535;
Alexandre Julliard's avatar
Alexandre Julliard committed
	else
Alexandre Julliard's avatar
Alexandre Julliard committed
	    es->MaxTextLen = 32767;
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_LINEFROMCHAR:
	lResult = EDIT_LineFromCharMsg(hwnd, wParam);
	break;

    case EM_LINEINDEX:
	if (IsMultiLine())
	    lResult = EDIT_LineIndexMsg(hwnd, wParam);
	else
	    lResult = 0L;
	break;

    case EM_LINELENGTH:
Alexandre Julliard's avatar
Alexandre Julliard committed
	lResult = EDIT_LineLengthMsg(hwnd, wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_LINESCROLL:
Alexandre Julliard's avatar
Alexandre Julliard committed
	fprintf(stdnimp,"edit: cannot process EM_LINESCROLL message\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_REPLACESEL:
Alexandre Julliard's avatar
Alexandre Julliard committed
	HideCaret(hwnd);
	EDIT_ReplaceSel(hwnd, lParam);
	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
	ShowCaret(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_SETHANDLE:
Alexandre Julliard's avatar
Alexandre Julliard committed
	EDIT_SetHandleMsg(hwnd, wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_SETMODIFY:
	es->TextChanged = wParam;
	break;

    case EM_SETPASSWORDCHAR:
Alexandre Julliard's avatar
Alexandre Julliard committed
	fprintf(stdnimp,"edit: cannot process EM_SETPASSWORDCHAR message\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_SETREADONLY:
Alexandre Julliard's avatar
Alexandre Julliard committed
	fprintf(stdnimp,"edit: cannot process EM_SETREADONLY message\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_SETRECT:
    case EM_SETRECTNP:
Alexandre Julliard's avatar
Alexandre Julliard committed
	fprintf(stdnimp,"edit: cannot process EM_SETRECT(NP) message\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_SETSEL:
	HideCaret(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
	EDIT_SetSelMsg(hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
	ShowCaret(hwnd);
	break;

    case EM_SETTABSTOPS:
Alexandre Julliard's avatar
Alexandre Julliard committed
	lResult = EDIT_SetTabStopsMsg(hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case EM_SETWORDBREAKPROC:
Alexandre Julliard's avatar
Alexandre Julliard committed
	fprintf(stdnimp,"edit: cannot process EM_SETWORDBREAKPROC message\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case EM_UNDO:
	HideCaret(hwnd);
	lResult = EDIT_UndoMsg(hwnd);
	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
	ShowCaret(hwnd);
	break;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case WM_GETDLGCODE:
        return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case WM_CHAR:
	EDIT_CharMsg(hwnd, wParam);
	break;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case WM_COPY:
	EDIT_CopyToClipboard(hwnd);
	EDIT_ClearSel(hwnd);
	break;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case WM_CREATE:
	lResult = EDIT_CreateMsg(hwnd, lParam);
	break;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case WM_CUT:
	EDIT_CopyToClipboard(hwnd);
	EDIT_DeleteSel(hwnd);
	break;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case WM_DESTROY:
Alexandre Julliard's avatar
Alexandre Julliard committed
	EDIT_HeapFree(hwnd, es->hTextPtrs);
	EDIT_HeapFree(hwnd, es->hCharWidths);
	EDIT_HeapFree(hwnd, es->hText);
	EDIT_HeapFree(hwnd, (HANDLE)(*(wndPtr->wExtra)));
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case WM_ENABLE:
	InvalidateRect(hwnd, NULL, FALSE);
	break;

    case WM_GETTEXT:
Alexandre Julliard's avatar
Alexandre Julliard committed
	textPtr = EDIT_HeapAddr(hwnd, es->hText);
Alexandre Julliard's avatar
Alexandre Julliard committed
	if ((int)wParam > (len = strlen(textPtr)))
	{
	    strcpy((char *)lParam, textPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
	    lResult = (DWORD)len ;
Alexandre Julliard's avatar
Alexandre Julliard committed
	}
	else
	    lResult = 0L;
	break;

    case WM_GETTEXTLENGTH:
Alexandre Julliard's avatar
Alexandre Julliard committed
	textPtr = EDIT_HeapAddr(hwnd, es->hText);
Alexandre Julliard's avatar
Alexandre Julliard committed
	lResult = (DWORD)strlen(textPtr);
	break;

    case WM_HSCROLL:
	EDIT_HScrollMsg(hwnd, wParam, lParam);
	break;

    case WM_KEYDOWN:
	EDIT_KeyDownMsg(hwnd, wParam);
	break;

    case WM_KILLFOCUS:
	DestroyCaret();
	NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
	break;

    case WM_LBUTTONDOWN:
	HideCaret(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
	SetFocus(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
	EDIT_LButtonDownMsg(hwnd, wParam, lParam);
	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
	ShowCaret(hwnd);
	break;

    case WM_LBUTTONUP:
	ButtonDown = FALSE;
	if (TextMarking)
	    EDIT_StopMarking(hwnd);
	break;

    case WM_MOUSEMOVE:
	HideCaret(hwnd);
	EDIT_MouseMoveMsg(hwnd, wParam, lParam);
	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
	ShowCaret(hwnd);
	break;

    case WM_MOVE:
	lResult = 0;
	break;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case WM_NCCREATE:
	lResult = EDIT_NCCreateMsg(hwnd, lParam);
	break;
	
Alexandre Julliard's avatar
Alexandre Julliard committed
    case WM_PAINT:
	EDIT_PaintMsg(hwnd);
	break;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case WM_PASTE:
	EDIT_PasteMsg(hwnd);
	break;

Alexandre Julliard's avatar
Alexandre Julliard committed
    case WM_SETFOCUS:
	CreateCaret(hwnd, 0, 2, es->txtht);
	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
	ShowCaret(hwnd);
	NOTIFY_PARENT(hwnd, EN_SETFOCUS);
	break;

    case WM_SETFONT:
Alexandre Julliard's avatar
Alexandre Julliard committed
	HideCaret(hwnd);
	EDIT_SetFont(hwnd, wParam, lParam);
	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
	ShowCaret(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
	break;

    case WM_SETTEXT:
	EDIT_SetTextMsg(hwnd, lParam);
	break;

    case WM_SIZE:
	EDIT_SizeMsg(hwnd, wParam, lParam);
	lResult = 0;
	break;

    case WM_VSCROLL:
	EDIT_VScrollMsg(hwnd, wParam, lParam);
	break;

    default:
	lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
	break;
    }

    return lResult;
}


/*********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
 *  WM_NCCREATE message function
Alexandre Julliard's avatar
Alexandre Julliard committed
long EDIT_NCCreateMsg(HWND hwnd, LONG lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
{
Alexandre Julliard's avatar
Alexandre Julliard committed
    CREATESTRUCT *createStruct = (CREATESTRUCT *)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
    WND *wndPtr = WIN_FindWndPtr(hwnd);
    EDITSTATE *es;
    unsigned int *textPtrs;
Alexandre Julliard's avatar
Alexandre Julliard committed
    char *text;
Alexandre Julliard's avatar
Alexandre Julliard committed

Alexandre Julliard's avatar
Alexandre Julliard committed
    /* store pointer to local or global heap in window structure so that */
Alexandre Julliard's avatar
Alexandre Julliard committed
    /* EDITSTATE structure itself can be stored on local heap  */
Alexandre Julliard's avatar
Alexandre Julliard committed
    if (HEAP_LocalFindHeap(createStruct->hInstance)!=NULL)
      (MDESC **)*(LONG *)(wndPtr->wExtra + 2) = 
Alexandre Julliard's avatar
Alexandre Julliard committed
	&HEAP_LocalFindHeap(createStruct->hInstance)->free_list;
Alexandre Julliard's avatar
Alexandre Julliard committed
    else
      {
	(MDESC **)*(LONG *)(wndPtr->wExtra + 2) =
	  GlobalLock(createStruct->hInstance);
	/* GlobalUnlock(createStruct->hInstance); */
      }
Alexandre Julliard's avatar
Alexandre Julliard committed
    /* allocate space for state variable structure */
Alexandre Julliard's avatar
Alexandre Julliard committed
    (HANDLE)(*(wndPtr->wExtra)) = EDIT_HeapAlloc(hwnd, sizeof(EDITSTATE));
    es = (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
    es->hTextPtrs = EDIT_HeapAlloc(hwnd, sizeof(int));
    textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
    es->hCharWidths = EDIT_HeapAlloc(hwnd, 256 * sizeof(short));
Alexandre Julliard's avatar
Alexandre Julliard committed

    /* --- text buffer */
    es->MaxTextLen = MAXTEXTLEN + 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
    if (!(createStruct->lpszName))
Alexandre Julliard's avatar
Alexandre Julliard committed
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
	es->textlen = EditBufLen(wndPtr) + 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
	es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
	text = EDIT_HeapAddr(hwnd, es->hText);
Alexandre Julliard's avatar
Alexandre Julliard committed
	memset(text, 0, es->textlen + 2);
	EDIT_ClearTextPointers(hwnd);
    }
    else
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (strlen(createStruct->lpszName) < EditBufLen(wndPtr))
	{
Alexandre Julliard's avatar
Alexandre Julliard committed
	    es->textlen = EditBufLen(wndPtr) + 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
	    es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
	    text = EDIT_HeapAddr(hwnd, es->hText);
Alexandre Julliard's avatar
Alexandre Julliard committed
	    strcpy(text, createStruct->lpszName);
Alexandre Julliard's avatar
Alexandre Julliard committed
	    *(text + es->textlen) = '\0';
	}
	else
	{
Alexandre Julliard's avatar
Alexandre Julliard committed
	    es->hText = EDIT_HeapAlloc(hwnd, 
				       strlen(createStruct->lpszName) + 2);
	    text = EDIT_HeapAddr(hwnd, es->hText);
Alexandre Julliard's avatar
Alexandre Julliard committed
	    strcpy(text, createStruct->lpszName);
Alexandre Julliard's avatar
Alexandre Julliard committed
	    es->textlen = strlen(createStruct->lpszName) + 1;
	}
	*(text + es->textlen + 1) = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
	EDIT_BuildTextPointers(hwnd);
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
    if ((createStruct->style & WS_VSCROLL) || 
	(createStruct->style & WS_HSCROLL)) NC_CreateScrollBars(hwnd);

Alexandre Julliard's avatar
Alexandre Julliard committed
    /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
    /* the corresponding WM_* message is set                          */
    if (createStruct->style & WS_VSCROLL)
	wndPtr->dwStyle |= ES_AUTOVSCROLL;
    if (createStruct->style & WS_HSCROLL)
	wndPtr->dwStyle |= ES_AUTOHSCROLL;

Alexandre Julliard's avatar
Alexandre Julliard committed
    /* 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 message function
 */

long EDIT_CreateMsg(HWND hwnd, LONG lParam)
{
    HDC hdc;
    WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
    EDITSTATE *es = 
	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
Alexandre Julliard's avatar
Alexandre Julliard committed
    CLASS *classPtr;
    short *charWidths;
    TEXTMETRIC tm;
    char *text;

    /* initialize state variable structure */
    /* --- char width array */
    hdc = GetDC(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
    charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
Alexandre Julliard's avatar
Alexandre Julliard committed
    memset(charWidths, 0, 256 * sizeof(short));
    GetCharWidth(hdc, 0, 255, charWidths);

Alexandre Julliard's avatar
Alexandre Julliard committed
    /* --- other structure variables */
    GetTextMetrics(hdc, &tm);
    es->txtht = tm.tmHeight + tm.tmExternalLeading;
    es->wlines = 0;
    es->wtop = es->wleft = 0;
    es->CurrCol = es->CurrLine = 0;
    es->WndCol = es->WndRow = 0;
    es->TextChanged = FALSE;
    es->textwidth = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
    es->SelBegLine = es->SelBegCol = 0;
    es->SelEndLine = es->SelEndCol = 0;
    es->hFont = 0;
    es->hDeletedText = 0;
    es->DeletedLength = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
    es->NumTabStops = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
    es->hTabStops = EDIT_HeapAlloc(hwnd, sizeof(int));
Alexandre Julliard's avatar
Alexandre Julliard committed

    /* allocate space for a line full of blanks to speed up */
    /* line filling */
Alexandre Julliard's avatar
Alexandre Julliard committed
    es->hBlankLine = EDIT_HeapAlloc(hwnd, (ClientWidth(wndPtr) / 
Alexandre Julliard's avatar
Alexandre Julliard committed
				      charWidths[32]) + 2); 
Alexandre Julliard's avatar
Alexandre Julliard committed
    text = EDIT_HeapAddr(hwnd, es->hBlankLine);
Alexandre Julliard's avatar
Alexandre Julliard committed
    memset(text, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);

    /* set up text cursor for edit class */
Alexandre Julliard's avatar
Alexandre Julliard committed
    CLASS_FindClassByName("EDIT", 0, &classPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
    classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM);

    /* paint background on first WM_PAINT */
    es->PaintBkgd = TRUE;

    ReleaseDC(hwnd, hdc);
    return 0L;
}


/*********************************************************************
 *  EDIT_ClearTextPointers
 *
 *  Clear and initialize text line pointer array.
 */

void EDIT_ClearTextPointers(HWND hwnd)
{
    unsigned int *textPtrs;
    WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
    EDITSTATE *es = 
	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
Alexandre Julliard's avatar
Alexandre Julliard committed
    
Alexandre Julliard's avatar
Alexandre Julliard committed
    es->hTextPtrs = EDIT_HeapReAlloc(hwnd, es->hTextPtrs, sizeof(int));
    textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
Alexandre Julliard's avatar
Alexandre Julliard committed
    *textPtrs = 0;
}


/*********************************************************************
 *  EDIT_BuildTextPointers
 *
 *  Build array of pointers to text lines.
 */

#define INITLINES 100

void EDIT_BuildTextPointers(HWND hwnd)
{
    WND *wndPtr = WIN_FindWndPtr(hwnd);
    char *text, *cp;
    int incrs = INITLINES;
Alexandre Julliard's avatar
Alexandre Julliard committed
    unsigned int off, len;
Alexandre Julliard's avatar
Alexandre Julliard committed
    EDITSTATE *es;
    unsigned int *textPtrs;
    short *charWidths;

Alexandre Julliard's avatar
Alexandre Julliard committed
    es = (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
    text = EDIT_HeapAddr(hwnd, es->hText);
    textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
    charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
Alexandre Julliard's avatar
Alexandre Julliard committed

    es->textwidth = es->wlines = 0;
    cp = text;

    /* advance through text buffer */
    while (*cp)
    {
	/* increase size of text pointer array */ 
	if (incrs == INITLINES)
	{
	    incrs = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
	    es->hTextPtrs = EDIT_HeapReAlloc(hwnd, es->hTextPtrs,
Alexandre Julliard's avatar
Alexandre Julliard committed
			      (es->wlines + INITLINES) * sizeof(int));
Alexandre Julliard's avatar
Alexandre Julliard committed
	    textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
Alexandre Julliard's avatar
Alexandre Julliard committed
	}
	off = (unsigned int)(cp - text);     /* offset of beginning of line */
	*(textPtrs + es->wlines) = off;
	es->wlines++;
	incrs++;
	len = 0;
	
	/* advance through current line */
	while (*cp && *cp != '\n')
	{
Alexandre Julliard's avatar
Alexandre Julliard committed
	    len += EDIT_CharWidth(hwnd, (BYTE)*cp, len);
Alexandre Julliard's avatar
Alexandre Julliard committed
	                                     /* width of line in pixels */
Alexandre Julliard's avatar
Alexandre Julliard committed
	    cp++;
	}
	es->textwidth = max(es->textwidth, len);
	if (*cp)
	    cp++;                            /* skip '\n' */
    }
Alexandre Julliard's avatar
Alexandre Julliard committed

    off = (unsigned int)(cp - text);
Alexandre Julliard's avatar
Alexandre Julliard committed
    *(textPtrs + es->wlines) = off;
}


/*********************************************************************
 *  EDIT_ModTextPointers
 *
 *  Modify text pointers from a specified position.
 */

void EDIT_ModTextPointers(HWND hwnd, int lineno, int var)
{
    WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
    EDITSTATE *es = 
	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
    unsigned int *textPtrs = 
	(unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
Alexandre Julliard's avatar
Alexandre Julliard committed

    while (lineno < es->wlines)
	*(textPtrs + lineno++) += var;
}


/*********************************************************************
 *  WM_PAINT message function
 */

void EDIT_PaintMsg(HWND hwnd)
{
    PAINTSTRUCT ps;
    HDC hdc;
    int y;
    RECT rc;
    WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
    EDITSTATE *es = 
	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
Alexandre Julliard's avatar
Alexandre Julliard committed

    hdc = BeginPaint(hwnd, &ps);
    rc = ps.rcPaint;

Alexandre Julliard's avatar
Alexandre Julliard committed
    dprintf_edit(stddeb,"WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc.left, rc.top, 
Alexandre Julliard's avatar
Alexandre Julliard committed
	   rc.right, rc.bottom);

    if (es->PaintBkgd)
	FillWindow(GetParent(hwnd), hwnd, hdc, CTLCOLOR_EDIT);

    for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
    {
	if (y < es->wlines - es->wtop)
	    EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
    }

    EndPaint(hwnd, &ps);
}


/*********************************************************************
 *  EDIT_GetTextLine
 *
 *  Get a copy of the text in the specified line.
 */

HANDLE EDIT_GetTextLine(HWND hwnd, int selection)
{
    char *line;
    HANDLE hLine;
    int len = 0;
    char *cp, *cp1;

Alexandre Julliard's avatar
Alexandre Julliard committed
    dprintf_edit(stddeb,"GetTextLine %d\n", selection);
Alexandre Julliard's avatar
Alexandre Julliard committed
    cp = cp1 = EDIT_TextLine(hwnd, selection);
    /* advance through line */
    while (*cp && *cp != '\n')
    {
	len++;
	cp++;
    }

    /* store selected line and return handle */
Alexandre Julliard's avatar
Alexandre Julliard committed
    hLine = EDIT_HeapAlloc(hwnd, len + 6);
    line = (char *)EDIT_HeapAddr(hwnd, hLine);
Alexandre Julliard's avatar
Alexandre Julliard committed
    memmove(line, cp1, len);
    line[len] = '\0';
    return hLine;
}


/*********************************************************************
 *  EDIT_TextLine
 *
 *  Return a pointer to the text in the specified line.
 */

char *EDIT_TextLine(HWND hwnd, int sel)
{
    WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
    EDITSTATE *es = 
	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
    char *text = EDIT_HeapAddr(hwnd, es->hText);
    unsigned int *textPtrs = 
	(unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
Alexandre Julliard's avatar
Alexandre Julliard committed

Alexandre Julliard's avatar
Alexandre Julliard committed
    if(sel>es->wlines)return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
    return (text + *(textPtrs + sel));
}
    

/*********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
 *  EDIT_StrLength
Alexandre Julliard's avatar
Alexandre Julliard committed
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
 *  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.
Alexandre Julliard's avatar
Alexandre Julliard committed
int EDIT_StrLength(HWND hwnd, unsigned char *str, int len, int pcol)
Alexandre Julliard's avatar
Alexandre Julliard committed
{
    int i, plen = 0;

    for (i = 0; i < len; i++)
Alexandre Julliard's avatar
Alexandre Julliard committed
	plen += EDIT_CharWidth(hwnd, (BYTE)(*(str + i)), pcol + plen);
Alexandre Julliard's avatar
Alexandre Julliard committed

Alexandre Julliard's avatar
Alexandre Julliard committed
    dprintf_edit(stddeb,"EDIT_StrLength: returning %d\n", plen);
Alexandre Julliard's avatar
Alexandre Julliard committed
    return plen;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
/*********************************************************************
 *  EDIT_LineLength
 *
 *  Return length of line _num_ in characters.
 */

int EDIT_LineLength(HWND hwnd, int num)
{
    char *cp = EDIT_TextLine(hwnd, num);
    char *cp1;

Alexandre Julliard's avatar
Alexandre Julliard committed
    if(!cp)return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
    cp1 = strchr(cp, '\n');
    return cp1 ? (int)(cp1 - cp) : strlen(cp);
}


Alexandre Julliard's avatar
Alexandre Julliard committed
/*********************************************************************
 *  EDIT_WriteTextLine
 *
 *  Write the line of text at offset _y_ in text buffer to a window.
 */

void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
{
    int len = 0;
    HANDLE hLine;
    unsigned char *lp;
    int lnlen, lnlen1;
    int col, off = 0;
    int sbl, sel, sbc, sec;
    RECT rc;
    WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
    EDITSTATE *es = 
	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
Alexandre Julliard's avatar
Alexandre Julliard committed

    /* initialize rectangle if NULL, else copy */
    if (rect)
	CopyRect(&rc, rect);
    else
	GetClientRect(hwnd, &rc);

Alexandre Julliard's avatar
Alexandre Julliard committed
    dprintf_edit(stddeb,"WriteTextLine %d\n", y);
Alexandre Julliard's avatar
Alexandre Julliard committed

    /* make sure y is inside the window */
    if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
	dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is not a displayed line\n", y);
Alexandre Julliard's avatar
Alexandre Julliard committed
	return;
    }

    /* make sure rectangle is within window */
    if (rc.left >= ClientWidth(wndPtr) - 1)
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
	dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
	       rc.left);
	return;
    }
    if (rc.right <= 0)
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
	dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
	       rc.right);
	return;
    }
    if (y - es->wtop < (rc.top / es->txtht) || 
	y - es->wtop > (rc.bottom / es->txtht))
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
	dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is outside window\n", y);
Alexandre Julliard's avatar
Alexandre Julliard committed
	return;
    }

    /* get the text and length of line */
    if ((hLine = EDIT_GetTextLine(hwnd, y)) == 0)
	return;
Alexandre Julliard's avatar
Alexandre Julliard committed
    lp = (unsigned char *)EDIT_HeapAddr(hwnd, hLine);
    lnlen = EDIT_StrLength(hwnd, lp, strlen(lp), 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
    lnlen1 = lnlen;

    /* build the line to display */
    if (lnlen < es->wleft)
	lnlen = 0;
    else
	off += es->wleft;

    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(&sbl, &sel);
	    swap(&sbc, &sec);
	}
	if (sbl == sel && sbc > sec)
	    swap(&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)
	{
Alexandre Julliard's avatar
Alexandre Julliard committed
	    col = EDIT_StrLength(hwnd, lp, sbc, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
	    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)
	    {
Alexandre Julliard's avatar
Alexandre Julliard committed
		col = EDIT_StrLength(hwnd, lp, sec, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
		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)
	{
Alexandre Julliard's avatar
Alexandre Julliard committed
	    col = EDIT_StrLength(hwnd, lp, sec, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
	    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);
	      
Alexandre Julliard's avatar
Alexandre Julliard committed
    EDIT_HeapFree(hwnd, hLine);
Alexandre Julliard's avatar
Alexandre Julliard committed
}


/*********************************************************************
 *  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?
 */

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;
Alexandre Julliard's avatar
Alexandre Julliard committed
    char *str, *cp, *cp1;
    int diff, num_spaces, tabwidth, scol;
Alexandre Julliard's avatar
Alexandre Julliard committed
    HRGN hrgnClip;
    COLORREF oldTextColor, oldBkgdColor;
Alexandre Julliard's avatar
Alexandre Julliard committed
    HFONT oldfont;
Alexandre Julliard's avatar
Alexandre Julliard committed
    WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
    EDITSTATE *es = 
	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
    short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
    char *blanks = (char *)EDIT_HeapAddr(hwnd, es->hBlankLine);