reactos/rosapps/dflat32/editbox.c

1114 lines
33 KiB
C
Raw Normal View History

/* ------------- editbox.c ------------ */
#include "dflat.h"
#define EditBufLen(wnd) (isMultiLine(wnd) ? EDITLEN : ENTRYLEN)
#define SetLinePointer(wnd, ln) (wnd->CurrLine = ln)
#define isWhite(c) ((c)==' '||(c)=='\n')
/* ---------- local prototypes ----------- */
static void SaveDeletedText(DFWINDOW, char *, int);
static void Forward(DFWINDOW);
static void Backward(DFWINDOW);
static void End(DFWINDOW);
static void Home(DFWINDOW);
static void Downward(DFWINDOW);
static void Upward(DFWINDOW);
static void StickEnd(DFWINDOW);
static void NextWord(DFWINDOW);
static void PrevWord(DFWINDOW);
static void ModTextPointers(DFWINDOW, int, int);
static void SetAnchor(DFWINDOW, int, int);
/* -------- local variables -------- */
static BOOL KeyBoardMarking, ButtonDown;
static BOOL TextMarking;
static int ButtonX, ButtonY;
static int PrevY = -1;
/* ----------- CREATE_WINDOW Message ---------- */
static int CreateWindowMsg(DFWINDOW wnd)
{
int rtn = BaseWndProc(EDITBOX, wnd, CREATE_WINDOW, 0, 0);
wnd->MaxTextLength = MAXTEXTLEN+1;
wnd->textlen = EditBufLen(wnd);
wnd->InsertMode = TRUE;
DfSendMessage(wnd, CLEARTEXT, 0, 0);
return rtn;
}
/* ----------- SETTEXT Message ---------- */
static int SetTextMsg(DFWINDOW wnd, PARAM p1)
{
int rtn = FALSE;
if (strlen((char *)p1) <= wnd->MaxTextLength)
rtn = BaseWndProc(EDITBOX, wnd, SETTEXT, p1, 0);
return rtn;
}
/* ----------- CLEARTEXT Message ------------ */
static int ClearTextMsg(DFWINDOW wnd)
{
int rtn = BaseWndProc(EDITBOX, wnd, CLEARTEXT, 0, 0);
unsigned blen = EditBufLen(wnd)+2;
wnd->text = DFrealloc(wnd->text, blen);
memset(wnd->text, 0, blen);
wnd->wlines = 0;
wnd->CurrLine = 0;
wnd->CurrCol = 0;
wnd->WndRow = 0;
wnd->wleft = 0;
wnd->wtop = 0;
wnd->textwidth = 0;
wnd->TextChanged = FALSE;
return rtn;
}
/* ----------- ADDTEXT Message ---------- */
static int AddTextMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
int rtn = FALSE;
if (strlen((char *)p1)+wnd->textlen <= wnd->MaxTextLength) {
rtn = BaseWndProc(EDITBOX, wnd, ADDTEXT, p1, p2);
if (rtn != FALSE) {
if (!isMultiLine(wnd)) {
wnd->CurrLine = 0;
wnd->CurrCol = strlen((char *)p1);
if (wnd->CurrCol >= ClientWidth(wnd)) {
wnd->wleft = wnd->CurrCol-ClientWidth(wnd);
wnd->CurrCol -= wnd->wleft;
}
wnd->BlkEndCol = wnd->CurrCol;
DfSendMessage(wnd, KEYBOARD_CURSOR,
WndCol, wnd->WndRow);
}
}
}
return rtn;
}
/* ----------- GETTEXT Message ---------- */
static int GetTextMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
char *cp1 = (char *)p1;
char *cp2 = wnd->text;
if (cp2 != NULL) {
while (p2-- && *cp2 && *cp2 != '\n')
*cp1++ = *cp2++;
*cp1 = '\0';
return TRUE;
}
return FALSE;
}
/* ----------- SETTEXTLENGTH Message ---------- */
static int SetTextLengthMsg(DFWINDOW wnd, unsigned int len)
{
if (++len < MAXTEXTLEN) {
wnd->MaxTextLength = len;
if (len < wnd->textlen) {
wnd->text=DFrealloc(wnd->text, len+2);
wnd->textlen = len;
*((wnd->text)+len) = '\0';
*((wnd->text)+len+1) = '\0';
BuildTextPointers(wnd);
}
return TRUE;
}
return FALSE;
}
/* ----------- KEYBOARD_CURSOR Message ---------- */
static void KeyboardCursorMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
wnd->CurrCol = (int)p1 + wnd->wleft;
wnd->WndRow = (int)p2;
wnd->CurrLine = (int)p2 + wnd->wtop;
if (wnd == inFocus) {
if (CharInView(wnd, (int)p1, (int)p2))
DfSendMessage(NULL, SHOW_CURSOR,
(wnd->InsertMode && !TextMarking), 0);
else
DfSendMessage(NULL, HIDE_CURSOR, 0, 0);
}
}
/* ----------- SIZE Message ---------- */
int SizeMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
int rtn = BaseWndProc(EDITBOX, wnd, DFM_SIZE, p1, p2);
if (WndCol > ClientWidth(wnd)-1)
wnd->CurrCol = ClientWidth(wnd)-1 + wnd->wleft;
if (wnd->WndRow > ClientHeight(wnd)-1) {
wnd->WndRow = ClientHeight(wnd)-1;
SetLinePointer(wnd, wnd->WndRow+wnd->wtop);
}
DfSendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
return rtn;
}
/* ----------- SCROLL Message ---------- */
static int ScrollMsg(DFWINDOW wnd, PARAM p1)
{
int rtn = FALSE;
if (isMultiLine(wnd)) {
rtn = BaseWndProc(EDITBOX,wnd,SCROLL,p1,0);
if (rtn != FALSE) {
if (p1) {
/* -------- scrolling up --------- */
if (wnd->WndRow == 0) {
wnd->CurrLine++;
StickEnd(wnd);
}
else
--wnd->WndRow;
}
else {
/* -------- scrolling down --------- */
if (wnd->WndRow == ClientHeight(wnd)-1) {
if (wnd->CurrLine > 0)
--wnd->CurrLine;
StickEnd(wnd);
}
else
wnd->WndRow++;
}
DfSendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
}
}
return rtn;
}
/* ----------- HORIZSCROLL Message ---------- */
static int HorizScrollMsg(DFWINDOW wnd, PARAM p1)
{
int rtn = FALSE;
char *currchar = CurrChar;
if (!(p1 &&
wnd->CurrCol == wnd->wleft && *currchar == '\n')) {
rtn = BaseWndProc(EDITBOX, wnd, HORIZSCROLL, p1, 0);
if (rtn != FALSE) {
if (wnd->CurrCol < wnd->wleft)
wnd->CurrCol++;
else if (WndCol == ClientWidth(wnd))
--wnd->CurrCol;
DfSendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
}
}
return rtn;
}
/* ----------- SCROLLPAGE Message ---------- */
static int ScrollPageMsg(DFWINDOW wnd, PARAM p1)
{
int rtn = FALSE;
if (isMultiLine(wnd)) {
rtn = BaseWndProc(EDITBOX, wnd, SCROLLPAGE, p1, 0);
SetLinePointer(wnd, wnd->wtop+wnd->WndRow);
StickEnd(wnd);
DfSendMessage(wnd, KEYBOARD_CURSOR,WndCol, wnd->WndRow);
}
return rtn;
}
/* ----------- HORIZSCROLLPAGE Message ---------- */
static int HorizPageMsg(DFWINDOW wnd, PARAM p1)
{
int rtn = BaseWndProc(EDITBOX, wnd, HORIZPAGE, p1, 0);
if ((int) p1 == FALSE) {
if (wnd->CurrCol > wnd->wleft+ClientWidth(wnd)-1)
wnd->CurrCol = wnd->wleft+ClientWidth(wnd)-1;
}
else if (wnd->CurrCol < wnd->wleft)
wnd->CurrCol = wnd->wleft;
DfSendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
return rtn;
}
/* ----- Extend the marked block to the new x,y position ---- */
static void ExtendBlock(DFWINDOW wnd, int x, int y)
{
int bbl, bel;
int ptop = min(wnd->BlkBegLine, wnd->BlkEndLine);
int pbot = max(wnd->BlkBegLine, wnd->BlkEndLine);
char *lp = TextLine(wnd, wnd->wtop+y);
int len = (int) (strchr(lp, '\n') - lp);
x = max(0, min(x, len));
y = max(0, y);
wnd->BlkEndCol = min(len, x+wnd->wleft);
wnd->BlkEndLine = y+wnd->wtop;
DfSendMessage(wnd, KEYBOARD_CURSOR, wnd->BlkEndCol, wnd->BlkEndLine);
bbl = min(wnd->BlkBegLine, wnd->BlkEndLine);
bel = max(wnd->BlkBegLine, wnd->BlkEndLine);
while (ptop < bbl) {
WriteTextLine(wnd, NULL, ptop, FALSE);
ptop++;
}
for (y = bbl; y <= bel; y++)
WriteTextLine(wnd, NULL, y, FALSE);
while (pbot > bel) {
WriteTextLine(wnd, NULL, pbot, FALSE);
--pbot;
}
}
/* ----------- LEFT_BUTTON Message ---------- */
static int LeftButtonMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
int MouseX = (int) p1 - GetClientLeft(wnd);
int MouseY = (int) p2 - GetClientTop(wnd);
DFRECT rc = ClientRect(wnd);
char *lp;
int len;
if (KeyBoardMarking)
return TRUE;
if (WindowMoving || WindowSizing)
return FALSE;
if (isMultiLine(wnd)) {
if (TextMarking) {
if (!InsideRect(p1, p2, rc)) {
int x = MouseX, y = MouseY;
int dir;
DFMESSAGE msg = 0;
if ((int)p2 == GetTop(wnd))
y++, dir = FALSE, msg = SCROLL;
else if ((int)p2 == GetBottom(wnd))
--y, dir = TRUE, msg = SCROLL;
else if ((int)p1 == GetLeft(wnd))
--x, dir = FALSE, msg = HORIZSCROLL;
else if ((int)p1 == GetRight(wnd))
x++, dir = TRUE, msg = HORIZSCROLL;
if (msg != 0) {
if (DfSendMessage(wnd, msg, dir, 0))
ExtendBlock(wnd, x, y);
DfSendMessage(wnd, PAINT, 0, 0);
}
}
return TRUE;
}
if (!InsideRect(p1, p2, rc))
return FALSE;
if (TextBlockMarked(wnd)) {
ClearTextBlock(wnd);
DfSendMessage(wnd, PAINT, 0, 0);
}
if (wnd->wlines) {
if (MouseY > wnd->wlines-1)
return TRUE;
lp = TextLine(wnd, MouseY+wnd->wtop);
len = (int) (strchr(lp, '\n') - lp);
MouseX = min(MouseX, len);
if (MouseX < wnd->wleft) {
MouseX = 0;
DfSendMessage(wnd, KEYBOARD, HOME, 0);
}
ButtonDown = TRUE;
ButtonX = MouseX;
ButtonY = MouseY;
}
else
MouseX = MouseY = 0;
wnd->WndRow = MouseY;
SetLinePointer(wnd, MouseY+wnd->wtop);
}
if (isMultiLine(wnd) ||
(!TextBlockMarked(wnd)
&& (int)(MouseX+wnd->wleft) < (int)strlen(wnd->text)))
wnd->CurrCol = MouseX+wnd->wleft;
DfSendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
return TRUE;
}
/* ----------- MOUSE_MOVED Message ---------- */
static int MouseMovedMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
int MouseX = (int) p1 - GetClientLeft(wnd);
int MouseY = (int) p2 - GetClientTop(wnd);
DFRECT rc = ClientRect(wnd);
if (!InsideRect(p1, p2, rc))
return FALSE;
if (MouseY > wnd->wlines-1)
return FALSE;
if (ButtonDown) {
SetAnchor(wnd, ButtonX+wnd->wleft, ButtonY+wnd->wtop);
TextMarking = TRUE;
rc = WindowRect(wnd);
DfSendMessage(NULL,MOUSE_TRAVEL,(PARAM) &rc, 0);
ButtonDown = FALSE;
}
if (TextMarking && !(WindowMoving || WindowSizing)) {
ExtendBlock(wnd, MouseX, MouseY);
return TRUE;
}
return FALSE;
}
static void StopMarking(DFWINDOW wnd)
{
TextMarking = FALSE;
if (wnd->BlkBegLine > wnd->BlkEndLine) {
swap(wnd->BlkBegLine, wnd->BlkEndLine);
swap(wnd->BlkBegCol, wnd->BlkEndCol);
}
if (wnd->BlkBegLine == wnd->BlkEndLine &&
wnd->BlkBegCol > wnd->BlkEndCol)
swap(wnd->BlkBegCol, wnd->BlkEndCol);
}
/* ----------- BUTTON_RELEASED Message ---------- */
static int ButtonReleasedMsg(DFWINDOW wnd)
{
if (isMultiLine(wnd)) {
ButtonDown = FALSE;
if (TextMarking && !(WindowMoving || WindowSizing)) {
/* release the mouse ouside the edit box */
DfSendMessage(NULL, MOUSE_TRAVEL, 0, 0);
StopMarking(wnd);
return TRUE;
}
else
PrevY = -1;
}
return FALSE;
}
/* ---- Process text block keys for multiline text box ---- */
static void DoMultiLines(DFWINDOW wnd, int c, PARAM p2)
{
if (isMultiLine(wnd) && !KeyBoardMarking) {
if ((int)p2 & (LEFTSHIFT | RIGHTSHIFT)) {
switch (c) {
case HOME:
case CTRL_HOME:
case CTRL_BS:
case PGUP:
case CTRL_PGUP:
case UP:
case BS:
case END:
case CTRL_END:
case PGDN:
case CTRL_PGDN:
case DN:
case FWD:
case CTRL_FWD:
KeyBoardMarking = TextMarking = TRUE;
SetAnchor(wnd, wnd->CurrCol, wnd->CurrLine);
break;
default:
break;
}
}
}
}
/* ---------- page/scroll keys ----------- */
static int DoScrolling(DFWINDOW wnd, int c, PARAM p2)
{
switch (c) {
case PGUP:
case PGDN:
if (isMultiLine(wnd))
BaseWndProc(EDITBOX, wnd, KEYBOARD, c, p2);
break;
case CTRL_PGUP:
case CTRL_PGDN:
BaseWndProc(EDITBOX, wnd, KEYBOARD, c, p2);
break;
case HOME:
Home(wnd);
break;
case END:
End(wnd);
break;
case CTRL_FWD:
NextWord(wnd);
break;
case CTRL_BS:
PrevWord(wnd);
break;
case CTRL_HOME:
if (isMultiLine(wnd)) {
DfSendMessage(wnd, SCROLLDOC, TRUE, 0);
wnd->CurrLine = 0;
wnd->WndRow = 0;
}
Home(wnd);
break;
case CTRL_END:
if (isMultiLine(wnd) &&
wnd->WndRow+wnd->wtop+1 < wnd->wlines
&& wnd->wlines > 0) {
DfSendMessage(wnd, SCROLLDOC, FALSE, 0);
SetLinePointer(wnd, wnd->wlines-1);
wnd->WndRow =
min(ClientHeight(wnd)-1, wnd->wlines-1);
Home(wnd);
}
End(wnd);
break;
case UP:
if (isMultiLine(wnd))
Upward(wnd);
break;
case DN:
if (isMultiLine(wnd))
Downward(wnd);
break;
case FWD:
Forward(wnd);
break;
case BS:
Backward(wnd);
break;
default:
return FALSE;
}
if (!KeyBoardMarking && TextBlockMarked(wnd)) {
ClearTextBlock(wnd);
DfSendMessage(wnd, PAINT, 0, 0);
}
DfSendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
return TRUE;
}
/* -------------- Del key ---------------- */
static void DelKey(DFWINDOW wnd)
{
char *currchar = CurrChar;
int repaint = *currchar == '\n';
if (TextBlockMarked(wnd)) {
DfSendMessage(wnd, DFM_COMMAND, ID_DELETETEXT, 0);
DfSendMessage(wnd, PAINT, 0, 0);
return;
}
if (isMultiLine(wnd) && *currchar == '\n' && *(currchar+1) == '\0')
return;
strcpy(currchar, currchar+1);
if (repaint) {
BuildTextPointers(wnd);
DfSendMessage(wnd, PAINT, 0, 0);
}
else {
ModTextPointers(wnd, wnd->CurrLine+1, -1);
WriteTextLine(wnd, NULL, wnd->WndRow+wnd->wtop, FALSE);
}
wnd->TextChanged = TRUE;
}
/* ------------ Tab key ------------ */
static void TabKey(DFWINDOW wnd, PARAM p2)
{
if (isMultiLine(wnd)) {
int insmd = wnd->InsertMode;
do {
char *cc = CurrChar+1;
if (!insmd && *cc == '\0')
break;
if (wnd->textlen == wnd->MaxTextLength)
break;
DfSendMessage(wnd,KEYBOARD,insmd ? ' ' : FWD,0);
} while (wnd->CurrCol % cfg.Tabs);
}
else
DfPostMessage(GetParent(wnd), KEYBOARD, '\t', p2);
}
/* ------------ Shift+Tab key ------------ */
static void ShiftTabKey(DFWINDOW wnd, PARAM p2)
{
if (isMultiLine(wnd)) {
do {
if (CurrChar == GetText(wnd))
break;
DfSendMessage(wnd,KEYBOARD,BS,0);
} while (wnd->CurrCol % cfg.Tabs);
}
else
DfPostMessage(GetParent(wnd), KEYBOARD, SHIFT_HT, p2);
}
/* --------- All displayable typed keys ------------- */
static void KeyTyped(DFWINDOW wnd, int c)
{
char *currchar = CurrChar;
if ((c != '\n' && c < ' ') || (c & 0x1000))
/* ---- not recognized by editor --- */
return;
if (!isMultiLine(wnd) && TextBlockMarked(wnd)) {
DfSendMessage(wnd, CLEARTEXT, 0, 0);
currchar = CurrChar;
}
/* ---- test typing at end of text ---- */
if (currchar == wnd->text+wnd->MaxTextLength) {
/* ---- typing at the end of maximum buffer ---- */
beep();
return;
}
if (*currchar == '\0') {
/* --- insert a newline at end of text --- */
*currchar = '\n';
*(currchar+1) = '\0';
BuildTextPointers(wnd);
}
/* --- displayable char or newline --- */
if (c == '\n' || wnd->InsertMode || *currchar == '\n') {
/* ------ inserting the keyed character ------ */
if (wnd->text[wnd->textlen-1] != '\0') {
/* --- the current text buffer is full --- */
if (wnd->textlen == wnd->MaxTextLength) {
/* --- text buffer is at maximum size --- */
beep();
return;
}
/* ---- increase the text buffer size ---- */
wnd->textlen += GROWLENGTH;
/* --- but not above maximum size --- */
if (wnd->textlen > wnd->MaxTextLength)
wnd->textlen = wnd->MaxTextLength;
wnd->text = DFrealloc(wnd->text, wnd->textlen+2);
wnd->text[wnd->textlen-1] = '\0';
currchar = CurrChar;
}
memmove(currchar+1, currchar, strlen(currchar)+1);
ModTextPointers(wnd, wnd->CurrLine+1, 1);
if (isMultiLine(wnd) && wnd->wlines > 1)
wnd->textwidth = max(wnd->textwidth,
(int) (TextLine(wnd, wnd->CurrLine+1)-
TextLine(wnd, wnd->CurrLine)));
else
wnd->textwidth = max((int)wnd->textwidth,
(int)strlen(wnd->text));
WriteTextLine(wnd, NULL,
wnd->wtop+wnd->WndRow, FALSE);
}
/* ----- put the char in the buffer ----- */
*currchar = c;
wnd->TextChanged = TRUE;
if (c == '\n') {
wnd->wleft = 0;
BuildTextPointers(wnd);
End(wnd);
Forward(wnd);
DfSendMessage(wnd, PAINT, 0, 0);
return;
}
/* ---------- test end of window --------- */
if (WndCol == ClientWidth(wnd)-1) {
if (!isMultiLine(wnd)) {
if (!(currchar == wnd->text+wnd->MaxTextLength-2))
DfSendMessage(wnd, HORIZSCROLL, TRUE, 0);
}
else {
char *cp = currchar;
while (*cp != ' ' && cp != TextLine(wnd, wnd->CurrLine))
--cp;
if (cp == TextLine(wnd, wnd->CurrLine) ||
!wnd->WordWrapMode)
DfSendMessage(wnd, HORIZSCROLL, TRUE, 0);
else {
int dif = 0;
if (c != ' ') {
dif = (int) (currchar - cp);
wnd->CurrCol -= dif;
DfSendMessage(wnd, KEYBOARD, DEL, 0);
--dif;
}
DfSendMessage(wnd, KEYBOARD, '\n', 0);
currchar = CurrChar;
wnd->CurrCol = dif;
if (c == ' ')
return;
}
}
}
/* ------ display the character ------ */
SetStandardColor(wnd);
PutWindowChar(wnd, c, WndCol, wnd->WndRow);
/* ----- advance the pointers ------ */
wnd->CurrCol++;
}
/* ------------ screen changing key strokes ------------- */
static void DoKeyStroke(DFWINDOW wnd, int c, PARAM p2)
{
switch (c) {
case RUBOUT:
if (wnd->CurrCol == 0 && wnd->CurrLine == 0)
break;
Backward(wnd);
case DEL:
DelKey(wnd);
break;
case SHIFT_HT:
ShiftTabKey(wnd, p2);
break;
case '\t':
TabKey(wnd, p2);
break;
case '\r':
if (!isMultiLine(wnd)) {
DfPostMessage(GetParent(wnd), KEYBOARD, c, p2);
break;
}
c = '\n';
default:
if (TextBlockMarked(wnd)) {
DfSendMessage(wnd, DFM_COMMAND, ID_DELETETEXT, 0);
DfSendMessage(wnd, PAINT, 0, 0);
}
KeyTyped(wnd, c);
break;
}
}
/* ----------- KEYBOARD Message ---------- */
static int KeyboardMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
int c = (int) p1;
if (WindowMoving || WindowSizing || ((int)p2 & ALTKEY))
return FALSE;
switch (c)
{
/* these keys get processed by lower classes */
case ESC:
case F1:
case F2:
case F3:
case F4:
case F5:
case F6:
case F7:
case F8:
case F9:
case F10:
case INS:
case SHIFT_INS:
case SHIFT_DEL:
return FALSE;
/* these keys get processed here */
case CTRL_FWD:
case CTRL_BS:
case CTRL_HOME:
case CTRL_END:
case CTRL_PGUP:
case CTRL_PGDN:
break;
default:
/* other ctrl keys get processed by lower classes */
if ((int)p2 & CTRLKEY)
return FALSE;
/* all other keys get processed here */
break;
}
DoMultiLines(wnd, c, p2);
if (DoScrolling(wnd, c, p2))
{
if (KeyBoardMarking)
ExtendBlock(wnd, WndCol, wnd->WndRow);
}
else if (!TestAttribute(wnd, READONLY))
{
DoKeyStroke(wnd, c, p2);
DfSendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
}
else
beep();
return TRUE;
}
/* ----------- SHIFT_CHANGED Message ---------- */
static void ShiftChangedMsg(DFWINDOW wnd, PARAM p1)
{
if (!((int)p1 & (LEFTSHIFT | RIGHTSHIFT)) &&
KeyBoardMarking) {
StopMarking(wnd);
KeyBoardMarking = FALSE;
}
}
/* ----------- ID_DELETETEXT Command ---------- */
static void DeleteTextCmd(DFWINDOW wnd)
{
if (TextBlockMarked(wnd)) {
char *bbl=TextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
char *bel=TextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
int len = (int) (bel - bbl);
SaveDeletedText(wnd, bbl, len);
wnd->TextChanged = TRUE;
strcpy(bbl, bel);
wnd->CurrLine = TextLineNumber(wnd, bbl-wnd->BlkBegCol);
wnd->CurrCol = wnd->BlkBegCol;
wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
if (wnd->WndRow < 0) {
wnd->wtop = wnd->BlkBegLine;
wnd->WndRow = 0;
}
DfSendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
ClearTextBlock(wnd);
BuildTextPointers(wnd);
}
}
/* ----------- ID_CLEAR Command ---------- */
static void ClearCmd(DFWINDOW wnd)
{
if (TextBlockMarked(wnd)) {
char *bbl=TextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
char *bel=TextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
int len = (int) (bel - bbl);
SaveDeletedText(wnd, bbl, len);
wnd->CurrLine = TextLineNumber(wnd, bbl);
wnd->CurrCol = wnd->BlkBegCol;
wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
if (wnd->WndRow < 0) {
wnd->WndRow = 0;
wnd->wtop = wnd->BlkBegLine;
}
/* ------ change all text lines in block to \n ----- */
while (bbl < bel) {
char *cp = strchr(bbl, '\n');
if (cp > bel)
cp = bel;
strcpy(bbl, cp);
bel -= (int) (cp - bbl);
bbl++;
}
ClearTextBlock(wnd);
BuildTextPointers(wnd);
DfSendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
wnd->TextChanged = TRUE;
}
}
/* ----------- ID_UNDO Command ---------- */
static void UndoCmd(DFWINDOW wnd)
{
if (wnd->DeletedText != NULL) {
PasteText(wnd, wnd->DeletedText, wnd->DeletedLength);
free(wnd->DeletedText);
wnd->DeletedText = NULL;
wnd->DeletedLength = 0;
DfSendMessage(wnd, PAINT, 0, 0);
}
}
/* ----------- ID_PARAGRAPH Command ---------- */
static void ParagraphCmd(DFWINDOW wnd)
{
int bc, fl;
char *bl, *bbl, *bel, *bb;
ClearTextBlock(wnd);
/* ---- forming paragraph from cursor position --- */
fl = wnd->wtop + wnd->WndRow;
bbl = bel = bl = TextLine(wnd, wnd->CurrLine);
if ((bc = wnd->CurrCol) >= ClientWidth(wnd))
bc = 0;
Home(wnd);
/* ---- locate the end of the paragraph ---- */
while (*bel) {
int blank = TRUE;
char *bll = bel;
/* --- blank line marks end of paragraph --- */
while (*bel && *bel != '\n') {
if (*bel != ' ')
blank = FALSE;
bel++;
}
if (blank) {
bel = bll;
break;
}
if (*bel)
bel++;
}
if (bel == bbl) {
DfSendMessage(wnd, KEYBOARD, DN, 0);
return;
}
if (*bel == '\0')
--bel;
if (*bel == '\n')
--bel;
/* --- change all newlines in block to spaces --- */
while (CurrChar < bel) {
if (*CurrChar == '\n') {
*CurrChar = ' ';
wnd->CurrLine++;
wnd->CurrCol = 0;
}
else
wnd->CurrCol++;
}
/* ---- insert newlines at new margin boundaries ---- */
bb = bbl;
while (bbl < bel) {
bbl++;
if ((int)(bbl - bb) == ClientWidth(wnd)-1) {
while (*bbl != ' ' && bbl > bb)
--bbl;
if (*bbl != ' ') {
bbl = strchr(bbl, ' ');
if (bbl == NULL || bbl >= bel)
break;
}
*bbl = '\n';
bb = bbl+1;
}
}
BuildTextPointers(wnd);
/* --- put cursor back at beginning --- */
wnd->CurrLine = TextLineNumber(wnd, bl);
wnd->CurrCol = bc;
if (fl < wnd->wtop)
wnd->wtop = fl;
wnd->WndRow = fl - wnd->wtop;
DfSendMessage(wnd, PAINT, 0, 0);
DfSendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
wnd->TextChanged = TRUE;
BuildTextPointers(wnd);
}
/* ----------- COMMAND Message ---------- */
static int CommandMsg(DFWINDOW wnd, PARAM p1)
{
switch ((int)p1) {
case ID_DELETETEXT:
DeleteTextCmd(wnd);
return TRUE;
case ID_CLEAR:
ClearCmd(wnd);
return TRUE;
case ID_UNDO:
UndoCmd(wnd);
return TRUE;
case ID_PARAGRAPH:
ParagraphCmd(wnd);
return TRUE;
default:
break;
}
return FALSE;
}
/* ---------- CLOSE_WINDOW Message ----------- */
static int CloseWindowMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
int rtn;
DfSendMessage(NULL, HIDE_CURSOR, 0, 0);
if (wnd->DeletedText != NULL)
free(wnd->DeletedText);
if (wnd->text != NULL)
{
free(wnd->text);
wnd->text = NULL;
}
rtn = BaseWndProc(EDITBOX, wnd, CLOSE_WINDOW, p1, p2);
return rtn;
}
/* ------- Window processing module for EDITBOX class ------ */
int EditBoxProc(DFWINDOW wnd, DFMESSAGE msg, PARAM p1, PARAM p2)
{
int rtn;
switch (msg) {
case CREATE_WINDOW:
return CreateWindowMsg(wnd);
case ADDTEXT:
return AddTextMsg(wnd, p1, p2);
case SETTEXT:
return SetTextMsg(wnd, p1);
case CLEARTEXT:
return ClearTextMsg(wnd);
case GETTEXT:
return GetTextMsg(wnd, p1, p2);
case SETTEXTLENGTH:
return SetTextLengthMsg(wnd, (unsigned) p1);
case KEYBOARD_CURSOR:
KeyboardCursorMsg(wnd, p1, p2);
return TRUE;
case SETFOCUS:
if (!(int)p1)
DfSendMessage(NULL, HIDE_CURSOR, 0, 0);
case PAINT:
case MOVE:
rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
DfSendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
return rtn;
case DFM_SIZE:
return SizeMsg(wnd, p1, p2);
case SCROLL:
return ScrollMsg(wnd, p1);
case HORIZSCROLL:
return HorizScrollMsg(wnd, p1);
case SCROLLPAGE:
return ScrollPageMsg(wnd, p1);
case HORIZPAGE:
return HorizPageMsg(wnd, p1);
case LEFT_BUTTON:
if (LeftButtonMsg(wnd, p1, p2))
return TRUE;
break;
case MOUSE_MOVED:
if (MouseMovedMsg(wnd, p1, p2))
return TRUE;
break;
case DFM_BUTTON_RELEASED:
if (ButtonReleasedMsg(wnd))
return TRUE;
break;
case KEYBOARD:
if (KeyboardMsg(wnd, p1, p2))
return TRUE;
break;
case SHIFT_CHANGED:
ShiftChangedMsg(wnd, p1);
break;
case DFM_COMMAND:
if (CommandMsg(wnd, p1))
return TRUE;
break;
case CLOSE_WINDOW:
return CloseWindowMsg(wnd, p1, p2);
default:
break;
}
return BaseWndProc(EDITBOX, wnd, msg, p1, p2);
}
/* ------ save deleted text for the Undo command ------ */
static void SaveDeletedText(DFWINDOW wnd, char *bbl, int len)
{
wnd->DeletedLength = len;
wnd->DeletedText=DFrealloc(wnd->DeletedText,len);
memmove(wnd->DeletedText, bbl, len);
}
/* ---- cursor right key: right one character position ---- */
static void Forward(DFWINDOW wnd)
{
char *cc = CurrChar+1;
if (*cc == '\0')
return;
if (*CurrChar == '\n') {
Home(wnd);
Downward(wnd);
}
else {
wnd->CurrCol++;
if (WndCol == ClientWidth(wnd))
DfSendMessage(wnd, HORIZSCROLL, TRUE, 0);
}
}
/* ----- stick the moving cursor to the end of the line ---- */
static void StickEnd(DFWINDOW wnd)
{
char *cp = TextLine(wnd, wnd->CurrLine);
char *cp1 = strchr(cp, '\n');
int len = cp1 ? (int) (cp1 - cp) : 0;
wnd->CurrCol = min(len, wnd->CurrCol);
if (wnd->wleft > wnd->CurrCol) {
wnd->wleft = max(0, wnd->CurrCol - 4);
DfSendMessage(wnd, PAINT, 0, 0);
}
else if (wnd->CurrCol-wnd->wleft >= ClientWidth(wnd)) {
wnd->wleft = wnd->CurrCol - (ClientWidth(wnd)-1);
DfSendMessage(wnd, PAINT, 0, 0);
}
}
/* --------- cursor down key: down one line --------- */
static void Downward(DFWINDOW wnd)
{
if (isMultiLine(wnd) &&
wnd->WndRow+wnd->wtop+1 < wnd->wlines) {
wnd->CurrLine++;
if (wnd->WndRow == ClientHeight(wnd)-1)
BaseWndProc(EDITBOX, wnd, SCROLL, TRUE, 0);
else
wnd->WndRow++;
StickEnd(wnd);
}
}
/* -------- cursor up key: up one line ------------ */
static void Upward(DFWINDOW wnd)
{
if (isMultiLine(wnd) && wnd->CurrLine != 0) {
--wnd->CurrLine;
if (wnd->WndRow == 0)
BaseWndProc(EDITBOX, wnd, SCROLL, FALSE, 0);
else
--wnd->WndRow;
StickEnd(wnd);
}
}
/* ---- cursor left key: left one character position ---- */
static void Backward(DFWINDOW wnd)
{
if (wnd->CurrCol) {
--wnd->CurrCol;
if (wnd->CurrCol < wnd->wleft)
DfSendMessage(wnd, HORIZSCROLL, FALSE, 0);
}
else if (isMultiLine(wnd) && wnd->CurrLine != 0) {
Upward(wnd);
End(wnd);
}
}
/* -------- End key: to end of line ------- */
static void End(DFWINDOW wnd)
{
while (*CurrChar && *CurrChar != '\n')
++wnd->CurrCol;
if (WndCol >= ClientWidth(wnd)) {
wnd->wleft = wnd->CurrCol - (ClientWidth(wnd)-1);
DfSendMessage(wnd, PAINT, 0, 0);
}
}
/* -------- Home key: to beginning of line ------- */
static void Home(DFWINDOW wnd)
{
wnd->CurrCol = 0;
if (wnd->wleft != 0) {
wnd->wleft = 0;
DfSendMessage(wnd, PAINT, 0, 0);
}
}
/* -- Ctrl+cursor right key: to beginning of next word -- */
static void NextWord(DFWINDOW wnd)
{
int savetop = wnd->wtop;
int saveleft = wnd->wleft;
ClearVisible(wnd);
while (!isWhite(*CurrChar)) {
char *cc = CurrChar+1;
if (*cc == '\0')
break;
Forward(wnd);
}
while (isWhite(*CurrChar)) {
char *cc = CurrChar+1;
if (*cc == '\0')
break;
Forward(wnd);
}
SetVisible(wnd);
DfSendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
if (wnd->wtop != savetop || wnd->wleft != saveleft)
DfSendMessage(wnd, PAINT, 0, 0);
}
/* -- Ctrl+cursor left key: to beginning of previous word -- */
static void PrevWord(DFWINDOW wnd)
{
int savetop = wnd->wtop;
int saveleft = wnd->wleft;
ClearVisible(wnd);
Backward(wnd);
while (isWhite(*CurrChar)) {
if (wnd->CurrLine == 0 && wnd->CurrCol == 0)
break;
Backward(wnd);
}
while (wnd->CurrCol != 0 && !isWhite(*CurrChar))
Backward(wnd);
if (isWhite(*CurrChar))
Forward(wnd);
SetVisible(wnd);
if (wnd->wleft != saveleft)
if (wnd->CurrCol >= saveleft)
if (wnd->CurrCol - saveleft < ClientWidth(wnd))
wnd->wleft = saveleft;
DfSendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
if (wnd->wtop != savetop || wnd->wleft != saveleft)
DfSendMessage(wnd, PAINT, 0, 0);
}
/* ----- modify text pointers from a specified position
by a specified plus or minus amount ----- */
static void ModTextPointers(DFWINDOW wnd, int lineno, int var)
{
while (lineno < wnd->wlines)
*((wnd->TextPointers) + lineno++) += var;
}
/* ----- set anchor point for marking text block ----- */
static void SetAnchor(DFWINDOW wnd, int mx, int my)
{
ClearTextBlock(wnd);
/* ------ set the anchor ------ */
wnd->BlkBegLine = wnd->BlkEndLine = my;
wnd->BlkBegCol = wnd->BlkEndCol = mx;
DfSendMessage(wnd, PAINT, 0, 0);
}
/* EOF */