📄 editbox.c
字号:
/* ------------- editbox.c ------------ */
#include "dflat.h"
#define EditBufLen(wnd) (DfIsMultiLine(wnd) ? DF_EDITLEN : DF_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;
/* ----------- DFM_CREATE_WINDOW Message ---------- */
static int CreateWindowMsg(DFWINDOW wnd)
{
int rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_CREATE_WINDOW, 0, 0);
wnd->MaxTextLength = DF_MAXTEXTLEN+1;
wnd->textlen = EditBufLen(wnd);
wnd->InsertMode = TRUE;
DfSendMessage(wnd, DFM_CLEARTEXT, 0, 0);
return rtn;
}
/* ----------- DFM_SETTEXT Message ---------- */
static int SetTextMsg(DFWINDOW wnd, DF_PARAM p1)
{
int rtn = FALSE;
if (strlen((char *)p1) <= wnd->MaxTextLength)
rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_SETTEXT, p1, 0);
return rtn;
}
/* ----------- DFM_CLEARTEXT Message ------------ */
static int ClearTextMsg(DFWINDOW wnd)
{
int rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_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;
}
/* ----------- DFM_ADDTEXT Message ---------- */
static int AddTextMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
int rtn = FALSE;
if (strlen((char *)p1)+wnd->textlen <= wnd->MaxTextLength) {
rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_ADDTEXT, p1, p2);
if (rtn != FALSE) {
if (!DfIsMultiLine(wnd)) {
wnd->CurrLine = 0;
wnd->CurrCol = strlen((char *)p1);
if (wnd->CurrCol >= DfClientWidth(wnd)) {
wnd->wleft = wnd->CurrCol-DfClientWidth(wnd);
wnd->CurrCol -= wnd->wleft;
}
wnd->BlkEndCol = wnd->CurrCol;
DfSendMessage(wnd, DFM_KEYBOARD_CURSOR,
DfWndCol, wnd->WndRow);
}
}
}
return rtn;
}
/* ----------- DFM_GETTEXT Message ---------- */
static int GetTextMsg(DFWINDOW wnd, DF_PARAM p1, DF_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;
}
/* ----------- DFM_SETTEXTLENGTH Message ---------- */
static int SetTextLengthMsg(DFWINDOW wnd, unsigned int len)
{
if (++len < DF_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';
DfBuildTextPointers(wnd);
}
return TRUE;
}
return FALSE;
}
/* ----------- DFM_KEYBOARD_CURSOR Message ---------- */
static void KeyboardCursorMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
wnd->CurrCol = (int)p1 + wnd->wleft;
wnd->WndRow = (int)p2;
wnd->CurrLine = (int)p2 + wnd->wtop;
if (wnd == DfInFocus) {
if (DfCharInView(wnd, (int)p1, (int)p2))
DfSendMessage(NULL, DFM_SHOW_CURSOR,
(wnd->InsertMode && !TextMarking), 0);
else
DfSendMessage(NULL, DFM_HIDE_CURSOR, 0, 0);
}
}
/* ----------- SIZE Message ---------- */
int SizeMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
int rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_DFM_SIZE, p1, p2);
if (DfWndCol > DfClientWidth(wnd)-1)
wnd->CurrCol = DfClientWidth(wnd)-1 + wnd->wleft;
if (wnd->WndRow > DfClientHeight(wnd)-1) {
wnd->WndRow = DfClientHeight(wnd)-1;
SetLinePointer(wnd, wnd->WndRow+wnd->wtop);
}
DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
return rtn;
}
/* ----------- DFM_SCROLL Message ---------- */
static int ScrollMsg(DFWINDOW wnd, DF_PARAM p1)
{
int rtn = FALSE;
if (DfIsMultiLine(wnd)) {
rtn = DfBaseWndProc(DF_EDITBOX,wnd,DFM_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 == DfClientHeight(wnd)-1) {
if (wnd->CurrLine > 0)
--wnd->CurrLine;
StickEnd(wnd);
}
else
wnd->WndRow++;
}
DfSendMessage(wnd,DFM_KEYBOARD_CURSOR,DfWndCol,wnd->WndRow);
}
}
return rtn;
}
/* ----------- DFM_HORIZSCROLL Message ---------- */
static int HorizScrollMsg(DFWINDOW wnd, DF_PARAM p1)
{
int rtn = FALSE;
char *currchar = DfCurrChar;
if (!(p1 &&
wnd->CurrCol == wnd->wleft && *currchar == '\n')) {
rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_HORIZSCROLL, p1, 0);
if (rtn != FALSE) {
if (wnd->CurrCol < wnd->wleft)
wnd->CurrCol++;
else if (DfWndCol == DfClientWidth(wnd))
--wnd->CurrCol;
DfSendMessage(wnd,DFM_KEYBOARD_CURSOR,DfWndCol,wnd->WndRow);
}
}
return rtn;
}
/* ----------- DFM_SCROLLPAGE Message ---------- */
static int ScrollPageMsg(DFWINDOW wnd, DF_PARAM p1)
{
int rtn = FALSE;
if (DfIsMultiLine(wnd)) {
rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_SCROLLPAGE, p1, 0);
SetLinePointer(wnd, wnd->wtop+wnd->WndRow);
StickEnd(wnd);
DfSendMessage(wnd, DFM_KEYBOARD_CURSOR,DfWndCol, wnd->WndRow);
}
return rtn;
}
/* ----------- HORIZSCROLLPAGE Message ---------- */
static int HorizPageMsg(DFWINDOW wnd, DF_PARAM p1)
{
int rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_HORIZPAGE, p1, 0);
if ((int) p1 == FALSE) {
if (wnd->CurrCol > wnd->wleft+DfClientWidth(wnd)-1)
wnd->CurrCol = wnd->wleft+DfClientWidth(wnd)-1;
}
else if (wnd->CurrCol < wnd->wleft)
wnd->CurrCol = wnd->wleft;
DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, 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 = DfTextLine(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, DFM_KEYBOARD_CURSOR, wnd->BlkEndCol, wnd->BlkEndLine);
bbl = min(wnd->BlkBegLine, wnd->BlkEndLine);
bel = max(wnd->BlkBegLine, wnd->BlkEndLine);
while (ptop < bbl) {
DfWriteTextLine(wnd, NULL, ptop, FALSE);
ptop++;
}
for (y = bbl; y <= bel; y++)
DfWriteTextLine(wnd, NULL, y, FALSE);
while (pbot > bel) {
DfWriteTextLine(wnd, NULL, pbot, FALSE);
--pbot;
}
}
/* ----------- DFM_LEFT_BUTTON Message ---------- */
static int LeftButtonMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
int MouseX = (int) p1 - DfGetClientLeft(wnd);
int MouseY = (int) p2 - DfGetClientTop(wnd);
DFRECT rc = DfClientRect(wnd);
char *lp;
int len;
if (KeyBoardMarking)
return TRUE;
if (DfWindowMoving || DfWindowSizing)
return FALSE;
if (DfIsMultiLine(wnd)) {
if (TextMarking) {
if (!DfInsideRect(p1, p2, rc)) {
int x = MouseX, y = MouseY;
int dir;
DFMESSAGE msg = 0;
if ((int)p2 == DfGetTop(wnd))
y++, dir = FALSE, msg = DFM_SCROLL;
else if ((int)p2 == DfGetBottom(wnd))
--y, dir = TRUE, msg = DFM_SCROLL;
else if ((int)p1 == DfGetLeft(wnd))
--x, dir = FALSE, msg = DFM_HORIZSCROLL;
else if ((int)p1 == DfGetRight(wnd))
x++, dir = TRUE, msg = DFM_HORIZSCROLL;
if (msg != 0) {
if (DfSendMessage(wnd, msg, dir, 0))
ExtendBlock(wnd, x, y);
DfSendMessage(wnd, DFM_PAINT, 0, 0);
}
}
return TRUE;
}
if (!DfInsideRect(p1, p2, rc))
return FALSE;
if (DfTextBlockMarked(wnd)) {
DfClearTextBlock(wnd);
DfSendMessage(wnd, DFM_PAINT, 0, 0);
}
if (wnd->wlines) {
if (MouseY > wnd->wlines-1)
return TRUE;
lp = DfTextLine(wnd, MouseY+wnd->wtop);
len = (int) (strchr(lp, '\n') - lp);
MouseX = min(MouseX, len);
if (MouseX < wnd->wleft) {
MouseX = 0;
DfSendMessage(wnd, DFM_KEYBOARD, DF_HOME, 0);
}
ButtonDown = TRUE;
ButtonX = MouseX;
ButtonY = MouseY;
}
else
MouseX = MouseY = 0;
wnd->WndRow = MouseY;
SetLinePointer(wnd, MouseY+wnd->wtop);
}
if (DfIsMultiLine(wnd) ||
(!DfTextBlockMarked(wnd)
&& (int)(MouseX+wnd->wleft) < (int)strlen(wnd->text)))
wnd->CurrCol = MouseX+wnd->wleft;
DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
return TRUE;
}
/* ----------- MOUSE_MOVED Message ---------- */
static int MouseMovedMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
{
int MouseX = (int) p1 - DfGetClientLeft(wnd);
int MouseY = (int) p2 - DfGetClientTop(wnd);
DFRECT rc = DfClientRect(wnd);
if (!DfInsideRect(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 = DfWindowRect(wnd);
DfSendMessage(NULL,DFM_MOUSE_TRAVEL,(DF_PARAM) &rc, 0);
ButtonDown = FALSE;
}
if (TextMarking && !(DfWindowMoving || DfWindowSizing)) {
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 (DfIsMultiLine(wnd)) {
ButtonDown = FALSE;
if (TextMarking && !(DfWindowMoving || DfWindowSizing)) {
/* release the mouse ouside the edit box */
DfSendMessage(NULL, DFM_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, DF_PARAM p2)
{
if (DfIsMultiLine(wnd) && !KeyBoardMarking) {
if ((int)p2 & (DF_LEFTSHIFT | DF_RIGHTSHIFT)) {
switch (c) {
case DF_HOME:
case DF_CTRL_HOME:
case DF_CTRL_BS:
case DF_PGUP:
case DF_CTRL_PGUP:
case DF_UP:
case DF_BS:
case DF_END:
case DF_CTRL_END:
case DF_PGDN:
case DF_CTRL_PGDN:
case DF_DN:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -