📄 textedit.c
字号:
#endif
node = mark->curNode;
pIns = node->content.string + mark->pos_lnOff;
if (kcode == SCANCODE_CURSORBLOCKRIGHT) {
if (*pIns == '\0')
return;
else if (*pIns == txtdoc->lnsep || is_rn_sep(pIns)) {
curnode = TXTNODE_NEXT(node);
set_current_node (txtdoc, curnode, bShift, FALSE);
#ifdef _SELECT_SUPPORT
if (bShift) {
SELECT_NODE(node, (NODE_IS_SELECTED(curnode) ? FALSE : TRUE) );
SELECT_NODE(curnode, TRUE);
ptedata->selItemY += NODE_HEIGHT(node);
}
else
#endif
ptedata->curItemY += NODE_HEIGHT(node);
}
else {
mark->pos_lnOff += CHLENNEXT(pIns, (node->content.string +
node->content.txtlen - pIns));
}
}
else if (kcode == SCANCODE_CURSORBLOCKLEFT) {
len = -1;
if (pIns == node->content.string) {
if (BE_FIRST_NODE(node))
return;
else {
curnode = TXTNODE_PREV(node);
set_current_node (txtdoc, curnode, bShift, FALSE);
#ifdef _SELECT_SUPPORT
if (bShift) {
SELECT_NODE(node, (NODE_IS_SELECTED(curnode) ? FALSE : TRUE) );
SELECT_NODE(curnode, TRUE);
ptedata->selItemY -= NODE_HEIGHT(TXTNODE_PREV(node));
}
else
#endif
ptedata->curItemY -= NODE_HEIGHT(TXTNODE_PREV(node));
mark->pos_lnOff = TXTNODE_PREV(node)->content.txtlen - 1;
}
}
else {
mark->pos_lnOff -= CHLENPREV(node->content.string, pIns);
}
}
else if (kcode == SCANCODE_HOME || kcode == SCANCODE_END) {
myGetCaretPos (&pt);
pt.y -= ptedata->curItemY;
pt.x = (kcode == SCANCODE_HOME)? 0 : scrolled_get_contwidth (ptescr) - 1;
if (node)
ptedata->des_caret_x = pt.x;
teOnMouseDown (hWnd, node, &pt, ptedata->curItemY, bShift);
goto SFRETURN;
}
teSetCaretPos (hWnd, ptedata);
SFRETURN:
#ifdef _SELECT_SUPPORT
if (bShift) {
REFRESH_NODE(mark->curNode);
check_caret ();
}
#endif
}
#ifdef _SELECT_SUPPORT
static void te_cursor_move (HWND hWnd, PTEDATA ptedata, POINT *pt)
{
int item_h;
TextDoc *txtdoc = &ptedata->txtdoc;
TextMark *selection = &txtdoc->selection;
TextNode *curnode;
POINT oldpt, newpt;
/* begin to select */
if (!selection->curNode) {
begin_selection (ptedata);
return;
}
curnode = selection->curNode;
item_h = scrollview_get_item_height (curnode->addData);
if (pt->y >= ptedata->selItemY + item_h) {
TextNode *next = TXTNODE_NEXT (curnode);
if (next) {
selection->curNode = next;
ptedata->selItemY += item_h;
}
else {
if (selection->pos_lnOff != curnode->content.txtlen) {
selection->pos_lnOff = curnode->content.txtlen;
REFRESH_NODE(curnode);
check_caret ();
}
return;
}
//FIXME
pt->y = ptedata->selItemY + item_h + ptedata->nLineHeight/2;
}
else if (pt->y < ptedata->selItemY) {
TextNode *prev = TXTNODE_PREV (curnode);
if (prev) {
selection->curNode = prev;
item_h = scrollview_get_item_height ((HSVITEM)prev->addData);
ptedata->selItemY -= item_h;
}
else {
if (selection->pos_lnOff != 0) {
selection->pos_lnOff = 0;
REFRESH_NODE(curnode);
check_caret ();
}
return;
}
pt->y = ptedata->selItemY - ptedata->nLineHeight/2;
}
if (ptedata->flags & TEST_MOVE) {
/*
int step;
step = pt->y - ptescr->nContY - ptescr->visibleHeight;
step = step > ptedata->nLineHeight ? 6 : 3;
*/
scrolled_make_pos_visible (hWnd, ptescr, pt->x, pt->y);
}
pt->y -= ptedata->selItemY;
/* moves to a new line */
if (curnode && selection->curNode != curnode) {
/* moves off the current selected line */
if (NODE_IS_SELECTED(selection->curNode))
SELECT_NODE(curnode, FALSE);
else
SELECT_NODE(selection->curNode, TRUE);
REFRESH_NODE(curnode);
}
myGetSelPos (&oldpt);
set_caret_pos (hWnd, ptedata, selection->curNode, pt->x, pt->y, TRUE);
myGetSelPos (&newpt);
if (oldpt.x != newpt.x || oldpt.y != newpt.y)
REFRESH_NODE(selection->curNode);
check_caret ();
}
#endif
static SVITEMOPS textedit_iops =
{
NULL, NULL, teDrawItem
};
void textedit_set_draw_selected (HWND hWnd, TEITEM_DRAWSEL_FUNC drawSel)
{
PTEDATA ptedata = (PTEDATA) GetWindowAdditionalData2 (hWnd);
ptedata->drawSelected = drawSel;
InvalidateRect (hWnd, NULL, TRUE);
}
/* --------------------------------------------------------------------------------- */
static int textedit_get_pos_ex (HWND hWnd, int *line_pos, int *char_pos, BOOL bSel)
{
PTEDATA ptedata = (PTEDATA) GetWindowAdditionalData2 (hWnd);
TextDoc *txtdoc = &ptedata->txtdoc;
int nr_chars = 0;
TextMark *mark;
mark = GETMARK(bSel);
if (!mark->curNode)
return -1;
if (line_pos) {
*line_pos = NODE_INDEX(mark->curNode);
}
if (char_pos) {
nr_chars = GetTextMCharInfo (GetWindowFont (hWnd),
mark->curNode->content.string, mark->pos_lnOff, NULL);
*char_pos = nr_chars;
}
return mark->pos_lnOff;
}
int textedit_get_caretpos (HWND hWnd, int *line_pos, int *char_pos)
{
return textedit_get_pos_ex (hWnd, line_pos, char_pos, FALSE);
}
int textedit_get_selpos (HWND hWnd, int *line_pos, int *char_pos)
{
return textedit_get_pos_ex (hWnd, line_pos, char_pos, TRUE);
}
static int textedit_set_pos_ex (HWND hWnd, int line_pos, int char_pos, BOOL bSel)
{
PTEDATA ptedata = (PTEDATA) GetWindowAdditionalData2 (hWnd);
TextDoc *txtdoc = &ptedata->txtdoc;
int item_y, newpos;
TextMark *mark;
TextNode *node;
mark = GETMARK(bSel);
if ( !(node = te_set_position (hWnd, ptedata, mark,
line_pos, char_pos, &item_y, &newpos)) )
return -1;
#ifdef _SELECT_SUPPORT
/* unselect the former seleted before mark is changed */
if (txtdoc->selection.curNode) {
te_unselect_all (hWnd, ptedata, TRUE);
}
#endif
SETITEMY(bSel, item_y);
mark->pos_lnOff = newpos;
mark->curNode = node;
teSetCaretPos (hWnd, ptedata);
#ifdef _SELECT_SUPPORT
if (bSel)
te_set_selection (hWnd, ptedata);
#endif
return mark->pos_lnOff;
}
#ifdef _TITLE_SUPPORT
static int textedit_get_titletext (HWND hWnd, PTEDATA ptedata, int tlen, char *buffer)
{
int len, title_len;
if (!ptedata->title)
return -1;
title_len = strlen (ptedata->title);
if (!buffer)
return title_len;
if (tlen >= 0)
len = (tlen > DEF_TITLE_LEN) ? DEF_TITLE_LEN : tlen;
else
len = DEF_TITLE_LEN;
strncpy (buffer, ptedata->title, len);
buffer[len] = '\0';
return title_len;
}
static int textedit_set_titletext (HWND hWnd, PTEDATA ptedata, int tlen, const char *newtitle)
{
int len;
HDC hdc;
if (!ptedata->title || !newtitle)
return -1;
if (tlen >= 0)
len = (tlen > DEF_TITLE_LEN) ? DEF_TITLE_LEN : tlen;
else
len = DEF_TITLE_LEN;
strncpy (ptedata->title, newtitle, len);
ptedata->title[len] = '\0';
hdc = GetClientDC (hWnd);
SelectFont (hdc, GetWindowFont(hWnd));
ptedata->titleIndent = teGetTitleIndent (hWnd, ptedata, hdc);
ReleaseDC (hWnd);
mySetCaretPos (hWnd, ptedata->titleIndent, 0 + ptedata->nLineAboveH);
return strlen (ptedata->title);
}
#endif
static void textedit_reset_content (HWND hWnd, PTEDATA ptedata, const char *newtext)
{
TextDoc *txtdoc = &ptedata->txtdoc;
scrollview_reset_content (hWnd, &ptedata->svdata);
teResetData (ptedata);
scrollview_freeze (hWnd, &ptedata->svdata, TRUE);
textdoc_settext (txtdoc, newtext);
scrollview_freeze (hWnd, &ptedata->svdata, FALSE);
mySetCaretPos (hWnd, teGetLineIndent(ptedata, FIRSTNODE(txtdoc)),
0 + ptedata->nLineAboveH);
}
#ifdef _CLIPBOARD_SUPPORT
/*
* textedit_insert_cbtext : inserts clipboard texts into the current insertion point
*/
static int textedit_insert_cbtext (HWND hWnd, PTEDATA ptedata)
{
int inserting;
unsigned char *txtBuffer;
TextDoc *txtdoc = &ptedata->txtdoc;
/*
TextNode *node = txtdoc->insert.curNode;
TextNode *nextnode = NULL;
if (!BE_LAST_NODE(node))
nextnode = TXTNODE_NEXT (node);
*/
inserting = GetClipBoardDataLen (CBNAME_TEXT);
txtBuffer = FixStrAlloc (inserting);
GetClipBoardData (CBNAME_TEXT, txtBuffer, inserting);
textdoc_insert_text (txtdoc, txtBuffer, inserting);
FreeFixStr(txtBuffer);
//FIXME
//if (node != txtdoc->insert.curNode)
teNodeChange (txtdoc, FALSE);
teSetCaretPos (hWnd, ptedata);
//FIXME
REFRESH_NODE(txtdoc->insert.curNode);
/*
if (set_line_size (hWnd, ptedata, node) < 0)
REFRESH_NODE(node);
if (nextnode)
set_line_size (hWnd, ptedata, TXTNODE_PREV(nextnode));
else
set_line_size (hWnd, ptedata, LASTNODE(txtdoc));
*/
return inserting;
}
#endif
/*
* initialize text edit object structure
*/
static int teInitData (HWND hWnd, PTEDATA ptedata)
{
int pageval;
TextDoc *txtdoc = &ptedata->txtdoc;
/* init scrollview object */
scrollview_init (hWnd, &ptedata->svdata);
/* change default move_content function */
ptedata->svdata.scrdata.move_content = textedit_set_svlist;
ptedata->nLineHeight = DEF_LINE_HEIGHT;
ptedata->nLineAboveH = DEF_LINE_ABOVE_H;
ptedata->nLineBaseH = DEF_LINE_BASE_H;
#ifdef _TITLE_SUPPORT
if (GetWindowStyle(hWnd) & ES_TITLE) {
ptedata->title = FixStrAlloc (DEF_TITLE_LEN+1);
ptedata->title[0] = '\0';
ptedata->titleIndent = 0;
}
else {
ptedata->title = NULL;
ptedata->titleIndent = 0;
}
#endif
scrolled_set_scrollval (ptescr, 0, ptedata->nLineHeight);
pageval = (ptescr->visibleHeight / ptedata->nLineHeight ) *
ptedata->nLineHeight;
scrolled_set_scrollpageval (ptescr, 0, pageval);
ptedata->lnChar = 0;
teResetData (ptedata);
scrollview_set_itemops (&ptedata->svdata, (SVITEMOPS*)&textedit_iops);
ptedata->drawSelected = NULL;
/* init text document object */
INIT_LIST_HEAD(&txtdoc->queue);
memset (&txtdoc->insert, 0, sizeof(txtdoc->insert));
#ifdef _SELECT_SUPPORT
txtdoc->selection.curNode = NULL;
#endif
textdoc_reset (hWnd, txtdoc);
scrollview_freeze (hWnd, &ptedata->svdata, TRUE);
textdoc_settext (txtdoc, GetWindowCaption(hWnd));
scrollview_freeze (hWnd, &ptedata->svdata, FALSE);
return 0;
}
#ifdef _UNDO_SUPPORT
/*
static void teUndoBackup (TextDoc *txtdoc)
{
PTEDATA ptedata = (PTEDATA)GetWindowAdditionalData2 ((HWND)txtdoc->fn_data);
TextNode *curnode = txtdoc->insert.curNode;
if ( (ptedata->act_count %= ACTION_COUNT) == 0 ) {
BACKUP_DATA();
ptedata->bkIns = txtdoc->insert;
ptedata->bkSel = txtdoc->selection;
testr_free (ptedata->bkBuff);
free (ptedata->bkBuff);
ptedata->bkBuff = testr_dup (&curnode->content);
printf ("back up : %s\n", ptedata->bkBuff->string);
ptedata->act_count = 0;
}
ptedata->act_count ++;
}
*/
static int te_init_undo (HWND hWnd, PTEDATA ptedata)
{
ptedata->undo_depth = DEF_UNDO_DEPTH;
ptedata->bkData = malloc (sizeof(BKDATA)*ptedata->undo_depth);
if (!ptedata->bkData)
return -1;
ptedata->undo_level = -1;
ptedata->act_count = 0;
return 0;
}
#endif
static int textedit_init (HWND hWnd, PTEDATA ptedata)
{
if (!ptedata)
return -1;
if (BE_WRAP(hWnd))
ShowScrollBar (hWnd, SB_HORZ, FALSE);
teInitData (hWnd, ptedata);
SetWindowAdditionalData2 (hWnd, (DWORD) ptedata);
CreateCaret (hWnd, NULL, 1, ptedata->nLineHeight - ptedata->nLineAboveH);
//SetFocus (hWnd);
mySetCaretPos (hWnd, ptedata->des_caret_x, 0 + ptedata->nLineAboveH);
#ifdef _UNDO_SUPPORT
if (te_init_undo (hWnd, ptedata) < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -