📄 editbox.c
字号:
/* ------------- editbox.c ------------ */
#include "dflat.h"
#define EditBufLen(wnd) (isMultiLine(wnd) ? EDITLEN : ENTRYLEN)
#define SetLinePointer(wnd, ln) (wnd->CurrLine = ln)
#define FANCY_CTRL_P
#define Ch(c) ((c)&0x7f)
#define isWhite(c) (Ch(c)==' '||Ch(c)=='\n'||Ch(c)=='\f'||Ch(c)=='\t')
/* ---------- local prototypes ----------- */
static void SaveDeletedText(WINDOW, char *, int);
static void Forward(WINDOW);
static void Backward(WINDOW);
static void End(WINDOW);
static void Home(WINDOW);
static void Downward(WINDOW);
static void Upward(WINDOW);
static void StickEnd(WINDOW);
static void NextWord(WINDOW);
static void PrevWord(WINDOW);
static void ModTextPointers(WINDOW, int, int);
static void SetAnchor(WINDOW, 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(WINDOW wnd)
{
int rtn = BaseWndProc(EDITBOX, wnd, CREATE_WINDOW, 0, 0);
/* *** added in 0.6e *** */
wnd->BlkBegLine=0;
wnd->BlkBegCol=0;
wnd->BlkEndLine=0;
wnd->BlkEndCol=0;
wnd->TextChanged=FALSE;
wnd->DeletedText=NULL;
wnd->DeletedLength=0;
/* *** /added *** */
wnd->MaxTextLength=MAXTEXTLEN+1;
wnd->textlen=EditBufLen(wnd);
wnd->InsertMode=TRUE;
if (isMultiLine(wnd))
wnd->WordWrapMode = TRUE;
SendMessage(wnd, CLEARTEXT, 0, 0);
return rtn;
}
/* ----------- SETTEXT Message ---------- */
static int SetTextMsg(WINDOW wnd, PARAM p1)
{
int rtn=FALSE;
if (strlen((char *)p1) <= wnd->MaxTextLength)
{
rtn=BaseWndProc(EDITBOX, wnd, SETTEXT, p1, 0);
wnd->TextChanged=FALSE;
}
return rtn;
}
/* ----------- CLEARTEXT Message ------------ */
static int ClearTextMsg(WINDOW 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(WINDOW 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;
SendMessage(wnd, KEYBOARD_CURSOR,
WndCol, wnd->WndRow);
}
}
}
return rtn;
}
/* ----------- GETTEXT Message ---------- */
static int GetTextMsg(WINDOW 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(WINDOW 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(WINDOW 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))
SendMessage(NULL, SHOW_CURSOR,
(wnd->InsertMode && !TextMarking), 0);
else
SendMessage(NULL, HIDE_CURSOR, 0, 0);
}
}
/* ----------- SIZE Message ---------- */
int SizeMsg(WINDOW wnd, PARAM p1, PARAM p2)
{
int rtn = BaseWndProc(EDITBOX, wnd, 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);
}
SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
return rtn;
}
/* ----------- SCROLL Message ---------- */
static int ScrollMsg(WINDOW 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++;
}
SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
}
}
return rtn;
}
/* ----------- HORIZSCROLL Message ---------- */
static int HorizScrollMsg(WINDOW 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;
SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
}
}
return rtn;
}
/* ----------- SCROLLPAGE Message ---------- */
static int ScrollPageMsg(WINDOW wnd, PARAM p1)
{
int rtn = FALSE;
if (isMultiLine(wnd)) {
rtn = BaseWndProc(EDITBOX, wnd, SCROLLPAGE, p1, 0);
SetLinePointer(wnd, wnd->wtop+wnd->WndRow);
StickEnd(wnd);
SendMessage(wnd, KEYBOARD_CURSOR,WndCol, wnd->WndRow);
}
return rtn;
}
/* ----------- HORIZSCROLLPAGE Message ---------- */
static int HorizPageMsg(WINDOW 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;
SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
return rtn;
}
/* ----- Extend the marked block to the new x,y position ---- */
static void ExtendBlock(WINDOW 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;
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(WINDOW wnd, PARAM p1, PARAM p2)
{
int MouseX = (int) p1 - GetClientLeft(wnd);
int MouseY = (int) p2 - GetClientTop(wnd);
RECT rc = ClientRect(wnd);
char *lp;
int len;
if (KeyBoardMarking)
return TRUE;
if (WindowMoving || WindowSizing)
return FALSE;
if (TextMarking) {
if (!InsideRect(p1, p2, rc)) {
int x = MouseX, y = MouseY;
int dir;
MESSAGE 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 (SendMessage(wnd, msg, dir, 0))
ExtendBlock(wnd, x, y);
SendMessage(wnd, PAINT, 0, 0);
}
}
return TRUE;
}
if (!InsideRect(p1, p2, rc))
return FALSE;
if (TextBlockMarked(wnd)) {
ClearTextBlock(wnd);
SendMessage(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;
SendMessage(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)
&& MouseX+wnd->wleft < strlen(wnd->text)))
wnd->CurrCol = MouseX+wnd->wleft;
SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
return TRUE;
}
/* ----------- MOUSE_MOVED Message ---------- */
static int MouseMovedMsg(WINDOW wnd, PARAM p1, PARAM p2)
{
int MouseX = (int) p1 - GetClientLeft(wnd);
int MouseY = (int) p2 - GetClientTop(wnd);
RECT 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);
SendMessage(NULL,MOUSE_TRAVEL,(PARAM) &rc, 0);
ButtonDown = FALSE;
}
if (TextMarking && !(WindowMoving || WindowSizing)) {
ExtendBlock(wnd, MouseX, MouseY);
return TRUE;
}
return FALSE;
}
static void StopMarking(WINDOW 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(WINDOW wnd)
{
ButtonDown = FALSE;
if (TextMarking && !(WindowMoving || WindowSizing)) {
/* release the mouse ouside the edit box */
SendMessage(NULL, MOUSE_TRAVEL, 0, 0);
StopMarking(wnd);
return TRUE;
}
PrevY = -1;
return FALSE;
}
/* ---- Process text block keys for multiline text box ---- */
static void DoMultiLines(WINDOW wnd, int c, PARAM p2)
{
if (!KeyBoardMarking) {
if ((int)p2 & (LEFTSHIFT | RIGHTSHIFT)) {
switch (c) {
case HOME:
case CTRL_HOME:
case CTRL_BS:
case PGUP:
case CTRL_PGUP:
case BS:
case UP:
case END:
case CTRL_END:
case PGDN:
case CTRL_PGDN:
case DN:
case FWD:
case LARROW:
case CTRL_RARROW:
case CTRL_LARROW:
KeyBoardMarking = TextMarking = TRUE;
SetAnchor(wnd, wnd->CurrCol, wnd->CurrLine);
break;
default:
break;
}
}
}
}
/* ---------- page/scroll keys ----------- */
static int DoScrolling(WINDOW wnd, int c, PARAM p2)
{
switch (c) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -