📄 textedit.c
字号:
const unsigned char *pLine, *pIns; DTFIRSTLINE fl; rc.left = 0; rc.top = 0; rc.right = ptedata->svdata.scrdata.nContWidth; rc.bottom = GetWindowFont(hWnd)->size; linenr = NODE_LINENR(node); pLine = node->content.string; pIns = pLine + mark->pos_lnOff; txtlen = node->content.txtlen; /* if (pLine[txtlen-1] == txtdoc->lnsep) txtlen --; */ lineidx = 0; while (txtlen > 0) { DrawTextEx2 (hdc, pLine, txtlen, &rc, indent, TE_FORMAT | DT_WORDBREAK | DT_CALCRECT, &fl); if (pLine + fl.nr_chars > pIns) break; else if (pLine + fl.nr_chars == pIns) { if (lineidx < linenr-1) { pLine += fl.nr_chars; lineidx ++; indent = 0; } break; } pLine += fl.nr_chars; txtlen -= fl.nr_chars; rc.top += ptedata->nLineHeight; lineidx ++; indent = 0; } GetTabbedTextExtent(hdc, pLine, pIns - pLine, &txtsize); w = indent + txtsize.cx; h += ptedata->nLineHeight * lineidx; ptedata->des_caret_x = w; endh = (h < ptescr->nContY) ? h : h + ptedata->nLineHeight; scrolled_make_pos_visible (hWnd, ptescr, -1, endh-1);#ifdef _SELECT_SUPPORT if (txtdoc->selection.curNode) mySetSelPos (w, h + ptedata->nLineAboveH); else#endif mySetCaretPos (hWnd, w, h + ptedata->nLineAboveH); } else { SIZE txtsize; GetTabbedTextExtent(hdc, node->content.string, mark->pos_lnOff, &txtsize); ptedata->des_caret_x = txtsize.cx + indent; endh = (h < ptescr->nContY) ? h : h + ptedata->nLineHeight; scrolled_make_pos_visible (hWnd, ptescr, txtsize.cx + indent, endh-1);#ifdef _SELECT_SUPPORT if (txtdoc->selection.curNode) mySetSelPos (txtsize.cx + indent, h + ptedata->nLineAboveH); else#endif mySetCaretPos (hWnd, txtsize.cx + indent, h + ptedata->nLineAboveH); } ReleaseDC (hdc);}static void teOnChar (HWND hWnd, PTEDATA ptedata, WPARAM wParam){ int chlen; unsigned char ch[2]; //int linenr, old_linenr, indent = 0; TextNode *node; DWORD dwStyle = GetWindowStyle(hWnd); if (dwStyle & ES_READONLY) { Ping(); return; } ch [0] = LOBYTE (wParam); ch [1] = HIBYTE (wParam); if (ch[1]) { chlen = 2; } else { chlen = 1; if ( ch[0] < 0x20 && ch[0] != '\b' && ch[0] != '\t' && ch[0] != '\n' && ch[0] != '\r' ) { return; } if (dwStyle & ES_UPPERCASE) { ch [0] = toupper (ch[0]); } else if (dwStyle & ES_LOWERCASE) { ch [0] = tolower (ch[0]); } //ENTER if (ch [0] == '\r') { ch [0] = ptedata->txtdoc.lnsep; } } //FIXME node = ptedata->txtdoc.insert.curNode; /* node = ptedata->txtdoc.insert.curNode; indent = teGetLineIndent (ptedata, node); old_linenr = NODE_LINENR(node); */#if 0 if (textdoc_insert_string (&ptedata->txtdoc, ch, chlen) < 0) return;#else if (textdoc_insert_string (&ptedata->txtdoc, ch, chlen)) REFRESH_NODE(node);#endif /* linenr = get_line_nr(hWnd, ptedata, node, indent); if (linenr != old_linenr) { scrollview_set_item_height (hWnd, (HSVITEM)node->addData, ptedata->nLineHeight*linenr); } set_line_width (hWnd, ptedata, node, indent); */ if (node != ptedata->txtdoc.insert.curNode) { node = ptedata->txtdoc.insert.curNode; //FIXME, optimize teNodeChange (&ptedata->txtdoc, FALSE); REFRESH_NODE(node); } teSetCaretPos (hWnd, ptedata); //REFRESH_NODE(node); //scrollview_refresh_content (&ptedata->svdata); NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CHANGE);}static voidteOnMouseDown (HWND hWnd, TextNode *node, POINT *pt, int item_y, BOOL bShift){ PTEDATA ptedata = (PTEDATA)GetWindowAdditionalData2(hWnd); TextDoc *txtdoc = &ptedata->txtdoc; if (!node) return; if (!bShift) { txtdoc->insert.curNode = node; ptedata->curItemY = item_y; }#ifdef _SELECT_SUPPORT else { txtdoc->selection.curNode = node; ptedata->selItemY = item_y; }#endif set_caret_pos (hWnd, ptedata, node, pt->x, pt->y, bShift);}#ifdef _SELECT_SUPPORTstatic void get_selected_rect (PTEDATA ptedata, RECT *rcSel){ TextDoc *txtdoc = &ptedata->txtdoc; rcSel->left = 0; rcSel->right = 0; if (ptedata->curItemY < ptedata->selItemY) { rcSel->top = ptedata->curItemY; rcSel->bottom = ptedata->selItemY + NODE_HEIGHT(txtdoc->selection.curNode); } else { rcSel->top = ptedata->selItemY; rcSel->bottom = ptedata->curItemY + NODE_HEIGHT(txtdoc->insert.curNode); }}/* * te_unselect_all : unselects the selected parts * Params : bChange - whether to change the insertion point to the * position of the selection point */static void te_unselect_all (HWND hWnd, PTEDATA ptedata, BOOL bChange){ TextDoc *txtdoc = &ptedata->txtdoc; RECT rcSel; POINT pt; get_selected_rect (ptedata, &rcSel); if (bChange) { txtdoc->insert = txtdoc->selection; ptedata->curItemY = ptedata->selItemY; myGetSelPos (&pt); } txtdoc->selection.curNode = NULL; scrollview_unselect_all (&ptedata->svdata); scrolled_refresh_rect (ptescr, &rcSel); if (bChange) { mySetCaretPos (hWnd, pt.x, pt.y); ptedata->des_caret_x = pt.x; }}static intte_set_selection (HWND hWnd, PTEDATA ptedata){ TextDoc *txtdoc = &ptedata->txtdoc; TextMark *markStart, *markEnd; TextNode *node; RECT rcSel; markStart = get_start_mark (ptedata); markEnd = (markStart == &txtdoc->insert) ? &txtdoc->selection : &txtdoc->insert; node = markStart->curNode; while (node) { SELECT_NODE (node, TRUE); if (node == markEnd->curNode) break; node = TXTNODE_NEXT (node); } get_selected_rect (ptedata, &rcSel); scrolled_refresh_rect (ptescr, &rcSel); check_caret (); return 0;}static int te_select_all (HWND hWnd, PTEDATA ptedata){ TextMark *selection = &ptedata->txtdoc.selection; TextMark *insertion = &ptedata->txtdoc.insert; TextNode *last; if (selection->curNode) { te_unselect_all (hWnd, ptedata, TRUE); } insertion->pos_lnOff = 0; insertion->curNode = FIRSTNODE(&ptedata->txtdoc); ptedata->curItemY = 0; teSetCaretPos (hWnd, ptedata); last = LASTNODE(&ptedata->txtdoc); selection->curNode = last; selection->pos_lnOff = last->content.txtlen; ptedata->selItemY = scrollview_get_total_item_height (&ptedata->svdata) - NODE_HEIGHT(last); //FIXME, optimize teSetCaretPos (hWnd, ptedata); return te_set_selection (hWnd, ptedata);}#endif/* * te_set_position : Sets insertion or selection position * Params : mark - insertion or selection point */static TextNode*te_set_position (HWND hWnd, PTEDATA ptedata, TextMark *mark, int line, int char_pos, int *item_y, int *newpos){ TextNode *markNode; int *pos_chars; int nr_chars; if (char_pos < 0) return NULL; if ( !(markNode = get_node_by_idx (ptedata, line, item_y)) ) return NULL; if (char_pos > markNode->content.txtlen) return NULL; pos_chars = ALLOCATE_LOCAL (markNode->content.txtlen * sizeof(int)); nr_chars = GetTextMCharInfo (GetWindowFont (hWnd), markNode->content.string, markNode->content.txtlen, pos_chars); if (char_pos > nr_chars) { DEALLOCATE_LOCAL (pos_chars); return NULL; } if (char_pos == nr_chars) char_pos = markNode->content.txtlen; else char_pos = pos_chars[char_pos]; DEALLOCATE_LOCAL (pos_chars); if (newpos) *newpos = char_pos; return markNode;}static intTE_OnMouseDown (HWND hWnd, HSVITEM hsvi, POINT* pt, int item_y, BOOL bShift){ PTEDATA ptedata = (PTEDATA)GetWindowAdditionalData2(hWnd); TextNode *node = NULL;#ifdef _SELECT_SUPPORT TextDoc *txtdoc = &ptedata->txtdoc; //TextNode *org_node = txtdoc->insert.curNode; TextMark *selection = &txtdoc->selection;#endif /* note that hsvi may be null */ if (hsvi) node = (TextNode*)scrollview_get_item_adddata (hsvi);#ifdef _SELECT_SUPPORT if (selection->curNode) { te_unselect_all (hWnd, ptedata, !bShift); }#endif if (!bShift) { if (node) ptedata->des_caret_x = pt->x; teOnMouseDown (hWnd, node, pt, item_y, bShift);//FIXME //ShowCaret (hWnd); NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CLICKED); //FIXME //NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CHANGE); }#ifdef _SELECT_SUPPORT else { teOnMouseDown (hWnd, node, pt, item_y, bShift); te_set_selection (hWnd, ptedata); }#endif return 0;}#ifdef _SELECT_SUPPORTstatic void begin_selection (PTEDATA ptedata){ ptedata->txtdoc.selection = ptedata->txtdoc.insert; ptedata->selItemY = ptedata->curItemY; ptedata->sel_x = ptedata->caret_x; ptedata->sel_y = ptedata->caret_y; SELECT_NODE(ptedata->txtdoc.selection.curNode, TRUE);}#endifstatic voidte_cursor_updown (HWND hWnd, PTEDATA ptedata, int len, BOOL bShift){ TextDoc *txtdoc = &ptedata->txtdoc; TextNode *node; TextMark *mark; int item_y; POINT pt;#ifdef _SELECT_SUPPORT TextNode *org_node; if (!bShift && txtdoc->selection.curNode) { te_unselect_all (hWnd, ptedata, TRUE); } mark = bShift ? &txtdoc->selection : &txtdoc->insert; if (bShift && !mark->curNode) { begin_selection (ptedata); } node = mark->curNode; org_node = mark->curNode; item_y = bShift ? ptedata->selItemY : ptedata->curItemY;#else mark = &txtdoc->insert; node = mark->curNode; item_y = ptedata->curItemY;#endif#ifdef _SELECT_SUPPORT if (bShift) { myGetSelPos (&pt); } else#endif myGetCaretPos (&pt); pt.y += len * ptedata->nLineHeight; pt.x = ptedata->des_caret_x; if (len == 1) { // go to next line if (pt.y >= item_y + NODE_HEIGHT(node)) { // go to next node if (BE_LAST_NODE(node)) return; item_y += NODE_HEIGHT(node); node = TXTNODE_NEXT(node); } } else if (len == -1) { if (pt.y < item_y) { // go to previous node if (BE_FIRST_NODE(node)) return; node = TXTNODE_PREV(node); item_y -= NODE_HEIGHT(node); } } else { //TODO return; } pt.y -= item_y; teOnMouseDown (hWnd, node, &pt, item_y, bShift); te_make_caret_visible (hWnd, ptedata, bShift);#ifdef _SELECT_SUPPORT if (bShift) { if(NODE_IS_SELECTED(node)) { if (node != org_node) SELECT_NODE(org_node, FALSE); } else { SELECT_NODE(node, TRUE); } if (node != org_node) REFRESH_NODE(org_node); REFRESH_NODE(node); check_caret(); }#endif}/* * te_cursor_shift : process shift keys, including left and right arrow, Home, * End keys. * Params : bShift - Whether shift key is in pressed status */ static voidte_cursor_shift (HWND hWnd, PTEDATA ptedata, int kcode, BOOL bShift){ TextDoc *txtdoc = &ptedata->txtdoc; TextNode *node, *curnode; unsigned char *pIns; int len; POINT pt; TextMark *mark;#ifdef _SELECT_SUPPORT /* unselect the selected first */ if (!bShift && txtdoc->selection.curNode) { te_unselect_all (hWnd, ptedata, TRUE); } mark = bShift ? &txtdoc->selection : &txtdoc->insert; if (bShift && !mark->curNode) { begin_selection (ptedata); }#else mark = &txtdoc->insert;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -