/blender-2.63a/source/blender/blenkernel/intern/text.c
C | 3279 lines | 2436 code | 621 blank | 222 comment | 647 complexity | ffea1e1e393d3ea7d5ded6b05f2fac4a MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, BSD-3-Clause, LGPL-3.0, BSD-2-Clause, Apache-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
- /** \file blender/blenkernel/intern/text.c
- * \ingroup bke
- */
- #include <stdlib.h> /* abort */
- #include <string.h> /* strstr */
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <wchar.h>
- #include <wctype.h>
- #include "MEM_guardedalloc.h"
- #include "BLI_path_util.h"
- #include "BLI_string.h"
- #include "BLI_string_cursor_utf8.h"
- #include "BLI_string_utf8.h"
- #include "BLI_listbase.h"
- #include "BLI_utildefines.h"
- #include "BLI_fileops.h"
- #include "DNA_constraint_types.h"
- #include "DNA_controller_types.h"
- #include "DNA_scene_types.h"
- #include "DNA_screen_types.h"
- #include "DNA_space_types.h"
- #include "DNA_text_types.h"
- #include "DNA_userdef_types.h"
- #include "DNA_object_types.h"
- #include "BKE_depsgraph.h"
- #include "BKE_global.h"
- #include "BKE_library.h"
- #include "BKE_main.h"
- #include "BKE_text.h"
- #ifdef WITH_PYTHON
- #include "BPY_extern.h"
- #endif
- /*
- * How Texts should work
- * --
- * A text should relate to a file as follows -
- * (Text *)->name should be the place where the
- * file will or has been saved.
- *
- * (Text *)->flags has the following bits
- * TXT_ISDIRTY - should always be set if the file in mem. differs from
- * the file on disk, or if there is no file on disk.
- * TXT_ISMEM - should always be set if the Text has not been mapped to
- * a file, in which case (Text *)->name may be NULL or garbage.
- * TXT_ISEXT - should always be set if the Text is not to be written into
- * the .blend
- * TXT_ISSCRIPT - should be set if the user has designated the text
- * as a script. (NEW: this was unused, but now it is needed by
- * space handler script links (see header_view3d.c, for example)
- *
- * ->>> see also: /makesdna/DNA_text_types.h
- *
- * Display
- * --
- * The st->top determines at what line the top of the text is displayed.
- * If the user moves the cursor the st containing that cursor should
- * be popped ... other st's retain their own top location.
- *
- * Markers
- * --
- * The mrk->flags define the behavior and relationships between markers. The
- * upper two bytes are used to hold a group ID, the lower two are normal flags. If
- * TMARK_EDITALL is set the group ID defines which other markers should be edited.
- *
- * The mrk->clr field is used to visually group markers where the flags may not
- * match. A template system, for example, may allow editing of repeating tokens
- * (in one group) but include other marked positions (in another group) all in the
- * same template with the same color.
- *
- * Undo
- * --
- * Undo/Redo works by storing
- * events in a queue, and a pointer
- * to the current position in the
- * queue...
- *
- * Events are stored using an
- * arbitrary op-code system
- * to keep track of
- * a) the two cursors (normal and selected)
- * b) input (visible and control (ie backspace))
- *
- * input data is stored as its
- * ASCII value, the opcodes are
- * then selected to not conflict.
- *
- * opcodes with data in between are
- * written at the beginning and end
- * of the data to allow undo and redo
- * to simply check the code at the current
- * undo position
- *
- */
- /***/
- static void txt_pop_first(Text *text);
- static void txt_pop_last(Text *text);
- static void txt_undo_add_op(Text *text, int op);
- static void txt_undo_add_block(Text *text, int op, const char *buf);
- static void txt_delete_line(Text *text, TextLine *line);
- static void txt_delete_sel (Text *text);
- static void txt_make_dirty (Text *text);
- /***/
- static unsigned char undoing;
- /* allow to switch off undoing externally */
- void txt_set_undostate(int u)
- {
- undoing = u;
- }
- int txt_get_undostate(void)
- {
- return undoing;
- }
- static void init_undo_text(Text *text)
- {
- text->undo_pos= -1;
- text->undo_len= TXT_INIT_UNDO;
- text->undo_buf= MEM_mallocN(text->undo_len, "undo buf");
- }
- void free_text(Text *text)
- {
- TextLine *tmp;
- for (tmp= text->lines.first; tmp; tmp= tmp->next) {
- MEM_freeN(tmp->line);
- if (tmp->format)
- MEM_freeN(tmp->format);
- }
-
- BLI_freelistN(&text->lines);
- BLI_freelistN(&text->markers);
- if (text->name) MEM_freeN(text->name);
- MEM_freeN(text->undo_buf);
- #ifdef WITH_PYTHON
- if (text->compiled) BPY_text_free_code(text);
- #endif
- }
- Text *add_empty_text(const char *name)
- {
- Main *bmain= G.main;
- Text *ta;
- TextLine *tmp;
-
- ta= alloc_libblock(&bmain->text, ID_TXT, name);
- ta->id.us= 1;
-
- ta->name= NULL;
- init_undo_text(ta);
- ta->nlines=1;
- ta->flags= TXT_ISDIRTY | TXT_ISMEM;
- if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE)==0)
- ta->flags |= TXT_TABSTOSPACES;
- ta->lines.first= ta->lines.last= NULL;
- ta->markers.first= ta->markers.last= NULL;
- tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
- tmp->line= (char*) MEM_mallocN(1, "textline_string");
- tmp->format= NULL;
-
- tmp->line[0]=0;
- tmp->len= 0;
-
- tmp->next= NULL;
- tmp->prev= NULL;
-
- BLI_addhead(&ta->lines, tmp);
-
- ta->curl= ta->lines.first;
- ta->curc= 0;
- ta->sell= ta->lines.first;
- ta->selc= 0;
- return ta;
- }
- /* this function replaces extended ascii characters */
- /* to a valid utf-8 sequences */
- int txt_extended_ascii_as_utf8(char **str)
- {
- int bad_char, added= 0, i= 0;
- int length = strlen(*str);
- while ((*str)[i]) {
- if ((bad_char= BLI_utf8_invalid_byte(*str+i, length-i)) == -1)
- break;
- added++;
- i+= bad_char + 1;
- }
-
- if (added != 0) {
- char *newstr = MEM_mallocN(length+added+1, "text_line");
- int mi = 0;
- i= 0;
-
- while ((*str)[i]) {
- if ((bad_char= BLI_utf8_invalid_byte((*str)+i, length-i)) == -1) {
- memcpy(newstr+mi, (*str)+i, length - i + 1);
- break;
- }
-
- memcpy(newstr+mi, (*str)+i, bad_char);
- BLI_str_utf8_from_unicode((*str)[i+bad_char], newstr+mi+bad_char);
- i+= bad_char+1;
- mi+= bad_char+2;
- }
- newstr[length+added] = '\0';
- MEM_freeN(*str);
- *str = newstr;
- }
-
- return added;
- }
- // this function removes any control characters from
- // a textline and fixes invalid utf-8 sequences
- static void cleanup_textline(TextLine * tl)
- {
- int i;
- for (i = 0; i < tl->len; i++ ) {
- if (tl->line[i] < ' ' && tl->line[i] != '\t') {
- memmove(tl->line + i, tl->line + i + 1, tl->len - i);
- tl->len--;
- i--;
- }
- }
- tl->len+= txt_extended_ascii_as_utf8(&tl->line);
- }
- int reopen_text(Text *text)
- {
- FILE *fp;
- int i, llen, len;
- unsigned char *buffer;
- TextLine *tmp;
- char str[FILE_MAX];
- struct stat st;
- if (!text || !text->name) return 0;
-
- BLI_strncpy(str, text->name, FILE_MAX);
- BLI_path_abs(str, G.main->name);
-
- fp= BLI_fopen(str, "r");
- if (fp==NULL) return 0;
- /* free memory: */
- for (tmp= text->lines.first; tmp; tmp= tmp->next) {
- MEM_freeN(tmp->line);
- if (tmp->format) MEM_freeN(tmp->format);
- }
-
- BLI_freelistN(&text->lines);
- text->lines.first= text->lines.last= NULL;
- text->curl= text->sell= NULL;
- /* clear undo buffer */
- MEM_freeN(text->undo_buf);
- init_undo_text(text);
-
- fseek(fp, 0L, SEEK_END);
- len= ftell(fp);
- fseek(fp, 0L, SEEK_SET);
- text->undo_pos= -1;
-
- buffer= MEM_mallocN(len, "text_buffer");
- // under windows fread can return less then len bytes because
- // of CR stripping
- len = fread(buffer, 1, len, fp);
- fclose(fp);
- stat(str, &st);
- text->mtime= st.st_mtime;
-
- text->nlines=0;
- llen=0;
- for (i=0; i<len; i++) {
- if (buffer[i]=='\n') {
- tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
- tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
- tmp->format= NULL;
-
- if (llen) memcpy(tmp->line, &buffer[i-llen], llen);
- tmp->line[llen]=0;
- tmp->len= llen;
-
- cleanup_textline(tmp);
- BLI_addtail(&text->lines, tmp);
- text->nlines++;
-
- llen=0;
- continue;
- }
- llen++;
- }
- if (llen!=0 || text->nlines==0) {
- tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
- tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
- tmp->format= NULL;
-
- if (llen) memcpy(tmp->line, &buffer[i-llen], llen);
- tmp->line[llen]=0;
- tmp->len= llen;
-
- cleanup_textline(tmp);
- BLI_addtail(&text->lines, tmp);
- text->nlines++;
- }
-
- text->curl= text->sell= text->lines.first;
- text->curc= text->selc= 0;
-
- MEM_freeN(buffer);
- return 1;
- }
- Text *add_text(const char *file, const char *relpath)
- {
- Main *bmain= G.main;
- FILE *fp;
- int i, llen, len;
- unsigned char *buffer;
- TextLine *tmp;
- Text *ta;
- char str[FILE_MAX];
- struct stat st;
- BLI_strncpy(str, file, FILE_MAX);
- if (relpath) /* can be NULL (bg mode) */
- BLI_path_abs(str, relpath);
-
- fp= BLI_fopen(str, "r");
- if (fp==NULL) return NULL;
-
- ta= alloc_libblock(&bmain->text, ID_TXT, BLI_path_basename(str));
- ta->id.us= 1;
- ta->lines.first= ta->lines.last= NULL;
- ta->markers.first= ta->markers.last= NULL;
- ta->curl= ta->sell= NULL;
- if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE)==0)
- ta->flags= TXT_TABSTOSPACES;
- fseek(fp, 0L, SEEK_END);
- len= ftell(fp);
- fseek(fp, 0L, SEEK_SET);
- ta->name= MEM_mallocN(strlen(file)+1, "text_name");
- strcpy(ta->name, file);
- init_undo_text(ta);
-
- buffer= MEM_mallocN(len, "text_buffer");
- // under windows fread can return less then len bytes because
- // of CR stripping
- len = fread(buffer, 1, len, fp);
- fclose(fp);
- stat(str, &st);
- ta->mtime= st.st_mtime;
-
- ta->nlines=0;
- llen=0;
- for (i=0; i<len; i++) {
- if (buffer[i]=='\n') {
- tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
- tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
- tmp->format= NULL;
-
- if (llen) memcpy(tmp->line, &buffer[i-llen], llen);
- tmp->line[llen]=0;
- tmp->len= llen;
-
- cleanup_textline(tmp);
- BLI_addtail(&ta->lines, tmp);
- ta->nlines++;
-
- llen=0;
- continue;
- }
- llen++;
- }
- /* create new line in cases:
- * - rest of line (if last line in file hasn't got \n terminator).
- * in this case content of such line would be used to fill text line buffer
- * - file is empty. in this case new line is needed to start editing from.
- * - last characted in buffer is \n. in this case new line is needed to
- * deal with newline at end of file. (see [#28087]) (sergey) */
- if (llen!=0 || ta->nlines==0 || buffer[len-1]=='\n') {
- tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
- tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
- tmp->format= NULL;
-
- if (llen) memcpy(tmp->line, &buffer[i-llen], llen);
- tmp->line[llen]=0;
- tmp->len= llen;
-
- cleanup_textline(tmp);
- BLI_addtail(&ta->lines, tmp);
- ta->nlines++;
- }
-
- ta->curl= ta->sell= ta->lines.first;
- ta->curc= ta->selc= 0;
-
- MEM_freeN(buffer);
- return ta;
- }
- Text *copy_text(Text *ta)
- {
- Text *tan;
- TextLine *line, *tmp;
-
- tan= copy_libblock(&ta->id);
-
- /* file name can be NULL */
- if (ta->name) {
- tan->name= MEM_mallocN(strlen(ta->name)+1, "text_name");
- strcpy(tan->name, ta->name);
- }
- else {
- tan->name= NULL;
- }
- tan->flags = ta->flags | TXT_ISDIRTY;
-
- tan->lines.first= tan->lines.last= NULL;
- tan->markers.first= tan->markers.last= NULL;
- tan->curl= tan->sell= NULL;
-
- tan->nlines= ta->nlines;
- line= ta->lines.first;
- /* Walk down, reconstructing */
- while (line) {
- tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
- tmp->line= MEM_mallocN(line->len+1, "textline_string");
- tmp->format= NULL;
-
- strcpy(tmp->line, line->line);
- tmp->len= line->len;
-
- BLI_addtail(&tan->lines, tmp);
-
- line= line->next;
- }
- tan->curl= tan->sell= tan->lines.first;
- tan->curc= tan->selc= 0;
- init_undo_text(tan);
- return tan;
- }
- void unlink_text(Main *bmain, Text *text)
- {
- bScreen *scr;
- ScrArea *area;
- SpaceLink *sl;
- Object *ob;
- bController *cont;
- bConstraint *con;
- short update;
- for (ob=bmain->object.first; ob; ob=ob->id.next) {
- /* game controllers */
- for (cont=ob->controllers.first; cont; cont=cont->next) {
- if (cont->type==CONT_PYTHON) {
- bPythonCont *pc;
-
- pc= cont->data;
- if (pc->text==text) pc->text= NULL;
- }
- }
- /* pyconstraints */
- update = 0;
- if (ob->type==OB_ARMATURE && ob->pose) {
- bPoseChannel *pchan;
- for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- for (con = pchan->constraints.first; con; con=con->next) {
- if (con->type==CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *data = con->data;
- if (data->text==text) data->text = NULL;
- update = 1;
-
- }
- }
- }
- }
- for (con = ob->constraints.first; con; con=con->next) {
- if (con->type==CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *data = con->data;
- if (data->text==text) data->text = NULL;
- update = 1;
- }
- }
-
- if (update)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
- /* pynodes */
- // XXX nodeDynamicUnlinkText(&text->id);
-
- /* text space */
- for (scr= bmain->screen.first; scr; scr= scr->id.next) {
- for (area= scr->areabase.first; area; area= area->next) {
- for (sl= area->spacedata.first; sl; sl= sl->next) {
- if (sl->spacetype==SPACE_TEXT) {
- SpaceText *st= (SpaceText*) sl;
-
- if (st->text==text) {
- st->text= NULL;
- st->top= 0;
- }
- }
- }
- }
- }
- text->id.us= 0;
- }
- void clear_text(Text *text) /* called directly from rna */
- {
- int oldstate;
- oldstate = txt_get_undostate( );
- txt_set_undostate( 1 );
- txt_sel_all( text );
- txt_delete_sel(text);
- txt_set_undostate(oldstate);
- txt_make_dirty(text);
- }
- void write_text(Text *text, const char *str) /* called directly from rna */
- {
- int oldstate;
- oldstate = txt_get_undostate();
- txt_insert_buf(text, str);
- txt_move_eof(text, 0);
- txt_set_undostate(oldstate);
- txt_make_dirty(text);
- }
- /*****************************/
- /* Editing utility functions */
- /*****************************/
- static void make_new_line(TextLine *line, char *newline)
- {
- if (line->line) MEM_freeN(line->line);
- if (line->format) MEM_freeN(line->format);
-
- line->line= newline;
- line->len= strlen(newline);
- line->format= NULL;
- }
- static TextLine *txt_new_line(const char *str)
- {
- TextLine *tmp;
- if (!str) str= "";
-
- tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
- tmp->line= MEM_mallocN(strlen(str)+1, "textline_string");
- tmp->format= NULL;
-
- strcpy(tmp->line, str);
-
- tmp->len= strlen(str);
- tmp->next= tmp->prev= NULL;
-
- return tmp;
- }
- static TextLine *txt_new_linen(const char *str, int n)
- {
- TextLine *tmp;
- tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
- tmp->line= MEM_mallocN(n+1, "textline_string");
- tmp->format= NULL;
-
- BLI_strncpy(tmp->line, (str)? str: "", n+1);
-
- tmp->len= strlen(tmp->line);
- tmp->next= tmp->prev= NULL;
-
- return tmp;
- }
- void txt_clean_text (Text *text)
- {
- TextLine **top, **bot;
-
- if (!text) return;
-
- if (!text->lines.first) {
- if (text->lines.last) text->lines.first= text->lines.last;
- else text->lines.first= text->lines.last= txt_new_line(NULL);
- }
-
- if (!text->lines.last) text->lines.last= text->lines.first;
- top= (TextLine **) &text->lines.first;
- bot= (TextLine **) &text->lines.last;
-
- while ((*top)->prev) *top= (*top)->prev;
- while ((*bot)->next) *bot= (*bot)->next;
- if (!text->curl) {
- if (text->sell) text->curl= text->sell;
- else text->curl= text->lines.first;
- text->curc= 0;
- }
- if (!text->sell) {
- text->sell= text->curl;
- text->selc= 0;
- }
- }
- int txt_get_span (TextLine *from, TextLine *to)
- {
- int ret=0;
- TextLine *tmp= from;
- if (!to || !from) return 0;
- if (from==to) return 0;
- /* Look forwards */
- while (tmp) {
- if (tmp == to) return ret;
- ret++;
- tmp= tmp->next;
- }
- /* Look backwards */
- if (!tmp) {
- tmp= from;
- ret=0;
- while (tmp) {
- if (tmp == to) break;
- ret--;
- tmp= tmp->prev;
- }
- if (!tmp) ret=0;
- }
- return ret;
- }
- static void txt_make_dirty (Text *text)
- {
- text->flags |= TXT_ISDIRTY;
- #ifdef WITH_PYTHON
- if (text->compiled) BPY_text_free_code(text);
- #endif
- }
- /****************************/
- /* Cursor utility functions */
- /****************************/
- static void txt_curs_cur (Text *text, TextLine ***linep, int **charp)
- {
- *linep= &text->curl; *charp= &text->curc;
- }
- static void txt_curs_sel (Text *text, TextLine ***linep, int **charp)
- {
- *linep= &text->sell; *charp= &text->selc;
- }
- static void txt_curs_first (Text *text, TextLine **linep, int *charp)
- {
- if (text->curl==text->sell) {
- *linep= text->curl;
- if (text->curc<text->selc) *charp= text->curc;
- else *charp= text->selc;
- }
- else if (txt_get_span(text->lines.first, text->curl)<txt_get_span(text->lines.first, text->sell)) {
- *linep= text->curl;
- *charp= text->curc;
- }
- else {
- *linep= text->sell;
- *charp= text->selc;
- }
- }
- /*****************************/
- /* Cursor movement functions */
- /*****************************/
- int txt_utf8_offset_to_index(const char *str, int offset)
- {
- int index= 0, pos= 0;
- while (pos != offset) {
- pos += BLI_str_utf8_size(str + pos);
- index++;
- }
- return index;
- }
- int txt_utf8_index_to_offset(const char *str, int index)
- {
- int offset= 0, pos= 0;
- while (pos != index) {
- offset += BLI_str_utf8_size(str + offset);
- pos++;
- }
- return offset;
- }
- /* returns the real number of characters in string */
- /* not the same as BLI_strlen_utf8, which returns length for wide characters */
- static int txt_utf8_len(const char *src)
- {
- int len;
- for (len=0; *src; len++) {
- src += BLI_str_utf8_size(src);
- }
- return len;
- }
- void txt_move_up(Text *text, short sel)
- {
- TextLine **linep;
- int *charp;
- /* int old; */ /* UNUSED */
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
- if (!*linep) return;
- /* old= *charp; */ /* UNUSED */
- if ((*linep)->prev) {
- int index = txt_utf8_offset_to_index((*linep)->line, *charp);
- *linep= (*linep)->prev;
- if (index > txt_utf8_len((*linep)->line)) *charp= (*linep)->len;
- else *charp= txt_utf8_index_to_offset((*linep)->line, index);
-
- if (!undoing)
- txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
- }
- else {
- txt_move_bol(text, sel);
- }
- if (!sel) txt_pop_sel(text);
- }
- void txt_move_down(Text *text, short sel)
- {
- TextLine **linep;
- int *charp;
- /* int old; */ /* UNUSED */
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
- if (!*linep) return;
- /* old= *charp; */ /* UNUSED */
- if ((*linep)->next) {
- int index = txt_utf8_offset_to_index((*linep)->line, *charp);
- *linep= (*linep)->next;
- if (index > txt_utf8_len((*linep)->line)) *charp= (*linep)->len;
- else *charp= txt_utf8_index_to_offset((*linep)->line, index);
-
- if (!undoing)
- txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
- }
- else {
- txt_move_eol(text, sel);
- }
- if (!sel) txt_pop_sel(text);
- }
- void txt_move_left(Text *text, short sel)
- {
- TextLine **linep;
- int *charp, oundoing= undoing;
- int tabsize= 0, i= 0;
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
- if (!*linep) return;
- undoing= 1;
- if (*charp== 0) {
- if ((*linep)->prev) {
- txt_move_up(text, sel);
- *charp= (*linep)->len;
- }
- }
- else {
- // do nice left only if there are only spaces
- // TXT_TABSIZE hardcoded in DNA_text_types.h
- if (text->flags & TXT_TABSTOSPACES) {
- tabsize= (*charp < TXT_TABSIZE) ? *charp : TXT_TABSIZE;
-
- for (i=0; i<(*charp); i++)
- if ((*linep)->line[i] != ' ') {
- tabsize= 0;
- break;
- }
-
- // if in the middle of the space-tab
- if (tabsize && (*charp) % TXT_TABSIZE != 0)
- tabsize= ((*charp) % TXT_TABSIZE);
- }
-
- if (tabsize)
- (*charp)-= tabsize;
- else {
- const char *prev= BLI_str_prev_char_utf8((*linep)->line + *charp);
- *charp= prev - (*linep)->line;
- }
- }
- undoing= oundoing;
- if (!undoing) txt_undo_add_op(text, sel?UNDO_SLEFT:UNDO_CLEFT);
-
- if (!sel) txt_pop_sel(text);
- }
- void txt_move_right(Text *text, short sel)
- {
- TextLine **linep;
- int *charp, oundoing= undoing, do_tab= 0, i;
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
- if (!*linep) return;
- undoing= 1;
- if (*charp== (*linep)->len) {
- if ((*linep)->next) {
- txt_move_down(text, sel);
- *charp= 0;
- }
- }
- else {
- // do nice right only if there are only spaces
- // spaces hardcoded in DNA_text_types.h
- if (text->flags & TXT_TABSTOSPACES && (*linep)->line[*charp]== ' ') {
- do_tab= 1;
- for (i=0; i<*charp; i++)
- if ((*linep)->line[i]!= ' ') {
- do_tab= 0;
- break;
- }
- }
-
- if (do_tab) {
- int tabsize= (*charp) % TXT_TABSIZE + 1;
- for (i=*charp+1; (*linep)->line[i]==' ' && tabsize<TXT_TABSIZE; i++)
- tabsize++;
- (*charp)= i;
- }
- else (*charp)+= BLI_str_utf8_size((*linep)->line + *charp);
- }
-
- undoing= oundoing;
- if (!undoing) txt_undo_add_op(text, sel?UNDO_SRIGHT:UNDO_CRIGHT);
- if (!sel) txt_pop_sel(text);
- }
- void txt_jump_left(Text *text, short sel)
- {
- TextLine **linep;
- int *charp, oldc;
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
- if (!*linep) return;
- oldc = *charp;
- BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len,
- charp, STRCUR_DIR_PREV,
- STRCUR_JUMP_DELIM);
-
- if (!sel) txt_pop_sel(text);
- if (!undoing) {
- int span = txt_get_span(text->lines.first, *linep);
- txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, span, oldc, span, (unsigned short)*charp);
- }
- }
- void txt_jump_right(Text *text, short sel)
- {
- TextLine **linep;
- int *charp, oldc;
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
- if (!*linep) return;
- oldc = *charp;
-
- BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len,
- charp, STRCUR_DIR_NEXT,
- STRCUR_JUMP_DELIM);
-
- if (!sel) txt_pop_sel(text);
- if (!undoing) {
- int span = txt_get_span(text->lines.first, *linep);
- txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, span, oldc, span, (unsigned short)*charp);
- }
- }
- void txt_move_bol (Text *text, short sel)
- {
- TextLine **linep;
- int *charp, old;
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else txt_curs_cur(text, &linep, &charp);
- if (!*linep) return;
- old= *charp;
-
- *charp= 0;
- if (!sel) txt_pop_sel(text);
- if (!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
- }
- void txt_move_eol (Text *text, short sel)
- {
- TextLine **linep;
- int *charp, old;
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else txt_curs_cur(text, &linep, &charp);
- if (!*linep) return;
- old= *charp;
-
- *charp= (*linep)->len;
- if (!sel) txt_pop_sel(text);
- if (!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
- }
- void txt_move_bof (Text *text, short sel)
- {
- TextLine **linep;
- int *charp, old;
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else txt_curs_cur(text, &linep, &charp);
- if (!*linep) return;
- old= *charp;
- *linep= text->lines.first;
- *charp= 0;
- if (!sel) txt_pop_sel(text);
- if (!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
- }
- void txt_move_eof (Text *text, short sel)
- {
- TextLine **linep;
- int *charp, old;
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else txt_curs_cur(text, &linep, &charp);
- if (!*linep) return;
- old= *charp;
- *linep= text->lines.last;
- *charp= (*linep)->len;
- if (!sel) txt_pop_sel(text);
- if (!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
- }
- void txt_move_toline (Text *text, unsigned int line, short sel)
- {
- txt_move_to(text, line, 0, sel);
- }
- /* Moves to a certain byte in a line, not a certain utf8-character! */
- void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel)
- {
- TextLine **linep, *oldl;
- int *charp, oldc;
- unsigned int i;
-
- if (!text) return;
- if (sel) txt_curs_sel(text, &linep, &charp);
- else txt_curs_cur(text, &linep, &charp);
- if (!*linep) return;
- oldc= *charp;
- oldl= *linep;
-
- *linep= text->lines.first;
- for (i=0; i<line; i++) {
- if ((*linep)->next) *linep= (*linep)->next;
- else break;
- }
- if (ch>(unsigned int)((*linep)->len))
- ch= (unsigned int)((*linep)->len);
- *charp= ch;
-
- if (!sel) txt_pop_sel(text);
- if (!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
- }
- /****************************/
- /* Text selection functions */
- /****************************/
- static void txt_curs_swap (Text *text)
- {
- TextLine *tmpl;
- int tmpc;
-
- tmpl= text->curl;
- text->curl= text->sell;
- text->sell= tmpl;
-
- tmpc= text->curc;
- text->curc= text->selc;
- text->selc= tmpc;
-
- if (!undoing) txt_undo_add_op(text, UNDO_SWAP);
- }
- static void txt_pop_first (Text *text)
- {
-
- if (txt_get_span(text->curl, text->sell)<0 ||
- (text->curl==text->sell && text->curc>text->selc)) {
- txt_curs_swap(text);
- }
- if (!undoing) txt_undo_add_toop(text, UNDO_STO,
- txt_get_span(text->lines.first, text->sell),
- text->selc,
- txt_get_span(text->lines.first, text->curl),
- text->curc);
-
- txt_pop_sel(text);
- }
- static void txt_pop_last (Text *text)
- {
- if (txt_get_span(text->curl, text->sell)>0 ||
- (text->curl==text->sell && text->curc<text->selc)) {
- txt_curs_swap(text);
- }
- if (!undoing) txt_undo_add_toop(text, UNDO_STO,
- txt_get_span(text->lines.first, text->sell),
- text->selc,
- txt_get_span(text->lines.first, text->curl),
- text->curc);
-
- txt_pop_sel(text);
- }
- /* never used: CVS 1.19 */
- /* static void txt_pop_selr (Text *text) */
- void txt_pop_sel (Text *text)
- {
- text->sell= text->curl;
- text->selc= text->curc;
- }
- void txt_order_cursors(Text *text)
- {
- if (!text) return;
- if (!text->curl) return;
- if (!text->sell) return;
-
- /* Flip so text->curl is before text->sell */
- if (txt_get_span(text->curl, text->sell)<0 ||
- (text->curl==text->sell && text->curc>text->selc))
- txt_curs_swap(text);
- }
- int txt_has_sel(Text *text)
- {
- return ((text->curl!=text->sell) || (text->curc!=text->selc));
- }
- static void txt_delete_sel (Text *text)
- {
- TextLine *tmpl;
- TextMarker *mrk;
- char *buf;
- int move, lineno;
-
- if (!text) return;
- if (!text->curl) return;
- if (!text->sell) return;
- if (!txt_has_sel(text)) return;
-
- txt_order_cursors(text);
- if (!undoing) {
- buf= txt_sel_to_buf(text);
- txt_undo_add_block(text, UNDO_DBLOCK, buf);
- MEM_freeN(buf);
- }
- buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string");
-
- if (text->curl != text->sell) {
- txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0, 0);
- move= txt_get_span(text->curl, text->sell);
- }
- else {
- mrk= txt_find_marker_region(text, text->curl, text->curc, text->selc, 0, 0);
- if (mrk && (mrk->start > text->curc || mrk->end < text->selc))
- txt_clear_marker_region(text, text->curl, text->curc, text->selc, 0, 0);
- move= 0;
- }
- mrk= txt_find_marker_region(text, text->sell, text->selc-1, text->sell->len, 0, 0);
- if (mrk) {
- lineno= mrk->lineno;
- do {
- mrk->lineno -= move;
- if (mrk->start > text->curc) mrk->start -= text->selc - text->curc;
- mrk->end -= text->selc - text->curc;
- mrk= mrk->next;
- } while (mrk && mrk->lineno==lineno);
- }
- strncpy(buf, text->curl->line, text->curc);
- strcpy(buf+text->curc, text->sell->line + text->selc);
- buf[text->curc+(text->sell->len - text->selc)]=0;
- make_new_line(text->curl, buf);
-
- tmpl= text->sell;
- while (tmpl != text->curl) {
- tmpl= tmpl->prev;
- if (!tmpl) break;
-
- txt_delete_line(text, tmpl->next);
- }
-
- text->sell= text->curl;
- text->selc= text->curc;
- }
- void txt_sel_all (Text *text)
- {
- if (!text) return;
- text->curl= text->lines.first;
- text->curc= 0;
-
- text->sell= text->lines.last;
- text->selc= text->sell->len;
- }
- void txt_sel_line (Text *text)
- {
- if (!text) return;
- if (!text->curl) return;
-
- text->curc= 0;
- text->sell= text->curl;
- text->selc= text->sell->len;
- }
- /***************************/
- /* Cut and paste functions */
- /***************************/
- char *txt_to_buf (Text *text)
- {
- int length;
- TextLine *tmp, *linef, *linel;
- int charf, charl;
- char *buf;
-
- if (!text) return NULL;
- if (!text->curl) return NULL;
- if (!text->sell) return NULL;
- if (!text->lines.first) return NULL;
- linef= text->lines.first;
- charf= 0;
-
- linel= text->lines.last;
- charl= linel->len;
- if (linef == text->lines.last) {
- length= charl-charf;
- buf= MEM_mallocN(length+2, "text buffer");
-
- BLI_strncpy(buf, linef->line + charf, length+1);
- buf[length]=0;
- }
- else {
- length= linef->len - charf;
- length+= charl;
- length+= 2; /* For the 2 '\n' */
-
- tmp= linef->next;
- while (tmp && tmp!= linel) {
- length+= tmp->len+1;
- tmp= tmp->next;
- }
-
- buf= MEM_mallocN(length+1, "cut buffer");
- strncpy(buf, linef->line + charf, linef->len-charf);
- length= linef->len - charf;
-
- buf[length++]='\n';
-
- tmp= linef->next;
- while (tmp && tmp!=linel) {
- strncpy(buf+length, tmp->line, tmp->len);
- length+= tmp->len;
-
- buf[length++]='\n';
-
- tmp= tmp->next;
- }
- strncpy(buf+length, linel->line, charl);
- length+= charl;
-
- /* python compiler wants an empty end line */
- buf[length++]='\n';
- buf[length]=0;
- }
-
- return buf;
- }
- int txt_find_string(Text *text, const char *findstr, int wrap, int match_case)
- {
- TextLine *tl, *startl;
- char *s= NULL;
- if (!text || !text->curl || !text->sell) return 0;
-
- txt_order_cursors(text);
- tl= startl= text->sell;
-
- if (match_case) s= strstr(&tl->line[text->selc], findstr);
- else s= BLI_strcasestr(&tl->line[text->selc], findstr);
- while (!s) {
- tl= tl->next;
- if (!tl) {
- if (wrap)
- tl= text->lines.first;
- else
- break;
- }
- if (match_case) s= strstr(tl->line, findstr);
- else s= BLI_strcasestr(tl->line, findstr);
- if (tl==startl)
- break;
- }
-
- if (s) {
- int newl= txt_get_span(text->lines.first, tl);
- int newc= (int)(s-tl->line);
- txt_move_to(text, newl, newc, 0);
- txt_move_to(text, newl, newc + strlen(findstr), 1);
- return 1;
- }
- else
- return 0;
- }
- char *txt_sel_to_buf (Text *text)
- {
- char *buf;
- int length=0;
- TextLine *tmp, *linef, *linel;
- int charf, charl;
-
- if (!text) return NULL;
- if (!text->curl) return NULL;
- if (!text->sell) return NULL;
-
- if (text->curl==text->sell) {
- linef= linel= text->curl;
-
- if (text->curc < text->selc) {
- charf= text->curc;
- charl= text->selc;
- }
- else {
- charf= text->selc;
- charl= text->curc;
- }
- }
- else if (txt_get_span(text->curl, text->sell)<0) {
- linef= text->sell;
- linel= text->curl;
- charf= text->selc;
- charl= text->curc;
- }
- else {
- linef= text->curl;
- linel= text->sell;
-
- charf= text->curc;
- charl= text->selc;
- }
- if (linef == linel) {
- length= charl-charf;
- buf= MEM_mallocN(length+1, "sel buffer");
-
- BLI_strncpy(buf, linef->line + charf, length+1);
- }
- else {
- length+= linef->len - charf;
- length+= charl;
- length++; /* For the '\n' */
-
- tmp= linef->next;
- while (tmp && tmp!= linel) {
- length+= tmp->len+1;
- tmp= tmp->next;
- }
-
- buf= MEM_mallocN(length+1, "sel buffer");
-
- strncpy(buf, linef->line+ charf, linef->len-charf);
- length= linef->len-charf;
-
- buf[length++]='\n';
-
- tmp= linef->next;
- while (tmp && tmp!=linel) {
- strncpy(buf+length, tmp->line, tmp->len);
- length+= tmp->len;
-
- buf[length++]='\n';
-
- tmp= tmp->next;
- }
- strncpy(buf+length, linel->line, charl);
- length+= charl;
-
- buf[length]=0;
- }
- return buf;
- }
- static void txt_shift_markers(Text *text, int lineno, int count)
- {
- TextMarker *marker;
- for (marker=text->markers.first; marker; marker= marker->next)
- if (marker->lineno>=lineno) {
- marker->lineno+= count;
- }
- }
- void txt_insert_buf(Text *text, const char *in_buffer)
- {
- int l=0, u, len, lineno= -1, count= 0;
- size_t i=0, j;
- TextLine *add;
- char *buffer;
- if (!text) return;
- if (!in_buffer) return;
- txt_delete_sel(text);
-
- len= strlen(in_buffer);
- buffer= BLI_strdupn(in_buffer, len);
- len+= txt_extended_ascii_as_utf8(&buffer);
-
- if (!undoing) txt_undo_add_block(text, UNDO_IBLOCK, buffer);
- u= undoing;
- undoing= 1;
- /* Read the first line (or as close as possible */
- while (buffer[i] && buffer[i]!='\n')
- txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &i));
-
- if (buffer[i]=='\n') txt_split_curline(text);
- else { undoing = u; MEM_freeN(buffer); return; }
- i++;
- /* Read as many full lines as we can */
- lineno= txt_get_span(text->lines.first, text->curl);
- while (i<len) {
- l=0;
- while (buffer[i] && buffer[i]!='\n') {
- i++; l++;
- }
-
- if (buffer[i]=='\n') {
- add= txt_new_linen(buffer +(i-l), l);
- BLI_insertlinkbefore(&text->lines, text->curl, add);
- i++;
- count++;
- }
- else {
- if (count) {
- txt_shift_markers(text, lineno, count);
- count= 0;
- }
- for (j= i-l; j<i && j<len; )
- txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j));
- break;
- }
- }
-
- MEM_freeN(buffer);
- if (count) {
- txt_shift_markers(text, lineno, count);
- }
- undoing= u;
- }
- /******************/
- /* Undo functions */
- /******************/
- static int max_undo_test(Text *text, int x)
- {
- while (text->undo_pos+x >= text->undo_len) {
- if (text->undo_len*2 > TXT_MAX_UNDO) {
- /* XXX error("Undo limit reached, buffer cleared\n"); */
- MEM_freeN(text->undo_buf);
- init_undo_text(text);
- return 0;
- }
- else {
- void *tmp= text->undo_buf;
- text->undo_buf= MEM_callocN(text->undo_len*2, "undo buf");
- memcpy(text->undo_buf, tmp, text->undo_len);
- text->undo_len*=2;
- MEM_freeN(tmp);
- }
- }
- return 1;
- }
- static void dump_buffer(Text *text)
- {
- int i= 0;
-
- while (i++<text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]);
- }
- void txt_print_undo(Text *text)
- {
- int i= 0;
- int op;
- const char *ops;
- int linep, charp;
-
- dump_buffer(text);
-
- printf ("---< Undo Buffer >---\n");
-
- printf ("UndoPosition is %d\n", text->undo_pos);
-
- while (i<=text->undo_pos) {
- op= text->undo_buf[i];
-
- if (op==UNDO_CLEFT) {
- ops= "Cursor left";
- }
- else if (op==UNDO_CRIGHT) {
- ops= "Cursor right";
- }
- else if (op==UNDO_CUP) {
- ops= "Cursor up";
- }
- else if (op==UNDO_CDOWN) {
- ops= "Cursor down";
- }
- else if (op==UNDO_SLEFT) {
- ops= "Selection left";
- }
- else if (op==UNDO_SRIGHT) {
- ops= "Selection right";
- }
- else if (op==UNDO_SUP) {
- ops= "Selection up";
- }
- else if (op==UNDO_SDOWN) {
- ops= "Selection down";
- }
- else if (op==UNDO_STO) {
- ops= "Selection ";
- }
- else if (op==UNDO_CTO) {
- ops= "Cursor ";
- }
- else if (op==UNDO_INSERT_1) {
- ops= "Insert ascii ";
- }
- else if (op==UNDO_INSERT_2) {
- ops= "Insert 2 bytes ";
- }
- else if (op==UNDO_INSERT_3) {
- ops= "Insert 3 bytes ";
- }
- else if (op==UNDO_INSERT_4) {
- ops= "Insert unicode ";
- }
- else if (op==UNDO_BS_1) {
- ops= "Backspace for ascii ";
- }
- else if (op==UNDO_BS_2) {
- ops= "Backspace for 2 bytes ";
- }
- else if (op==UNDO_BS_3) {
- ops= "Backspace for 3 bytes ";
- }
- else if (op==UNDO_BS_4) {
- ops= "Backspace for unicode ";
- }
- else if (op==UNDO_DEL_1) {
- ops= "Delete ascii ";
- }
- else if (op==UNDO_DEL_2) {
- ops= "Delete 2 bytes ";
- }
- else if (op==UNDO_DEL_3) {
- ops= "Delete 3 bytes ";
- }
- else if (op==UNDO_DEL_4) {
- ops= "Delete unicode ";
- }
- else if (op==UNDO_SWAP) {
- ops= "Cursor swap";
- }
- else if (op==UNDO_DBLOCK) {
- ops= "Delete text block";
- }
- else if (op==UNDO_IBLOCK) {
- ops= "Insert text block";
- }
- else if (op==UNDO_INDENT) {
- ops= "Indent ";
- }
- else if (op==UNDO_UNINDENT) {
- ops= "Unindent ";
- }
- else if (op==UNDO_COMMENT) {
- ops= "Comment ";
- }
- else if (op==UNDO_UNCOMMENT) {
- ops= "Uncomment ";
- }
- else {
- ops= "Unknown";
- }
-
- printf ("Op (%o) at %d = %s", op, i, ops);
- if (op >= UNDO_INSERT_1 && op <= UNDO_DEL_4) {
- i++;
- printf (" - Char is ");
- switch (op) {
- case UNDO_INSERT_1: case UNDO_BS_1: case UNDO_DEL_1:
- printf ("%c", text->undo_buf[i]);
- i++;
- break;
- case UNDO_INSERT_2: case UNDO_BS_2: case UNDO_DEL_2:
- printf ("%c%c", text->undo_buf[i], text->undo_buf[i+1]);
- i+=2;
- break;
- case UNDO_INSERT_3: case UNDO_BS_3: case UNDO_DEL_3:
- printf ("%c%c%c", text->undo_buf[i], text->undo_buf[i+1], text->undo_buf[i+2]);
- i+=3;
- break;
- case UNDO_INSERT_4: case UNDO_BS_4: case UNDO_DEL_4: {
- unsigned int uc;
- char c[BLI_UTF8_MAX+1];
- size_t c_len;
- uc= text->undo_buf[i]; i++;
- uc= uc+(text->undo_buf[i]<<8); i++;
- uc= uc+(text->undo_buf[i]<<16); i++;
- uc= uc+(text->undo_buf[i]<<24); i++;
- c_len= BLI_str_utf8_from_unicode(uc, c);
- c[c_len]= '\0';
- puts(c);
- }
- }
- }
- else if (op==UNDO_STO || op==UNDO_CTO) {
- i++;
- charp= text->undo_buf[i]; i++;
- charp= charp+(text->undo_buf[i]<<8); i++;
- linep= text->undo_buf[i]; i++;
- linep= linep+(text->undo_buf[i]<<8); i++;
- linep= linep+(text->undo_buf[i]<<16); i++;
- linep= linep+(text->undo_buf[i]<<24); i++;
-
- printf ("to <%d, %d> ", linep, charp);
- charp= text->undo_buf[i]; i++;
- charp= charp+(text->undo_buf[i]<<8); i++;
- linep= text->undo_buf[i]; i++;
- linep= linep+(text->undo_buf[i]<<8); i++;
- linep= linep+(text->undo_buf[i]<<16); i++;
- linep= linep+(text->undo_buf[i]<<24); i++;
-
- printf ("from <%d, %d>", linep, charp);
- }
- else if (op==UNDO_DBLOCK || op==UNDO_IBLOCK) {
- i++;
- linep= text->undo_buf[i]; i++;
- linep= linep+(text->undo_buf[i]<<8); i++;
- linep= linep+(text->undo_buf[i]<<16); i++;
- linep= linep+(text->undo_buf[i]<<24); i++;
-
- printf (" (length %d) <", linep);
-
- while (linep>0) {
- putchar(text->undo_buf[i]);
- linep--; i++;
- }
-
- linep= text->undo_buf[i]; i++;
- linep= linep+(text->undo_buf[i]<<8); i++;
- linep= linep+(text->undo_buf[i]<<16); i++;
- linep= linep+(text->undo_buf[i]<<24); i++;
- printf ("> (%d)", linep);
- }
- else if (op==UNDO_INDENT || op==UNDO_UNINDENT) {
- i++;
- charp= text->undo_buf[i]; i++;
- charp= charp+(text->undo_buf[i]<<8); i++;
- linep= text->undo_buf[i]; i++;
- linep= linep+(text->undo_buf[i]<<8); i++;
- linep= linep+(text->undo_buf[i]<<16); i++;
- linep= linep+(text->undo_buf[i]<<24); i++;
-
- printf ("to <%d, %d> ", linep, charp);
- charp= text->undo_buf[i]; i++;
- charp= charp+(text->undo_buf[i]<<8); i++;
- linep= text->undo_buf[i]; i++;
- linep= linep+(text->undo_buf[i]<<8); i++;
- linep= linep+(text->undo_buf[i]<<16); i++;
- linep= linep+(text->undo_buf[i]<<24); i++;
-
- printf ("from <%d, %d>", linep, charp);
- }
-
- printf (" %d\n", i);
- i++;
- }
- }
- static void txt_undo_add_op(Text *text, int op)
- {
- if (!max_undo_test(text, 2))
- return;
-
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= op;
- text->undo_buf[text->undo_pos+1]= 0;
- }
- static void txt_undo_store_uint16(char *undo_buf, int *undo_pos, unsigned short value)
- {
- undo_buf[*undo_pos]= (value)&0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos]= (value>>8)&0xff;
- (*undo_pos)++;
- }
- static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int value)
- {
- undo_buf[*undo_pos]= (value)&0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos]= (value>>8)&0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos]= (value>>16)&0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos]= (value>>24)&0xff;
- (*undo_pos)++;
- }
- static void txt_undo_add_block(Text *text, int op, const char *buf)
- {
- unsigned int length= strlen(buf);
-
- if (!max_undo_test(text, length+11))
- return;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= op;
- text->undo_pos++;
-
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
-
- strncpy(text->undo_buf+text->undo_pos, buf, length);
- text->undo_pos+=length;
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
- text->undo_buf[text->undo_pos]= op;
-
- text->undo_buf[text->undo_pos+1]= 0;
- }
- void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc)
- {
- if (!max_undo_test(text, 15))
- return;
- if (froml==tol && fromc==toc) return;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= op;
- text->undo_pos++;
-
- txt_undo_store_uint16(text->undo_buf, &text->undo_pos, fromc);
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, froml);
- txt_undo_store_uint16(text->undo_buf, &text->undo_pos, toc);
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, tol);
-
- text->undo_buf[text->undo_pos]= op;
- text->undo_buf[text->undo_pos+1]= 0;
- }
- static void txt_undo_add_charop(Text *text, int op_start, unsigned int c)
- {
- char utf8[BLI_UTF8_MAX];
- size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8);
-
- if (!max_undo_test(text, 3 + utf8_size))
- return;
-
- text->undo_pos++;
-
- if (utf8_size < 4) {
- text->undo_buf[text->undo_pos]= op_start + utf8_size - 1;
- text->undo_pos++;
-
- for (i = 0; i < utf8_size; i++) {
- text->undo_buf[text->undo_pos]= utf8[i];
- text->undo_pos++;
- }
-
- text->undo_buf[text->undo_pos]= op_start + utf8_size - 1;
- }
- else {
- text->undo_buf[text->undo_pos]= op_start + 3;
- text->undo_pos++;
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c);
- text->undo_buf[text->undo_pos]= op_start + 3;
- }
-
- text->undo_buf[text->undo_pos+1]= 0;
- }
- static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos)
- {
- unsigned short val;
- val= undo_buf[*undo_pos]; (*undo_pos)--;
- val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--;
- return val;
- }
- static unsigned int txt_undo_read_uint32(const char *undo_buf, int *undo_pos)
- {
- unsigned int val;
- val= undo_buf[*undo_pos]; (*undo_pos)--;
- val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--;
- val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--;
- val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--;
- return val;
- }
- static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, short bytes)
- {
- unsigned int unicode;
- char utf8[BLI_UTF8_MAX+1];
-
- switch (bytes) {
- case 1: /* ascii */
- unicode = undo_buf[*undo_pos]; (*undo_pos)--;
- break;
- case 2: /* 2-byte symbol */
- utf8[2] = '\0';
- utf8[1] = undo_buf[*undo_pos]; (*undo_pos)--;
- utf8[0] = undo_buf[*undo_pos]; (*undo_pos)--;
- unicode= BLI_str_utf8_as_unicode(utf8);
- break;
- case 3: /* 3-byte symbol */
- utf8[3] = '\0';
- utf8[2] = undo_buf[*undo_pos]; (*undo_pos)--;
- utf8[1] = undo_buf[*undo_pos]; (*undo_pos)--;
- utf8[0] = undo_buf[*undo_pos]; (*undo_pos)--;
- unicode= BLI_str_utf8_as_unicode(utf8);
- break;
- case 4: /* 32-bit unicode symbol */
- unicode= txt_undo_read_uint32(undo_buf, undo_pos);
- default:
- /* should never happen */
- BLI_assert(0);
- unicode= 0;
- }
-
- return unicode;
- }
- static unsigned short txt_redo_read_uint16(const char *undo_buf, int *undo_pos)
- {
- unsigned short val;
- val = undo_buf[*undo_pos]; (*undo_pos)++;
- val = val+(undo_buf[*undo_pos]<<8); (*undo_pos)++;
- return val;
- }
- static unsigned int txt_redo_read_uint32(const char *undo_buf, int *undo_pos)
- {
- unsigned int val;
- val= undo_buf[*undo_pos]; (*undo_pos)++;
- val= val+(undo_buf[*undo_pos]<<8); (*undo_pos)++;
- val= val+(undo_buf[*undo_pos]<<16); (*undo_pos)++;
- val= val+(undo_buf[*undo_pos]<<24); (*undo_pos)++;
- return val;
- }
- static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, short bytes)
- {
- unsigned int unicode;
- char utf8[BLI_UTF8_MAX+1];
-
- switch (bytes) {
- case 1: /* ascii */
- unicode = undo_buf[*undo_pos]; (*undo_pos)++;
- break;
- case 2: /* 2-byte symbol */
- utf8[0] = undo_buf[*undo_pos]; (*undo_pos)++;
- utf8[1] = undo_buf[*undo_pos]; (*undo_pos)++;
- utf8[2] = '\0';
- unicode= BLI_str_utf8_as_unicode(utf8);
- break;
- case 3: /* 3-byte symbol */
- utf8[0] = undo_buf[*undo_pos]; (*undo_pos)++;
- utf8[1] = undo_buf[*undo_pos]; (*undo_pos)++;
- utf8[2] = undo_buf[*undo_pos]; (*undo_pos)++;
- utf8[3] = '\0';
- unicode= BLI_str_utf8_as_unicode(utf8);
- break;
- case 4: /* 32-bit unicode symbol */
- unicode= txt_undo_read_uint32(undo_buf, undo_pos);
- default:
- /* should never happen */
- BLI_assert(0);
- unicode= 0;
- }
-
- return unicode;
- }
- void txt_do_undo(Text *text)
- {
- int op= text->undo_buf[text->undo_pos];
- unsigned int linep, i;
- unsigned short charp;
- TextLine *holdl;
- int holdc, holdln;
- char *buf;
-
- if (text->undo_pos<0) {
- return;
- }
- text->undo_pos--;
- undoing= 1;
-
- switch(op) {
- case UNDO_CLEFT:
- txt_move_right(text, 0);
- break;
-
- case UNDO_CRIGHT:
- txt_move_left(text, 0);
- break;
-
- case UNDO_CUP:
- txt_move_down(text, 0);
- break;
-
- case UNDO_CDOWN:
- txt_move_up(text, 0);
- break;
- case UNDO_SLEFT:
- txt_move_right(text, 1);
- break;
- case UNDO_SRIGHT:
- txt_move_left(text, 1);
- break;
- case UNDO_SUP:
- txt_move_down(text, 1);
- break;
- case UNDO_SDOWN:
- txt_move_up(text, 1);
- break;
-
- case UNDO_CTO:
- case UNDO_STO:
- text->undo_pos--;
- text->undo_pos--;
- text->undo_pos--;
- text->undo_pos--;
-
- text->undo_pos--;
- text->undo_pos--;
-
- linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
- charp= txt_undo_read_uint16(text->undo_buf, &text->undo_pos);
-
- if (op==UNDO_CTO) {
- txt_move_toline(text, linep, 0);
- text->curc= charp;
- txt_pop_sel(text);
- }
- else {
- txt_move_toline(text, linep, 1);
- text->selc= charp;
- }
-
- text->undo_pos--;
- break;
-
- case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4:
- txt_backspace_char(text);
- text->undo_pos-= op - UNDO_INSERT_1 + 1;
- text->undo_pos--;
- break;
- case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4:
- charp = op - UNDO_BS_1 + 1;
- txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp));
- text->undo_pos--;
- break;
-
- case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4:
- charp = op - UNDO_DEL_1 + 1;
- txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp));
- txt_move_left(text, 0);
- text->undo_pos--;
- break;
- case UNDO_SWAP:
- txt_curs_swap(text);
- break;
- case UNDO_DBLOCK:
- linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
- buf= MEM_mallocN(linep+1, "dblock buffer");
- for (i=0; i < linep; i++) {
- buf[(linep-1)-i]= text->undo_buf[text->undo_pos];
- text->undo_pos--;
- }
- buf[i]= 0;
-
- txt_curs_first(text, &holdl, &holdc);
- holdln= txt_get_span(text->lines.first, holdl);
-
- txt_insert_buf(text, buf);
- MEM_freeN(buf);
- text->curl= text->lines.first;
- while (holdln>0) {
- if (text->curl->next)
- text->curl= text->curl->next;
-
- holdln--;
- }
- text->curc= holdc;
- text->undo_pos--;
- text->undo_pos--;
- text->undo_pos--;
- text->undo_pos--;
- text->undo_pos--;
-
- break;
- case UNDO_IBLOCK:
- linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
- txt_delete_sel(text);
- /* txt_backspace_char removes utf8-characters, not bytes */
- buf= MEM_mallocN(linep+1, "iblock buffer");
- for (i=0; i < linep; i++) {
- buf[(linep-1)-i]= text->undo_buf[text->undo_pos];
- text->undo_pos--;
- }
- buf[i]= 0;
- linep= txt_utf8_len(buf);
- MEM_freeN(buf);
- while (linep>0) {
- txt_backspace_char(text);
- linep--;
- }
- text->undo_pos--;
- text->undo_pos--;
- text->undo_pos--;
- text->undo_pos--;
-
- text->undo_pos--;
- break;
- case UNDO_INDENT:
- case UNDO_UNINDENT:
- case UNDO_COMMENT:
- case UNDO_UNCOMMENT:
- linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
- //linep is now the end line of the selection
-
- charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos);
- //charp is the last char selected or text->line->len
-
- //set the selection for this now
- text->selc = charp;
- text->sell = text->lines.first;
- for (i= 0; i < linep; i++) {
- text->sell = text->sell->next;
- }
- linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
- //first line to be selected
-
- charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos);
- //first postion to be selected
- text->curc = charp;
- text->curl = text->lines.first;
- for (i = 0; i < linep; i++) {
- text->curl = text->curl->next;
- }
-
- if (op==UNDO_INDENT) {
- txt_unindent(text);
- }
- else if (op== UNDO_UNINDENT) {
- txt_indent(text);
- }
- else if (op == UNDO_COMMENT) {
- txt_uncomment(text);
- }
- else if (op == UNDO_UNCOMMENT) {
- txt_comment(text);
- }
- text->undo_pos--;
- break;
- default:
- //XXX error("Undo buffer error - resetting");
- text->undo_pos= -1;
-
- break;
- }
- /* next undo step may need evaluating */
- if (text->undo_pos>=0) {
- switch (text->undo_buf[text->undo_pos]) {
- case UNDO_STO:
- txt_do_undo(text);
- txt_do_redo(text); /* selections need restoring */
- break;
- case UNDO_SWAP:
- txt_do_undo(text); /* swaps should appear transparent */
- break;
- }
- }
-
- undoing= 0;
- }
- void txt_do_redo(Text *text)
- {
- char op;
- unsigned int linep, i;
- unsigned short charp;
- char *buf;
-
- text->undo_pos++;
- op= text->undo_buf[text->undo_pos];
-
- i…
Large files files are truncated, but you can click here to view the full file