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

📄 textedit.c

📁 这是ARM嵌入式系统的实验教程中的MINIGUI的实验源代码!
💻 C
📖 第 1 页 / 共 5 页
字号:
    }


    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);
}

//TODO
static 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 int
revise_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_SUPPORT
int 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 */
    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 {
            int output;
            output = MIN(len, pos_end - pos_start);
            strncpy (buffer, node->content.string + pos_start, output);
            buffer += output;
            len -= output;
        }
        if(node != endnode)
            node = TXTNODE_NEXT (node);
        else
            break;
    }

    return org_len - len;
}
#endif

static 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);
        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;
        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 --;

⌨️ 快捷键说明

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