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

📄 textedit.c

📁 有了操作系统、TCP/IP协议栈、文件系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*** $Id: textedit.c,v 1.122 2005/02/05 03:54:33 snig Exp $**** textedit.c: text edit control**** Copyright (C) 2004 Feynman Software.** ** Current maintainer: Zhong Shuyi (zhongsy@minigui.org).**** Create date: 2004/03/01**** Note:**    the textedit control is written from scratch**    to replace the buggy medit control.****    The textedit control inherits scrollview.***//*** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//* * TODO * tab */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "common.h"#include "minigui.h"#include "gdi.h"#include "window.h"#include "ctrl/ctrlhelper.h"#include "ctrl/edit.h"#include "ctrl/textedit.h"#include "cliprect.h"#include "internals.h"#include "ctrlclass.h"#ifdef _CTRL_TEXTEDIT#include "ctrlmisc.h"#include "scrolled.h"#include "scrollview_impl.h"#include "text.h"#include "textedit_impl.h"#ifdef DT_WORDBREAK#undef DT_WORDBREAK#define DT_WORDBREAK 0#endif#ifdef _UNDO_SUPPORTstatic void teUndoBackup (TextDoc *txtoc);#endif#undef _TEXTEDIT_DEBUG//#define _TEXTEDIT_DEBUG#ifdef _TEXTEDIT_DEBUGstatic void dump_text (TextDoc *txtdoc, BOOL bSel){    list_t *me;    TextNode *node;    SIZE txtsize;    HWND hWnd = (HWND)txtdoc->fn_data;    HDC hdc;    printf ("\n\n\n\n");    printf ("------------------------------------------------------\n");    list_for_each (me, &txtdoc->queue) {        node  = list_entry (me, TextNode, list);        /*        if (scrollview_is_item_selected ((HSVITEM)node->addData)) {            printf ("sv select---<< %s\n", node->content.string);        }        */#ifdef _SELECT_SUPPORT        if (bSel && textnode_is_selected(txtdoc, node)) {            printf ("%d:\n", node->content.txtlen);            printf ("%s----->", node->content.string);        }#endif    }    hdc = GetClientDC (hWnd);    GetTabbedTextExtent(hdc, "\t", 1, &txtsize);    ReleaseDC (hdc);    printf ("tab size = %d\n", txtsize.cx);}static void print_selected (TextDoc *txtdoc){    dump_text (txtdoc, TRUE);}#endif/* ------------------------------ text document/buffer ------------------------ *//*  * set_current_node : Sets a node as the current insertion/selection node, *                    must be called when the current node is/will be changed. * Params           : newnode - the new node with insertion/selection point *                    bSel    - insertion or selection *                    bChange - Whether to call change function * Return           : TRUE on changed, FALSE otherwise. */static BOOLset_current_node (TextDoc *txtdoc, TextNode *newnode, BOOL bSel, BOOL bChange){    TextMark *mark;    TextNode *oldnode;    mark = GETMARK(bSel);    oldnode = mark->curNode;    if (newnode == oldnode)        return FALSE;    mark->curNode = newnode;    mark->pos_lnOff = 0;    /* called when the current insertion node is changed */    if (bChange && txtdoc->change_fn)        txtdoc->change_fn (txtdoc, bSel);    return TRUE;}/*  * textnode_create: creat a new text node and initialize it with text */static TextNode* textnode_create (TextDoc *txtdoc, const char *line, int len){    TextNode *newnode;    if ( !(newnode = textnode_alloc ()) )        return NULL;    /* create a new blank line */    if (!line || len < 0) len = 0;    if ( !(testr_alloc (&newnode->content, len, txtdoc->nBlockSize)) ) {        textnode_free (newnode);        return NULL;    }    testr_setstr (&newnode->content, line, len);    newnode->addData = 0;    return newnode;}/*  * textnode_destroy: destroy a text node */static void textnode_destroy (TextNode *node){    if (node) {        list_del (&node->list);        testr_free (&node->content);        textnode_free (node);    }}/*  * textdoc_free : free TextDoc nodes * Description  : only changes the status fields of a TextDoc object, does not  *                affect the properties. */static void textdoc_free (TextDoc *txtdoc){    TextNode *node;    if (!txtdoc) return;    while (!list_empty(&txtdoc->queue)) {        node = list_entry (txtdoc->queue.next, TextNode, list);        textnode_destroy (node);    }    txtdoc->insert.pos_lnOff = 0;    txtdoc->insert.curNode = NULL;#ifdef _SELECT_SUPPORT    txtdoc->selection.curNode = 0;    txtdoc->selection.pos_lnOff = 0;#endif}/* * txtAddNode : add a textnode after a specified node * params     : node - the previous text node, if NULL, the new node will be *                     inserted at the tail. */static TextNode*txtAddNode (TextDoc *txtdoc, const char*pLine, int len, TextNode *node){    TextNode *newnode;    if ( !(newnode = textnode_create (txtdoc, pLine, len)) )        return NULL;    if (node)        list_add (&newnode->list, &node->list);    else        list_add_tail (&newnode->list, &txtdoc->queue);    if (txtdoc->init_fn) txtdoc->init_fn(txtdoc, newnode, node);    return newnode;}/* * txtDelNode : deletes a text node */static void txtDelNode (TextDoc *txtdoc, TextNode *node){    /* deletes scrollview item */    if (txtdoc->del_fn)        txtdoc->del_fn(txtdoc, node);    textnode_destroy (node);}/* * textdoc_get_textlen : gets the total length of the text document */static int textdoc_get_textlen (TextDoc *txtdoc){    list_t *me;    TextNode *node;    int total_len = 0;    list_for_each (me, &txtdoc->queue) {        node = list_entry (me, TextNode, list);        total_len += node->content.txtlen;    }    return total_len;}/* * textdoc_gettext : get text string from text document */static int textdoc_gettext (TextDoc *txtdoc, int len, unsigned char *buffer){    list_t *me;    TextNode *node;    unsigned char *pch = buffer;    int total_len = 0, copy_len = 0;    if (!buffer || len <= 0)        return 0;    list_for_each (me, &txtdoc->queue) {        node = list_entry (me, TextNode, list);        copy_len = MIN(node->content.txtlen, len - total_len);        if (copy_len <= 0) break;        memcpy (pch, node->content.string, copy_len);        pch += copy_len;        total_len += copy_len;    }    *pch = '\0';    return total_len;}/*  * textdoc_settext : setting TextDoc object using a new text content and  *                   free the old one * Params          : content - new text content, if NULL, the content of the  *                             TextDoc object will not be changed; if content *                             is a null string, txtdoc content will be cleared. * TODO            : for not null-terminated text */static int textdoc_settext (TextDoc *txtdoc, const char*content){    const char *pLine, *ptmp;    if (!txtdoc || !content) return -1;    /* free the old text content */    textdoc_free (txtdoc);    ptmp = pLine = content;    if (content) {        while (*ptmp != '\0') {            if (*ptmp == txtdoc->lnsep) {                /* adds a new line, including the line seperator */                txtAddNode (txtdoc, pLine, ptmp-pLine+1, NULL);                pLine = ptmp + 1;            }            ptmp ++;        }    }    /* adds a new blank line or the last line without a line seperator */    txtAddNode (txtdoc, pLine, ptmp-pLine, NULL);    set_current_node (txtdoc, FIRSTNODE(txtdoc), FALSE, TRUE);    return 0;}static voidinsert_string (TextDoc *txtdoc, TextNode *curnode, int insert_pos,                const char *newtext, int len){    StrBuffer *strbuff = &curnode->content;    unsigned char *pLn, *pIns;    if (len > 0) {        pLn = testr_realloc (strbuff, strbuff->txtlen + len);        if (!pLn) return;        pIns = pLn + insert_pos;        memmove (pIns + len, pIns, strbuff->txtlen+1 - insert_pos);        memcpy (pIns, newtext, len);    }    else {        pIns = strbuff->string + insert_pos;        memmove (pIns + len, pIns, strbuff->txtlen+1 - insert_pos);        pLn = testr_realloc (strbuff, strbuff->txtlen + len);    }    strbuff->txtlen += len;}#ifdef _SELECT_SUPPORTstatic TextMark* get_start_mark (PTEDATA ptedata){    TextDoc *txtdoc = &ptedata->txtdoc;    if (ptedata->curItemY < ptedata->selItemY ||             (ptedata->curItemY == ptedata->selItemY &&               txtdoc->insert.pos_lnOff < txtdoc->selection.pos_lnOff) )        return &txtdoc->insert;    else        return &txtdoc->selection;}/* Gets the start and end selection points in a text node */static voidget_selection_points (PTEDATA ptedata, TextNode *node, int *pos_start, int *pos_end){    TextDoc *txtdoc = &ptedata->txtdoc;    TextMark *markStart = get_start_mark (ptedata);    TextMark *markEnd = (markStart == &txtdoc->insert) ?                           &txtdoc->selection : &txtdoc->insert;    if (node ==  txtdoc->insert.curNode || node == txtdoc->selection.curNode) {        if (txtdoc->insert.curNode == txtdoc->selection.curNode) {            *pos_start = markStart->pos_lnOff;            *pos_end = markEnd->pos_lnOff;        }        else if (node == markStart->curNode) {            *pos_start = markStart->pos_lnOff;            *pos_end = node->content.txtlen;        }        else {            *pos_start = 0;            *pos_end = markEnd->pos_lnOff;        }    }    else {        *pos_start = 0;        *pos_end = node->content.txtlen;    }}/* * delete_selection : deletes the selected texts */static int delete_selection (TextDoc *txtdoc){    int pos_start, pos_end;    int pos_start2, pos_end2;    TextNode *node, *startnode, *endnode;    TextMark *markStart, *markEnd;    HWND hWnd = (HWND)txtdoc->fn_data;    PTEDATA ptedata = (PTEDATA)GetWindowAdditionalData2 (hWnd);    markStart = get_start_mark (ptedata);    markEnd = (markStart == &txtdoc->insert) ?                           &txtdoc->selection : &txtdoc->insert;    startnode = markStart->curNode;    endnode = markEnd->curNode;    get_selection_points (ptedata, endnode, &pos_start, &pos_end);    get_selection_points (ptedata, startnode, &pos_start2, &pos_end2);    txtdoc->selection.curNode = NULL;    scrollview_freeze (hWnd, &ptedata->svdata, TRUE);    insert_string (txtdoc, endnode, pos_end, NULL, pos_start-pos_end);    if (startnode != endnode) {        while ( (node = TXTNODE_NEXT(startnode)) != endnode ) {            txtDelNode (txtdoc, node);        }        if (pos_start2 == 0) {            txtDelNode (txtdoc, startnode);            startnode = NULL;            txtdoc->insert.curNode = endnode;            txtdoc->insert.pos_lnOff = 0;            txtdoc->change_fn (txtdoc, FALSE);        }        else {            char del[1] = {127};            textdoc_insert_string_ex (txtdoc, startnode, pos_end2-1, NULL,                                       pos_start2-pos_end2+1);            textdoc_insert_string_ex_2 (txtdoc, startnode, pos_start2, del, 1);            txtdoc->insert.curNode = startnode;            endnode = NULL;        }    }    if (txtdoc->change_cont) {        txtdoc->change_cont (txtdoc, endnode);        txtdoc->change_cont (txtdoc, startnode);    }    txtdoc->selection.curNode = NULL;    scrollview_unselect_all (&ptedata->svdata);    scrollview_freeze (hWnd, &ptedata->svdata, FALSE);    return pos_start2;}#endifstatic TextNode*insert_ln_sep (TextDoc *txtdoc, TextNode *curnode, int insert_pos,                            BOOL bChRn){    StrBuffer *strbuff = &curnode->content;    TextNode *newnode;    unsigned char *pIns;    int len = bChRn ? 2 : 1;    pIns = strbuff->string + insert_pos;    newnode = txtAddNode ( txtdoc, pIns, strbuff->txtlen -                           (pIns-strbuff->string), curnode );    strbuff->txtlen = insert_pos + len; /* add a line sep */    if (*pIns == '\0') {        testr_realloc (strbuff, strbuff->txtlen);        pIns = strbuff->string + insert_pos ;    }    if (bChRn)        strncpy(pIns, CH_RN, len);    else        *pIns = txtdoc->lnsep;    *(pIns + len) = '\0';    return newnode;}/*  * textdoc_insert_string_ex :  *          inserts a text string(not including line seperator) into  *          the text buffer at the specified insertion point, or makes

⌨️ 快捷键说明

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