📄 textedit.c
字号:
*/
lineidx = 0;
while (1) {
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 void
teOnMouseDown (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_SUPPORT
static 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 int
te_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 int
TE_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);
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_SUPPORT
static 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);
}
#endif
static void
te_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 void
te_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 + -