📄 textedit.c
字号:
rc.left = 0; rc.top = 0; rc.right = scrolled_get_contwidth(ptescr); rc.bottom = ptedata->nLineHeight; i = 0; while (1) { if (i > 0) indent = 0; DrawTextEx2 (hdc, pLine, txtlen, &rc, indent, TE_FORMAT | DT_WORDBREAK | DT_CALCRECT, &fl); if (i == line) break; pLine += fl.nr_chars; txtlen -= fl.nr_chars; i++; } ln_chars = fl.nr_chars; } else { pLine = string; ln_chars = txtlen; } if (pLine[ln_chars-1] == txtdoc->lnsep) { // add caret before line seperator ln_chars --; if (ln_chars > 0 && is_rn_sep((pLine + ln_chars - 1)) ) ln_chars --; } if (x - indent <= 0) { out_chars = 0; txtsize.cx = 0; } else out_chars = GetTabbedTextExtentPoint (hdc, pLine, ln_chars, x - indent, NULL, NULL, NULL, &txtsize); ReleaseDC (hdc);#if 0 printf ("pLine : %s\n", pLine); printf ("lnchars : %d\n", ln_chars); printf ("out chars : %d\n", out_chars); printf ("caret x = %d\n", x); printf ("txtsize.cx = %d\n", txtsize.cx); printf ("h = %d\n", h);#endif if (!bSel) { txtdoc->insert.pos_lnOff = pLine - string + out_chars; mySetCaretPos (hWnd, txtsize.cx + indent, h + ptedata->nLineAboveH); }#ifdef _SELECT_SUPPORT else { txtdoc->selection.pos_lnOff = pLine - string + out_chars; mySetSelPos (txtsize.cx + indent, h + ptedata->nLineAboveH); }#endif //scrolled_make_pos_visible (hWnd, ptescr, txtsize.cx + indent, h + ptedata->nLineHeight); return 0;}/* calculates line number of a text node, for wrap mode */static int get_line_nr (HWND hWnd, PTEDATA ptedata, TextNode *node, int indent){ RECT rc; PLOGFONT logfont = GetWindowFont(hWnd); HDC hdc; if (!node) { fprintf (stderr, "Warning: pass NULL text node to get_line_nr\n"); return 0; } if (!BE_WRAP(hWnd)) return 1; hdc = GetClientDC (hWnd); SelectFont (hdc, logfont); rc.left = 0; rc.top = 0; rc.right = scrolled_get_contwidth(ptescr); rc.bottom = logfont->size; if (ptedata->lnChar) { char *content, chln = 0; int outlen; content = node->content.string; outlen = node->content.txtlen; if (outlen > 0 && content[outlen-1] == ptedata->txtdoc.lnsep) { outlen --; if (ptedata->txtdoc.lnsep == '\n' && content[outlen-1] == '\r') outlen --; outlen ++; chln = content[outlen-1]; content[outlen-1] = ptedata->lnChar; } DrawTextEx (hdc, content, outlen, &rc, indent, TE_FORMAT | DT_WORDBREAK | DT_CALCRECT); if (chln) content[outlen-1] = chln; } else { DrawTextEx (hdc, node->content.string, node->content.txtlen, &rc, indent, TE_FORMAT | DT_WORDBREAK | DT_CALCRECT); } ReleaseDC (hdc); return (RECTH(rc)/logfont->size);}//TODOstatic int recalc_max_len (HWND hWnd ,PTEDATA ptedata){ list_t *me; TextDoc *txtdoc = &ptedata->txtdoc; SIZE txtsize; TextNode *node; HDC hdc; ptedata->maxLen = 0; ptedata->maxNode = NULL; ptedata->secLen = 0; ptedata->secNode = NULL; hdc = GetClientDC (hWnd); //SelectFont (hdc, GetWindowFont(hWnd)); list_for_each (me, &txtdoc->queue) { node = list_entry (me, TextNode, list); GetTabbedTextExtent(hdc, node->content.string, node->content.txtlen, &txtsize); if (txtsize.cx > ptedata->maxLen || ptedata->maxLen == 0) { ptedata->maxLen = txtsize.cx; ptedata->maxNode = node; } else if (txtsize.cx >= ptedata->secLen) { ptedata->secLen = txtsize.cx; ptedata->secNode = node; } } ReleaseDC (hdc); return 0;}static intrevise_max_len (HWND hWnd, PTEDATA ptedata, TextNode *node, int textlen){ if (textlen > ptedata->maxLen) { if (node != ptedata->maxNode) { ptedata->secLen = ptedata->maxLen; ptedata->secNode = ptedata->maxNode; } ptedata->maxLen = textlen; ptedata->maxNode = node; } else if (textlen > ptedata->secLen) { if (node != ptedata->maxNode) { ptedata->secLen = textlen; ptedata->secNode = node; return 0; /* no need to reset content width */ } else { ptedata->maxLen = textlen; } } else { //FIXME if (node == ptedata->maxNode) { recalc_max_len (hWnd, ptedata); return 1; } else if (node == ptedata->secNode) { recalc_max_len (hWnd, ptedata); return 0; } return 0; } /* need to reset content width */ return 1;}/* set text node line width, for non wrap mode */static int set_line_width (HWND hWnd, PTEDATA ptedata, TextNode *node, int indent){ SIZE txtsize; HDC hdc; if (!node) { fprintf (stderr, "Warning: pass NULL text node to set_line_width\n"); return -1; } if (BE_WRAP(hWnd)) return -1; hdc = GetClientDC (hWnd); SelectFont (hdc, GetWindowFont(hWnd)); GetTabbedTextExtent(hdc, node->content.string, node->content.txtlen, &txtsize); ReleaseDC (hdc); if (revise_max_len (hWnd, ptedata, node, txtsize.cx + indent) > 0) scrolled_set_cont_width (hWnd, ptescr, ptedata->maxLen + 1); return 0;}/*static int set_line_size (HWND hWnd, PTEDATA ptedata, TextNode *node){ int linenr = 1, indent; if (!node) return 0; indent = teGetLineIndent (ptedata, node); linenr = get_line_nr(hWnd, ptedata, node, indent); set_line_width (hWnd, ptedata, node, indent); return scrollview_set_item_height (hWnd, (HSVITEM)node->addData, ptedata->nLineHeight*linenr);}*//* * get_node_by_idx : Get node and y position by node index */static TextNode* get_node_by_idx (PTEDATA ptedata, int line, int *item_y){ TextDoc *txtdoc = &ptedata->txtdoc; TextNode *node; int nr = 0, ypos = 0; if (line < 0) return NULL; node = FIRSTNODE(txtdoc); while (node) { if (nr == line) break; nr ++; ypos += NODE_HEIGHT(node); node = TXTNODE_NEXT(node); } if (nr != line) return NULL; if (item_y) *item_y = ypos; return node;}static void teNodeInit (TextDoc *txtdoc, TextNode* node, TextNode *prenode){ SVITEMINFO svii; HWND hWnd = (HWND)txtdoc->fn_data; PTEDATA ptedata = (PTEDATA)GetWindowAdditionalData2(hWnd); int linenr = 1, indent; HSVITEM preitem = 0; if (!node) return; indent = teGetLineIndent (ptedata, node); linenr = get_line_nr(hWnd, ptedata, node, indent); set_line_width (hWnd, ptedata, node, indent); svii.nItemHeight = ptedata->nLineHeight * linenr; svii.addData = (DWORD)node; svii.nItem = -1; if (prenode) preitem = (HSVITEM)prenode->addData; node->addData = (DWORD) scrollview_add_item (hWnd, &ptedata->svdata, preitem, &svii, NULL);}static void teNodeDel (TextDoc *txtdoc, TextNode *node){ HWND hWnd = (HWND)txtdoc->fn_data; PTEDATA ptedata = (PTEDATA)GetWindowAdditionalData2(hWnd); scrollview_del_item (hWnd, &ptedata->svdata, 0, (HSVITEM)node->addData);}static void teNodeChange (TextDoc *txtdoc, BOOL bSel){ PTEDATA ptedata = (PTEDATA)GetWindowAdditionalData2((HWND)txtdoc->fn_data); if (!bSel) { ptedata->curItemY = scrollview_get_item_ypos (&ptedata->svdata, (HSVITEM)txtdoc->insert.curNode->addData); }#ifdef _SELECT_SUPPORT else { ptedata->selItemY = scrollview_get_item_ypos (&ptedata->svdata, (HSVITEM)txtdoc->selection.curNode->addData); }#endif }static void teChangeCont (TextDoc *txtdoc, TextNode *node){ HWND hWnd = (HWND)txtdoc->fn_data; PTEDATA ptedata = (PTEDATA)GetWindowAdditionalData2(hWnd); int indent, linenr; if (!node) return; indent = teGetLineIndent (ptedata, node); linenr = get_line_nr(hWnd, ptedata, node, indent); scrollview_set_item_height (hWnd, (HSVITEM)node->addData, ptedata->nLineHeight*linenr); set_line_width (hWnd, ptedata, node, indent);}/* * textdoc_reset : resets or initializes the properties of a textdoc to * default values */static int textdoc_reset (HWND hWnd, TextDoc *txtdoc){ txtdoc->lnsep = DEF_LINESEP; txtdoc->nDefLineSize = DEF_LINE_BUFFER_SIZE; txtdoc->nBlockSize = DEF_LINE_BLOCK_SIZE; txtdoc->init_fn = teNodeInit; txtdoc->change_fn = teNodeChange; txtdoc->change_cont = teChangeCont; txtdoc->del_fn = teNodeDel; txtdoc->fn_data = (void*)hWnd; return 0;}/* * teResetData : resets status data */static void teResetData (PTEDATA ptedata){ ptedata->des_caret_x = 0; ptedata->curItemY = 0;#ifdef _SELECT_SUPPORT ptedata->selItemY = 0;#endif ptedata->maxNode = NULL; ptedata->maxLen = 0; ptedata->secNode = NULL; ptedata->secLen = 0; ptedata->flags = 0;}/* -------------------------------------------------------------------------- */#ifdef _SELECT_SUPPORTint textdoc_copy_to_cb (PTEDATA ptedata, char *buffer, int len, BOOL bCB){ TextDoc *txtdoc = &ptedata->txtdoc; int pos_start, pos_end; TextNode *node, *endnode; TextMark *markStart, *markEnd; int org_len = len; if (!txtdoc->selection.curNode) return 0; markStart = get_start_mark (ptedata); markEnd = (markStart == &txtdoc->insert) ? &txtdoc->selection : &txtdoc->insert; node = markStart->curNode; endnode = markEnd->curNode; /* clear clipboard */ if (bCB) SetClipBoardData (CBNAME_TEXT, NULL, 0, CBOP_NORMAL); while (1) { get_selection_points (ptedata, node, &pos_start, &pos_end); if (bCB) { SetClipBoardData (CBNAME_TEXT, node->content.string + pos_start, pos_end - pos_start, CBOP_APPEND); } else if (buffer) { int output; output = MIN(len, pos_end - pos_start); strncpy (buffer, node->content.string + pos_start, output); buffer += output; len -= output; } else { len += pos_end - pos_start; } if(node != endnode) node = TXTNODE_NEXT (node); else break; } if (!bCB && !buffer && org_len == 0) return len; return org_len - len;}#endifstatic void te_make_caret_visible (HWND hWnd, PTEDATA ptedata, BOOL bSel){ POINT pt; if (!bSel) myGetCaretPos (&pt);#ifdef _SELECT_SUPPORT else myGetSelPos (&pt);#endif if (pt.y > ptescr->nContY) pt.y = (pt.y / ptedata->nLineHeight + 1) * ptedata->nLineHeight; else pt.y = (pt.y / ptedata->nLineHeight) * ptedata->nLineHeight; scrolled_make_pos_visible (hWnd, ptescr, pt.x, pt.y); if (!bSel) { mySetCaretPos (hWnd, -1, -1);//FIXME //ShowCaret (hWnd); }}/* * teSetCaretPos : sets the caret position according to the current insertion * point or sets the selection caret position according to the * current selection point of the text doc. * Description : should be called after the current insert point or the * selection point of the text document is changed */static void teSetCaretPos (HWND hWnd, PTEDATA ptedata){ TextDoc *txtdoc = &ptedata->txtdoc; TextNode *node; TextMark *mark; int h, indent, endh; HDC hdc; hdc = GetClientDC (hWnd); mark = GETMARK(txtdoc->selection.curNode); node = mark->curNode; SelectFont (hdc, GetWindowFont(hWnd));#ifdef _SELECT_SUPPORT if (txtdoc->selection.curNode) h = ptedata->selItemY; else#endif h = ptedata->curItemY; indent = teGetLineIndent (ptedata, node); if (BE_WRAP(hWnd)) { RECT rc; int w; SIZE txtsize = {0, 0}; int txtlen, linenr, lineidx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -