⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 textedit.c

📁 有了操作系统、TCP/IP协议栈、文件系统
💻 C
📖 第 1 页 / 共 5 页
字号:
 *          some special operations (inserts line sep, del, bs, ...) * params : enode      - the specified node to operate on *          insert_pos - the designed insert position *          newtext    - text to insert *          len        - len of text to insert or remove */static inttextdoc_insert_string_ex (TextDoc *txtdoc, TextNode *enode, int insert_pos,                           const char* newtext, int len){    HWND hWnd = (HWND)txtdoc->fn_data;    TextNode *curnode, *newnode;    StrBuffer *strbuff;    unsigned char *pIns;#ifdef _UNDO_SUPPORT    //teUndoBackup (txtdoc);#endif#ifdef _SELECT_SUPPORT    if (!enode && txtdoc->selection.curNode) {        insert_pos = delete_selection (txtdoc);        if (len == 1 && (*newtext == '\b' || *newtext == 127) )            return insert_pos;        else {            txtdoc->insert.pos_lnOff = insert_pos;        }    }#endif    if (!enode) { //operates on the current insertion point        curnode = txtdoc->insert.curNode;        insert_pos = txtdoc->insert.pos_lnOff;    }    else {        curnode = enode;    }    strbuff = &curnode->content;    pIns = strbuff->string + insert_pos;    if ( len == 1 || (len == 2 && strcmp(newtext, CH_RN) == 0) ) {        if ( *newtext == txtdoc->lnsep || (strncmp(newtext, CH_RN, 2) == 0) ) {            /* add a new line */            newnode = insert_ln_sep (txtdoc, curnode,                                              insert_pos, len == 2);            if (!enode) {                txtdoc->insert.curNode = newnode;                insert_pos = 0;            }            return insert_pos;        }        /* len == 1, other cases */        switch (*newtext) {        case '\b':  //BS            if (pIns == strbuff->string) { //line head                TextNode *node;                if (BE_FIRST_NODE(curnode))                    return insert_pos;                node = TXTNODE_PREV(curnode);                /* adds the previous line at the beginning of the current line */                insert_pos += textdoc_insert_string_ex ( txtdoc, enode, insert_pos,                                        node->content.string, node->content.txtlen-1 );                /* deletes the previous line */                txtDelNode (txtdoc, node);                txtdoc->change_fn (txtdoc, FALSE);                return insert_pos;            }            len = - CHLENPREV(strbuff->string, pIns);            break;        case 127: //DEL            if (*pIns == '\0')                return insert_pos;            if ( *pIns == txtdoc->lnsep || is_rn_sep(pIns) ) {                TextNode *node = TXTNODE_NEXT(curnode);                int oldpos = insert_pos;                if (node->content.string[0] != txtdoc->lnsep &&                                 !is_rn_sep(node->content.string)) {                    *pIns = '\0';                    curnode->content.txtlen = pIns - curnode->content.string;                    textdoc_insert_string_ex ( txtdoc, enode, insert_pos,                                     node->content.string, node->content.txtlen );                    insert_pos = oldpos;                }                txtDelNode (txtdoc, node);                return insert_pos;            }            else {                int chlen = CHLENNEXT( pIns, (curnode->content.txtlen +                                              strbuff->string - pIns) );                pIns += chlen;                insert_pos += chlen;                len = -chlen;            }            break;        }    }    insert_string (txtdoc, curnode, insert_pos, newtext, len);    insert_pos += len;    return insert_pos;}/* * textdoc_insert_text : insert a multi-line text at the insertion point */static inttextdoc_insert_text (TextDoc *txtdoc, const char* newtext, int len){    const char *pLine, *ptmp;    TextNode *node, *newnode, *nextnode;    int leftlen = len;    if (!txtdoc || !newtext || len < 0) return -1;    pLine = ptmp = newtext;    /* insert first strings */    while (*ptmp != txtdoc->lnsep && *ptmp != '\0' && leftlen > 0) {        ptmp ++;        leftlen --;    }    textdoc_insert_string (txtdoc, pLine, ptmp-pLine);    if (*ptmp == '\0' || leftlen <= 0)        return 0;    node = txtdoc->insert.curNode;    /* make next node */    if (ptmp > pLine  && is_rn_sep(ptmp - 1)) {        textdoc_insert_string (txtdoc, CH_RN, 2);    }    else {        textdoc_insert_string (txtdoc, &txtdoc->lnsep, 1);    }    ptmp ++;    leftlen --;    pLine = ptmp;    nextnode = TXTNODE_NEXT (node);    /* insert lines */    newnode = node;    while (leftlen > 0 && *ptmp != '\0') {        if (*ptmp == txtdoc->lnsep) {            newnode = txtAddNode (txtdoc, pLine, ptmp-pLine+1, newnode);            pLine = ptmp + 1;        }        ptmp ++;        leftlen --;    }#ifdef _SELECT_SUPPORT    txtdoc->selection.curNode =NULL;    txtdoc->selection.pos_lnOff = 0;#endif    /* insert last strings */    //FIXME    if (!nextnode) {        fprintf (stderr, "Warning : nextnode is NULL!\n");        //set_current_node (txtdoc, LASTNODE(txtdoc), FALSE, TRUE);    }    else {        set_current_node (txtdoc, nextnode, FALSE, TRUE);        textdoc_insert_string (txtdoc, pLine, ptmp-pLine);    }    return 0;}/* ---------------------------------------------------------------------------- */#ifdef _TITLE_SUPPORTstatic int teGetTitleIndent (HWND hWnd, PTEDATA ptedata, HDC hdc){    SIZE txtsize = {0, 0};    if (ptedata->title)        GetTextExtent(hdc, ptedata->title, strlen(ptedata->title), &txtsize);        return txtsize.cx;}#endif/* paint textedit base lines */static void tePaint(HWND hWnd, HDC hdc, RECT *rcDraw){    RECT *rc = rcDraw;    PTEDATA ptedata;    int h, indent = 0;    ptedata = (PTEDATA)GetWindowAdditionalData2(hWnd);    h = ptedata->nLineHeight - 1;    if (GetWindowStyle(hWnd) & ES_BASELINE) {        SetPenColor (hdc, GetWindowElementColorEx (hWnd, FGC_CONTROL_NORMAL));        while (h < RECTHP(rc)) {#ifdef _TITLE_SUPPORT            indent = (h == ptedata->nLineHeight - 1) ? ptedata->titleIndent : 0;#endif            DrawHDotLine (hdc, rc->left + indent, rc->top+h, RECTWP(rc)-indent);            h += ptedata->nLineHeight;        }    }}static void setup_dc (HWND hWnd, HDC hdc, BOOL bSel){    if (!bSel) {        SetBkMode (hdc, BM_TRANSPARENT);        SetTextColor (hdc, GetWindowElementColorEx (hWnd, GetWindowStyle(hWnd)&WS_DISABLED?                            FGC_CONTROL_DISABLED:FGC_CONTROL_NORMAL));    }    else {        SetBkMode (hdc, BM_OPAQUE);        SetBkColor (hdc, GetWindowElementColorEx (hWnd, BKC_HILIGHT_NORMAL));        SetTextColor (hdc, GetWindowElementColorEx (hWnd, FGC_HILIGHT_NORMAL));    }}/*  * teDrawItem : draw text node/item, including multi lines in wrap mode */static void teDrawItem (HWND hWnd, HSVITEM hsvi, HDC hdc, RECT *rcDraw){    RECT rcTxt = *rcDraw;    TextNode *node;    char *content;    int txtlen, outlen, indent;    UINT format;    PTEDATA ptedata;    TextDoc *txtdoc;#ifdef _SELECT_SUPPORT    int i, pos_start, pos_end, outchars, line_nr, outw, selout = 0;    DTFIRSTLINE fl;#endif    unsigned char chln = 0;    ptedata = (PTEDATA)GetWindowAdditionalData2(hWnd);    txtdoc = &ptedata->txtdoc;    node =  (TextNode*) scrollview_get_item_adddata(hsvi);    content = node->content.string;    txtlen = node->content.txtlen;    indent = teGetLineIndent (ptedata, node);    if (txtlen <= 0 && indent <= 0)        return;    setup_dc (hWnd, hdc, FALSE);    format = TE_FORMAT;    if (BE_WRAP(hWnd))        format |= DT_WORDBREAK;    SetTextAboveLineExtra (hdc, ptedata->nLineAboveH);    SetTextBellowLineExtra (hdc, ptedata->nLineBaseH);#ifdef _TITLE_SUPPORT    /* draw title */    if (ptedata->title && indent > 0)        DrawText (hdc, ptedata->title, strlen(ptedata->title), &rcTxt, format);#endif    outlen = txtlen;    if (outlen > 0 && content[outlen-1] == txtdoc->lnsep) {        outlen --;        if (txtdoc->lnsep == '\n' && content[outlen-1] == '\r')            outlen --;        if (ptedata->lnChar) {            outlen ++;            chln = content[outlen-1];            content[outlen-1] = ptedata->lnChar;        }    }    /* draw not selected node line text */#ifdef _SELECT_SUPPORT    if (!textnode_is_selected(txtdoc, node)) {        DrawTextEx (hdc, content, outlen, &rcTxt, indent, format);        if (chln)            content[outlen-1] = chln;        return;    }    /* draw selected node */    get_selection_points (ptedata, node, &pos_start, &pos_end);    line_nr = RECTH(rcTxt) / ptedata->nLineHeight;    for (i = 0; i < line_nr; i++) {        int startx, starty;        if (i > 0) indent = 0;        /* calc line info */        DrawTextEx2(hdc, content, outlen, &rcTxt, indent, format, &fl);        startx = rcTxt.left;        starty = rcTxt.top;        outw = indent;        outchars = 0;        if (pos_start > 0) { //first: not selected section            setup_dc (hWnd, hdc, FALSE);            outchars = MIN(pos_start,fl.nr_chars);            outw += TabbedTextOutLen (hdc, startx + outw, starty, content, outchars);            content += outchars;        }        if (pos_start < fl.nr_chars && pos_end > 0) { //second: selected section            outchars = MIN(pos_end, fl.nr_chars) -  MAX(pos_start,0);            if (!ptedata->drawSelected) {                setup_dc (hWnd, hdc, TRUE);                outw += TabbedTextOutLen (hdc, startx + outw, starty, content, outchars);            }            else {                SetBkMode (hdc, BM_OPAQUE);                outw += ptedata->drawSelected(hWnd, hdc, startx+outw, starty, content, outchars, selout);            }            content += outchars;            selout += outchars;        }        if (pos_end < fl.nr_chars) { //third: not selected section            setup_dc (hWnd, hdc, FALSE);            outchars = fl.nr_chars - MAX(pos_end, 0);            outw += TabbedTextOutLen (hdc, startx + outw, starty, content, outchars);            content += outchars;        }        pos_start -= fl.nr_chars;        pos_end -= fl.nr_chars;        outlen -= fl.nr_chars;        rcTxt.top += ptedata->nLineHeight;    }#else    DrawTextEx (hdc, content, outlen, &rcTxt, indent, format);#endif    if (chln)        content[outlen-1] = chln;}/*static void teDestroyItem (HWND hWnd, HSVITEM hsvi){    TextNode *node = (TextNode*)scrollview_get_item_adddata(hsvi);    textnode_destroy (node);}*//* --------------------------- size and position calculation ---------------- */static int get_caret_width (HWND hWnd, PTEDATA ptedata){    if (ptedata->caretShape == ED_CARETSHAPE_LINE) {        return 1;    }    else if (ptedata->caretShape == ED_CARETSHAPE_BLOCK) {        TextDoc *txtdoc = &ptedata->txtdoc;        TextNode *node = txtdoc->insert.curNode;        char *pIns = node->content.string + txtdoc->insert.pos_lnOff;        int chlen = CHLENNEXT(pIns, node->content.txtlen - txtdoc->insert.pos_lnOff);        int width = GetWindowFont(hWnd)->size;        if (chlen == 0) {            if (ptedata->getCaretWidth) {                int cw = ptedata->getCaretWidth (hWnd, width);                if (cw > 0) width = cw;            }        }        else {            SIZE chsize = {0, 0};            HDC hdc = GetClientDC (hWnd);            GetTextExtent (hdc, pIns, chlen, &chsize);            ReleaseDC (hdc);            if (chsize.cx > 0)                width = chsize.cx;        }        return width;    }    return 1;}/* sets the current caret position in the virtual content window */static void mySetCaretPos (HWND hWnd, int x, int y){    PTEDATA ptedata = (PTEDATA)GetWindowAdditionalData2 (hWnd);    //no change, should return?/*    if ( (x < 0 || x == ptedata->caret_x) && (y < 0 || y == ptedata->caret_y) )        return;*/    if (x >= 0)       ptedata->caret_x = x;    else       x = ptedata->caret_x;    if (y >= 0)       ptedata->caret_y = y;    else       y = ptedata->caret_y;    if (scrolled_content_to_visible (ptescr, &x, &y) < 0) {        HideCaret (hWnd);    }    else {        scrolled_visible_to_window (ptescr, &x, &y);        SetCaretPos (hWnd, x, y);        ChangeCaretSize (hWnd, get_caret_width(hWnd, ptedata),                          ptedata->nLineHeight - ptedata->nLineAboveH);        if ( (ptedata->flags & TEST_FOCUSED) &&             !(ptedata->flags & TEST_NOCARET) #ifdef _SELECT_SUPPORT             && !(ptedata->txtdoc.selection.curNode)#endif           )        {            ActiveCaret (hWnd);            ShowCaret (hWnd);        }    }}static void textedit_set_svlist (HWND hWnd, PSCRDATA pscrdata, BOOL visChanged){    PTEDATA ptedata = (PTEDATA)GetWindowAdditionalData2 (hWnd);    /* reset caret pos in the real window */    if (ptedata->flags & TEST_FOCUSED)        mySetCaretPos (hWnd, -1, -1);    //FIXME: should be ScrollWindow ?    //InvalidateRect (hWnd, NULL, TRUE);    scrollview_set_svlist (hWnd, pscrdata, visChanged);}/* * set_caret_pos : Sets the caret/selection position in a node according to *                 x,y values */static intset_caret_pos (HWND hWnd, PTEDATA ptedata, TextNode *node, int x, int y, BOOL bSel){    TextDoc *txtdoc = &ptedata->txtdoc;    const unsigned char *string = node->content.string;    const unsigned char *pLine = string;    int txtlen = node->content.txtlen;    int line, indent, h = 0, out_chars, ln_chars;    RECT rc;    SIZE txtsize;    DTFIRSTLINE fl;    HDC hdc;    indent = teGetLineIndent (ptedata, node);    line = y / ptedata->nLineHeight;    if (!bSel)        h = ptedata->curItemY + line * ptedata->nLineHeight;#ifdef _SELECT_SUPPORT    else        h = ptedata->selItemY + line * ptedata->nLineHeight;#endif    if (txtlen == 0 || string[0] == txtdoc->lnsep || is_rn_sep(string)) {        if (!bSel) {            txtdoc->insert.pos_lnOff = 0;            mySetCaretPos (hWnd, 0 + indent, h + ptedata->nLineAboveH);        }#ifdef _SELECT_SUPPORT        else {            txtdoc->selection.pos_lnOff = 0;            mySetSelPos (0 + indent, h + ptedata->nLineAboveH);        }#endif        return 0;    }    //FIXME    hdc = GetClientDC (hWnd);    if (NODE_LINENR(node) > 1) {  /* multi line case */        int i = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -