2011-10-10 09:38:02 +00:00
|
|
|
/*
|
2008-01-07 19:13:47 +00:00
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* 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
|
2008-01-07 19:13:47 +00:00
|
|
|
* of the License, or (at your option) any later version.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
2008-01-07 19:13:47 +00:00
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
|
|
|
|
2011-02-27 20:40:57 +00:00
|
|
|
/** \file blender/blenkernel/intern/text.c
|
|
|
|
* \ingroup bke
|
|
|
|
*/
|
|
|
|
|
2012-03-07 15:55:12 +00:00
|
|
|
#include <stdlib.h> /* abort */
|
2002-10-12 11:37:38 +00:00
|
|
|
#include <string.h> /* strstr */
|
2008-06-26 18:28:33 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2012-01-16 16:23:25 +00:00
|
|
|
#include <wchar.h>
|
|
|
|
#include <wctype.h>
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2013-02-14 03:03:12 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2012-03-07 15:55:12 +00:00
|
|
|
#include "BLI_path_util.h"
|
|
|
|
#include "BLI_string.h"
|
|
|
|
#include "BLI_string_cursor_utf8.h"
|
|
|
|
#include "BLI_string_utf8.h"
|
|
|
|
#include "BLI_listbase.h"
|
2012-03-20 02:17:37 +00:00
|
|
|
#include "BLI_fileops.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2009-09-04 21:02:43 +00:00
|
|
|
#include "DNA_constraint_types.h"
|
|
|
|
#include "DNA_controller_types.h"
|
2012-09-25 05:48:33 +00:00
|
|
|
#include "DNA_actuator_types.h"
|
Giant commit!
A full detailed description of this will be done later... is several days
of work. Here's a summary:
Render:
- Full cleanup of render code, removing *all* globals and bad level calls
all over blender. Render module is now not called abusive anymore
- API-fied calls to rendering
- Full recode of internal render pipeline. Is now rendering tiles by
default, prepared for much smarter 'bucket' render later.
- Each thread now can render a full part
- Renders were tested with 4 threads, goes fine, apart from some lookup
tables in softshadow and AO still
- Rendering is prepared to do multiple layers and passes
- No single 32 bits trick in render code anymore, all 100% floats now.
Writing images/movies
- moved writing images to blender kernel (bye bye 'schrijfplaatje'!)
- made a new Movie handle system, also in kernel. This will enable much
easier use of movies in Blender
PreviewRender:
- Using new render API, previewrender (in buttons) now uses regular render
code to generate images.
- new datafile 'preview.blend.c' has the preview scenes in it
- previews get rendered in exact displayed size (1 pixel = 1 pixel)
3D Preview render
- new; press Pkey in 3d window, for a panel that continuously renders
(pkey is for games, i know... but we dont do that in orange now!)
- this render works nearly identical to buttons-preview render, so it stops
rendering on any event (mouse, keyboard, etc)
- on moving/scaling the panel, the render code doesn't recreate all geometry
- same for shifting/panning view
- all other operations (now) regenerate the full render database still.
- this is WIP... but big fun, especially for simple scenes!
Compositor
- Using same node system as now in use for shaders, you can composit images
- works pretty straightforward... needs much more options/tools and integration
with rendering still
- is not threaded yet, nor is so smart to only recalculate changes... will be
done soon!
- the "Render Result" node will get all layers/passes as output sockets
- The "Output" node renders to a builtin image, which you can view in the Image
window. (yes, output nodes to render-result, and to files, is on the list!)
The Bad News
- "Unified Render" is removed. It might come back in some stage, but this
system should be built from scratch. I can't really understand this code...
I expect it is not much needed, especially with advanced layer/passes
control
- Panorama render, Field render, Motion blur, is not coded yet... (I had to
recode every single feature in render, so...!)
- Lens Flare is also not back... needs total revision, might become composit
effect though (using zbuffer for visibility)
- Part render is gone! (well, thats obvious, its default now).
- The render window is only restored with limited functionality... I am going
to check first the option to render to a Image window, so Blender can become
a true single-window application. :)
For example, the 'Spare render buffer' (jkey) doesnt work.
- Render with border, now default creates a smaller image
- No zbuffers are written yet... on the todo!
- Scons files and MSVC will need work to get compiling again
OK... thats what I can quickly recall. Now go compiling!
2006-01-23 22:05:47 +00:00
|
|
|
#include "DNA_scene_types.h"
|
2009-09-04 21:02:43 +00:00
|
|
|
#include "DNA_screen_types.h"
|
|
|
|
#include "DNA_space_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_text_types.h"
|
2010-08-04 04:01:27 +00:00
|
|
|
#include "DNA_userdef_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
2012-11-03 14:32:26 +00:00
|
|
|
#include "DNA_node_types.h"
|
|
|
|
#include "DNA_material_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2009-09-04 21:02:43 +00:00
|
|
|
#include "BKE_depsgraph.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BKE_global.h"
|
2009-09-04 21:02:43 +00:00
|
|
|
#include "BKE_library.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BKE_main.h"
|
2009-09-04 21:02:43 +00:00
|
|
|
#include "BKE_text.h"
|
2012-11-03 14:32:26 +00:00
|
|
|
#include "BKE_node.h"
|
2011-01-07 19:18:31 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2010-10-31 04:11:39 +00:00
|
|
|
#ifdef WITH_PYTHON
|
2003-11-23 14:28:46 +00:00
|
|
|
#include "BPY_extern.h"
|
2008-10-28 18:47:13 +00:00
|
|
|
#endif
|
2003-11-23 14:28:46 +00:00
|
|
|
|
2012-03-09 18:28:30 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
*/
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2018-03-24 12:46:25 +01:00
|
|
|
|
|
|
|
/* Undo opcodes */
|
|
|
|
|
|
|
|
enum {
|
|
|
|
/* Complex editing */
|
|
|
|
/* 1 - opcode is followed by 1 byte for ascii character and opcode (repeat)) */
|
|
|
|
/* 2 - opcode is followed by 2 bytes for utf-8 character and opcode (repeat)) */
|
|
|
|
/* 3 - opcode is followed by 3 bytes for utf-8 character and opcode (repeat)) */
|
|
|
|
/* 4 - opcode is followed by 4 bytes for unicode character and opcode (repeat)) */
|
|
|
|
UNDO_INSERT_1 = 013,
|
|
|
|
UNDO_INSERT_2 = 014,
|
|
|
|
UNDO_INSERT_3 = 015,
|
|
|
|
UNDO_INSERT_4 = 016,
|
|
|
|
|
|
|
|
UNDO_BS_1 = 017,
|
|
|
|
UNDO_BS_2 = 020,
|
|
|
|
UNDO_BS_3 = 021,
|
|
|
|
UNDO_BS_4 = 022,
|
|
|
|
|
|
|
|
UNDO_DEL_1 = 023,
|
|
|
|
UNDO_DEL_2 = 024,
|
|
|
|
UNDO_DEL_3 = 025,
|
|
|
|
UNDO_DEL_4 = 026,
|
|
|
|
|
|
|
|
/* Text block (opcode is followed
|
|
|
|
* by 4 character length ID + the text
|
|
|
|
* block itself + the 4 character length
|
|
|
|
* ID (repeat) and opcode (repeat)) */
|
|
|
|
UNDO_DBLOCK = 027, /* Delete block */
|
|
|
|
UNDO_IBLOCK = 030, /* Insert block */
|
|
|
|
|
|
|
|
/* Misc */
|
|
|
|
UNDO_INDENT = 032,
|
|
|
|
UNDO_UNINDENT = 033,
|
|
|
|
UNDO_COMMENT = 034,
|
|
|
|
UNDO_UNCOMMENT = 035,
|
|
|
|
|
|
|
|
UNDO_MOVE_LINES_UP = 036,
|
|
|
|
UNDO_MOVE_LINES_DOWN = 037,
|
|
|
|
|
|
|
|
UNDO_DUPLICATE = 040,
|
|
|
|
};
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
/***/
|
|
|
|
|
|
|
|
static void txt_pop_first(Text *text);
|
|
|
|
static void txt_pop_last(Text *text);
|
2012-11-14 23:10:19 +00:00
|
|
|
static void txt_undo_add_blockop(Text *text, int op, const char *buf);
|
2002-10-12 11:37:38 +00:00
|
|
|
static void txt_delete_line(Text *text, TextLine *line);
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_delete_sel(Text *text);
|
|
|
|
static void txt_make_dirty(Text *text);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/***/
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-01-16 14:05:39 +00:00
|
|
|
static void init_undo_text(Text *text)
|
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_pos = -1;
|
|
|
|
text->undo_len = TXT_INIT_UNDO;
|
|
|
|
text->undo_buf = MEM_mallocN(text->undo_len, "undo buf");
|
2010-01-16 14:05:39 +00:00
|
|
|
}
|
|
|
|
|
2015-12-14 17:12:16 +11:00
|
|
|
/**
|
|
|
|
* \note caller must handle `undo_buf` and `compiled` members.
|
|
|
|
*/
|
|
|
|
void BKE_text_free_lines(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2015-12-14 17:12:16 +11:00
|
|
|
for (TextLine *tmp = text->lines.first, *tmp_next; tmp; tmp = tmp_next) {
|
|
|
|
tmp_next = tmp->next;
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(tmp->line);
|
2015-12-14 17:12:16 +11:00
|
|
|
if (tmp->format) {
|
2012-05-06 15:15:33 +00:00
|
|
|
MEM_freeN(tmp->format);
|
2015-12-14 17:12:16 +11:00
|
|
|
}
|
|
|
|
MEM_freeN(tmp);
|
2005-05-13 16:11:28 +00:00
|
|
|
}
|
2015-12-14 17:12:16 +11:00
|
|
|
|
|
|
|
BLI_listbase_clear(&text->lines);
|
|
|
|
|
|
|
|
text->curl = text->sell = NULL;
|
|
|
|
}
|
|
|
|
|
ID-Remap - Step one: core work (cleanup and rework of generic ID datablock handling).
This commit changes a lot of how IDs are handled internally, especially the unlinking/freeing
processes. So far, this was very fuzy, to summarize cleanly deleting or replacing a datablock
was pretty much impossible, except for a few special cases.
Also, unlinking was handled by each datatype, in a rather messy and prone-to-errors way (quite
a few ID usages were missed or wrongly handled that way).
One of the main goal of id-remap branch was to cleanup this, and fatorize ID links handling
by using library_query utils to allow generic handling of those, which is now the case
(now, generic ID links handling is only "knwon" from readfile.c and library_query.c).
This commit also adds backends to allow live replacement and deletion of datablocks in Blender
(so-called 'remapping' process, where we replace all usages of a given ID pointer by a new one,
or NULL one in case of unlinking).
This will allow nice new features, like ability to easily reload or relocate libraries, real immediate
deletion of datablocks in blender, replacement of one datablock by another, etc.
Some of those are for next commits.
A word of warning: this commit is highly risky, because it affects potentially a lot in Blender core.
Though it was tested rather deeply, being totally impossible to check all possible ID usage cases,
it's likely there are some remaining issues and bugs in new code... Please report them! ;)
Review task: D2027 (https://developer.blender.org/D2027).
Reviewed by campbellbarton, thanks a bunch.
2016-06-22 17:29:38 +02:00
|
|
|
/** Free (or release) any data used by this text (does not free the text itself). */
|
2015-12-14 17:12:16 +11:00
|
|
|
void BKE_text_free(Text *text)
|
|
|
|
{
|
ID-Remap - Step one: core work (cleanup and rework of generic ID datablock handling).
This commit changes a lot of how IDs are handled internally, especially the unlinking/freeing
processes. So far, this was very fuzy, to summarize cleanly deleting or replacing a datablock
was pretty much impossible, except for a few special cases.
Also, unlinking was handled by each datatype, in a rather messy and prone-to-errors way (quite
a few ID usages were missed or wrongly handled that way).
One of the main goal of id-remap branch was to cleanup this, and fatorize ID links handling
by using library_query utils to allow generic handling of those, which is now the case
(now, generic ID links handling is only "knwon" from readfile.c and library_query.c).
This commit also adds backends to allow live replacement and deletion of datablocks in Blender
(so-called 'remapping' process, where we replace all usages of a given ID pointer by a new one,
or NULL one in case of unlinking).
This will allow nice new features, like ability to easily reload or relocate libraries, real immediate
deletion of datablocks in blender, replacement of one datablock by another, etc.
Some of those are for next commits.
A word of warning: this commit is highly risky, because it affects potentially a lot in Blender core.
Though it was tested rather deeply, being totally impossible to check all possible ID usage cases,
it's likely there are some remaining issues and bugs in new code... Please report them! ;)
Review task: D2027 (https://developer.blender.org/D2027).
Reviewed by campbellbarton, thanks a bunch.
2016-06-22 17:29:38 +02:00
|
|
|
/* No animdata here. */
|
|
|
|
|
2015-12-14 17:12:16 +11:00
|
|
|
BKE_text_free_lines(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
ID-Remap - Step one: core work (cleanup and rework of generic ID datablock handling).
This commit changes a lot of how IDs are handled internally, especially the unlinking/freeing
processes. So far, this was very fuzy, to summarize cleanly deleting or replacing a datablock
was pretty much impossible, except for a few special cases.
Also, unlinking was handled by each datatype, in a rather messy and prone-to-errors way (quite
a few ID usages were missed or wrongly handled that way).
One of the main goal of id-remap branch was to cleanup this, and fatorize ID links handling
by using library_query utils to allow generic handling of those, which is now the case
(now, generic ID links handling is only "knwon" from readfile.c and library_query.c).
This commit also adds backends to allow live replacement and deletion of datablocks in Blender
(so-called 'remapping' process, where we replace all usages of a given ID pointer by a new one,
or NULL one in case of unlinking).
This will allow nice new features, like ability to easily reload or relocate libraries, real immediate
deletion of datablocks in blender, replacement of one datablock by another, etc.
Some of those are for next commits.
A word of warning: this commit is highly risky, because it affects potentially a lot in Blender core.
Though it was tested rather deeply, being totally impossible to check all possible ID usage cases,
it's likely there are some remaining issues and bugs in new code... Please report them! ;)
Review task: D2027 (https://developer.blender.org/D2027).
Reviewed by campbellbarton, thanks a bunch.
2016-06-22 17:29:38 +02:00
|
|
|
MEM_SAFE_FREE(text->name);
|
|
|
|
MEM_SAFE_FREE(text->undo_buf);
|
2010-10-31 04:11:39 +00:00
|
|
|
#ifdef WITH_PYTHON
|
ID-Remap - Step one: core work (cleanup and rework of generic ID datablock handling).
This commit changes a lot of how IDs are handled internally, especially the unlinking/freeing
processes. So far, this was very fuzy, to summarize cleanly deleting or replacing a datablock
was pretty much impossible, except for a few special cases.
Also, unlinking was handled by each datatype, in a rather messy and prone-to-errors way (quite
a few ID usages were missed or wrongly handled that way).
One of the main goal of id-remap branch was to cleanup this, and fatorize ID links handling
by using library_query utils to allow generic handling of those, which is now the case
(now, generic ID links handling is only "knwon" from readfile.c and library_query.c).
This commit also adds backends to allow live replacement and deletion of datablocks in Blender
(so-called 'remapping' process, where we replace all usages of a given ID pointer by a new one,
or NULL one in case of unlinking).
This will allow nice new features, like ability to easily reload or relocate libraries, real immediate
deletion of datablocks in blender, replacement of one datablock by another, etc.
Some of those are for next commits.
A word of warning: this commit is highly risky, because it affects potentially a lot in Blender core.
Though it was tested rather deeply, being totally impossible to check all possible ID usage cases,
it's likely there are some remaining issues and bugs in new code... Please report them! ;)
Review task: D2027 (https://developer.blender.org/D2027).
Reviewed by campbellbarton, thanks a bunch.
2016-06-22 17:29:38 +02:00
|
|
|
BPY_text_free_code(text);
|
2008-10-28 18:47:13 +00:00
|
|
|
#endif
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
First step to handle missing libs/datablocks when reading a file.
Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.
That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.
Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.
Future plans are also to be able to relocate missing libs and reload them at runtime.
Code notes:
- Placeholder ID is just a regular datablock of same type as expected linked one,
with 'default' data, and a LIB_MISSING bitflag set.
- To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
+ Allocation of memory itself.
+ Setting of all internal data to default values.
See also the design task (T43351).
Reviewed by @campbellbarton, thanks a bunch!
Differential Revision: https://developer.blender.org/D1394
2015-10-20 14:44:57 +02:00
|
|
|
void BKE_text_init(Text *ta)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine *tmp;
|
First step to handle missing libs/datablocks when reading a file.
Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.
That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.
Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.
Future plans are also to be able to relocate missing libs and reload them at runtime.
Code notes:
- Placeholder ID is just a regular datablock of same type as expected linked one,
with 'default' data, and a LIB_MISSING bitflag set.
- To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
+ Allocation of memory itself.
+ Setting of all internal data to default values.
See also the design task (T43351).
Reviewed by @campbellbarton, thanks a bunch!
Differential Revision: https://developer.blender.org/D1394
2015-10-20 14:44:57 +02:00
|
|
|
|
|
|
|
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ta, id));
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
ta->name = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2010-03-22 09:30:00 +00:00
|
|
|
init_undo_text(ta);
|
2010-01-16 14:05:39 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
ta->nlines = 1;
|
|
|
|
ta->flags = TXT_ISDIRTY | TXT_ISMEM;
|
|
|
|
if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE) == 0)
|
2010-03-06 21:45:46 +00:00
|
|
|
ta->flags |= TXT_TABSTOSPACES;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&ta->lines);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
|
|
|
|
tmp->line = (char *) MEM_mallocN(1, "textline_string");
|
|
|
|
tmp->format = NULL;
|
2005-05-13 16:11:28 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp->line[0] = 0;
|
|
|
|
tmp->len = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp->next = NULL;
|
|
|
|
tmp->prev = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
BLI_addhead(&ta->lines, tmp);
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
ta->curl = ta->lines.first;
|
|
|
|
ta->curc = 0;
|
|
|
|
ta->sell = ta->lines.first;
|
|
|
|
ta->selc = 0;
|
First step to handle missing libs/datablocks when reading a file.
Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.
That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.
Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.
Future plans are also to be able to relocate missing libs and reload them at runtime.
Code notes:
- Placeholder ID is just a regular datablock of same type as expected linked one,
with 'default' data, and a LIB_MISSING bitflag set.
- To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
+ Allocation of memory itself.
+ Setting of all internal data to default values.
See also the design task (T43351).
Reviewed by @campbellbarton, thanks a bunch!
Differential Revision: https://developer.blender.org/D1394
2015-10-20 14:44:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Text *BKE_text_add(Main *bmain, const char *name)
|
|
|
|
{
|
|
|
|
Text *ta;
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
ta = BKE_libblock_alloc(bmain, ID_TXT, name, 0);
|
First step to handle missing libs/datablocks when reading a file.
Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.
That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.
Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.
Future plans are also to be able to relocate missing libs and reload them at runtime.
Code notes:
- Placeholder ID is just a regular datablock of same type as expected linked one,
with 'default' data, and a LIB_MISSING bitflag set.
- To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
+ Allocation of memory itself.
+ Setting of all internal data to default values.
See also the design task (T43351).
Reviewed by @campbellbarton, thanks a bunch!
Differential Revision: https://developer.blender.org/D1394
2015-10-20 14:44:57 +02:00
|
|
|
|
|
|
|
BKE_text_init(ta);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
return ta;
|
|
|
|
}
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
/* this function replaces extended ascii characters */
|
|
|
|
/* to a valid utf-8 sequences */
|
|
|
|
int txt_extended_ascii_as_utf8(char **str)
|
|
|
|
{
|
2017-01-20 21:57:48 +01:00
|
|
|
ptrdiff_t bad_char, i = 0;
|
|
|
|
const ptrdiff_t length = (ptrdiff_t)strlen(*str);
|
2017-01-20 13:03:21 +01:00
|
|
|
int added = 0;
|
2012-01-16 16:23:25 +00:00
|
|
|
|
|
|
|
while ((*str)[i]) {
|
2012-05-06 15:15:33 +00:00
|
|
|
if ((bad_char = BLI_utf8_invalid_byte(*str + i, length - i)) == -1)
|
2012-01-17 17:26:58 +00:00
|
|
|
break;
|
2012-01-16 16:23:25 +00:00
|
|
|
|
|
|
|
added++;
|
2012-05-06 15:15:33 +00:00
|
|
|
i += bad_char + 1;
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (added != 0) {
|
2012-05-06 15:15:33 +00:00
|
|
|
char *newstr = MEM_mallocN(length + added + 1, "text_line");
|
2017-01-20 21:57:48 +01:00
|
|
|
ptrdiff_t mi = 0;
|
2012-05-06 15:15:33 +00:00
|
|
|
i = 0;
|
2012-01-16 16:23:25 +00:00
|
|
|
|
|
|
|
while ((*str)[i]) {
|
2012-05-06 15:15:33 +00:00
|
|
|
if ((bad_char = BLI_utf8_invalid_byte((*str) + i, length - i)) == -1) {
|
|
|
|
memcpy(newstr + mi, (*str) + i, length - i + 1);
|
2012-01-16 16:23:25 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
memcpy(newstr + mi, (*str) + i, bad_char);
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
BLI_str_utf8_from_unicode((*str)[i + bad_char], newstr + mi + bad_char);
|
|
|
|
i += bad_char + 1;
|
|
|
|
mi += bad_char + 2;
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
newstr[length + added] = '\0';
|
2012-01-16 16:23:25 +00:00
|
|
|
MEM_freeN(*str);
|
|
|
|
*str = newstr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return added;
|
|
|
|
}
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
// this function removes any control characters from
|
2012-01-16 16:23:25 +00:00
|
|
|
// a textline and fixes invalid utf-8 sequences
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void cleanup_textline(TextLine *tl)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
for (i = 0; i < tl->len; i++) {
|
2002-10-12 11:37:38 +00:00
|
|
|
if (tl->line[i] < ' ' && tl->line[i] != '\t') {
|
|
|
|
memmove(tl->line + i, tl->line + i + 1, tl->len - i);
|
|
|
|
tl->len--;
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
tl->len += txt_extended_ascii_as_utf8(&tl->line);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-09-17 19:28:46 +10:00
|
|
|
/**
|
|
|
|
* used for load and reload (unlike txt_insert_buf)
|
|
|
|
* assumes all fields are empty
|
|
|
|
*/
|
|
|
|
static void text_from_buf(Text *text, const unsigned char *buffer, const int len)
|
|
|
|
{
|
|
|
|
int i, llen;
|
|
|
|
|
|
|
|
BLI_assert(BLI_listbase_is_empty(&text->lines));
|
|
|
|
|
|
|
|
text->nlines = 0;
|
|
|
|
llen = 0;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
if (buffer[i] == '\n') {
|
|
|
|
TextLine *tmp;
|
|
|
|
|
|
|
|
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++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 || text->nlines == 0 || buffer[len - 1] == '\n') {
|
|
|
|
TextLine *tmp;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-06-05 11:46:01 +10:00
|
|
|
bool BKE_text_reload(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
unsigned char *buffer;
|
2015-12-14 17:12:16 +11:00
|
|
|
size_t buffer_len;
|
|
|
|
char filepath_abs[FILE_MAX];
|
2014-09-17 19:28:46 +10:00
|
|
|
BLI_stat_t st;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2015-06-05 11:46:01 +10:00
|
|
|
if (!text->name) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-12-14 17:12:16 +11:00
|
|
|
BLI_strncpy(filepath_abs, text->name, FILE_MAX);
|
|
|
|
BLI_path_abs(filepath_abs, G.main->name);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2015-12-21 18:16:14 +11:00
|
|
|
buffer = BLI_file_read_text_as_mem(filepath_abs, 0, &buffer_len);
|
2015-12-14 17:12:16 +11:00
|
|
|
if (buffer == NULL) {
|
2015-06-05 11:46:01 +10:00
|
|
|
return false;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* free memory: */
|
2015-12-14 17:12:16 +11:00
|
|
|
BKE_text_free_lines(text);
|
|
|
|
txt_make_dirty(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* clear undo buffer */
|
|
|
|
MEM_freeN(text->undo_buf);
|
2010-01-16 14:05:39 +00:00
|
|
|
init_undo_text(text);
|
2014-09-17 19:28:46 +10:00
|
|
|
|
2008-06-28 00:07:22 +00:00
|
|
|
|
2015-12-14 17:12:16 +11:00
|
|
|
if (BLI_stat(filepath_abs, &st) != -1) {
|
2015-02-18 07:26:10 +11:00
|
|
|
text->mtime = st.st_mtime;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
text->mtime = 0;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2015-12-14 17:12:16 +11:00
|
|
|
text_from_buf(text, buffer, buffer_len);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
MEM_freeN(buffer);
|
2015-06-05 11:46:01 +10:00
|
|
|
return true;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2013-06-02 17:52:06 +00:00
|
|
|
Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const bool is_internal)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
unsigned char *buffer;
|
2015-12-14 17:12:16 +11:00
|
|
|
size_t buffer_len;
|
2002-10-12 11:37:38 +00:00
|
|
|
Text *ta;
|
2015-12-14 17:12:16 +11:00
|
|
|
char filepath_abs[FILE_MAX];
|
2014-09-17 19:28:46 +10:00
|
|
|
BLI_stat_t st;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2015-12-14 17:12:16 +11:00
|
|
|
BLI_strncpy(filepath_abs, file, FILE_MAX);
|
2009-01-04 14:14:06 +00:00
|
|
|
if (relpath) /* can be NULL (bg mode) */
|
2015-12-14 17:12:16 +11:00
|
|
|
BLI_path_abs(filepath_abs, relpath);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2015-12-21 18:16:14 +11:00
|
|
|
buffer = BLI_file_read_text_as_mem(filepath_abs, 0, &buffer_len);
|
2015-12-14 17:12:16 +11:00
|
|
|
if (buffer == NULL) {
|
|
|
|
return false;
|
2015-06-05 11:46:01 +10:00
|
|
|
}
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(filepath_abs), 0);
|
2017-01-04 14:07:38 +01:00
|
|
|
ta->id.us = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&ta->lines);
|
2012-05-06 15:15:33 +00:00
|
|
|
ta->curl = ta->sell = NULL;
|
2010-03-06 21:45:46 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE) == 0)
|
|
|
|
ta->flags = TXT_TABSTOSPACES;
|
2010-03-06 21:45:46 +00:00
|
|
|
|
2013-06-02 17:52:06 +00:00
|
|
|
if (is_internal == false) {
|
|
|
|
ta->name = MEM_mallocN(strlen(file) + 1, "text_name");
|
|
|
|
strcpy(ta->name, file);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ta->flags |= TXT_ISMEM | TXT_ISDIRTY;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2014-09-17 19:28:46 +10:00
|
|
|
/* clear undo buffer */
|
2010-01-16 14:05:39 +00:00
|
|
|
init_undo_text(ta);
|
2008-06-28 00:07:22 +00:00
|
|
|
|
2015-12-14 17:12:16 +11:00
|
|
|
if (BLI_stat(filepath_abs, &st) != -1) {
|
2015-02-18 07:26:10 +11:00
|
|
|
ta->mtime = st.st_mtime;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ta->mtime = 0;
|
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
|
2015-12-14 17:12:16 +11:00
|
|
|
text_from_buf(ta, buffer, buffer_len);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
MEM_freeN(buffer);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
return ta;
|
|
|
|
}
|
|
|
|
|
2013-06-02 17:52:06 +00:00
|
|
|
Text *BKE_text_load(Main *bmain, const char *file, const char *relpath)
|
|
|
|
{
|
|
|
|
return BKE_text_load_ex(bmain, file, relpath, false);
|
|
|
|
}
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
/**
|
|
|
|
* Only copy internal data of Text ID from source to already allocated/initialized destination.
|
|
|
|
* You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
|
|
|
|
*
|
|
|
|
* WARNING! This function will not handle ID user count!
|
|
|
|
*
|
|
|
|
* \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
|
|
|
|
*/
|
|
|
|
void BKE_text_copy_data(Main *UNUSED(bmain), Text *ta_dst, const Text *ta_src, const int UNUSED(flag))
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2010-01-26 11:29:39 +00:00
|
|
|
/* file name can be NULL */
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
if (ta_src->name) {
|
|
|
|
ta_dst->name = BLI_strdup(ta_src->name);
|
2010-01-26 11:29:39 +00:00
|
|
|
}
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
ta_dst->flags |= TXT_ISDIRTY;
|
|
|
|
|
|
|
|
BLI_listbase_clear(&ta_dst->lines);
|
|
|
|
ta_dst->curl = ta_dst->sell = NULL;
|
|
|
|
ta_dst->compiled = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* Walk down, reconstructing */
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
for (TextLine *line_src = ta_src->lines.first; line_src; line_src = line_src->next) {
|
|
|
|
TextLine *line_dst = MEM_mallocN(sizeof(*line_dst), __func__);
|
2005-05-13 16:11:28 +00:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
line_dst->line = BLI_strdup(line_src->line);
|
|
|
|
line_dst->format = NULL;
|
|
|
|
line_dst->len = line_src->len;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
BLI_addtail(&ta_dst->lines, line_dst);
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
ta_dst->curl = ta_dst->sell = ta_dst->lines.first;
|
|
|
|
ta_dst->curc = ta_dst->selc = 0;
|
2010-01-16 14:05:39 +00:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
init_undo_text(ta_dst);
|
|
|
|
}
|
2015-01-09 09:52:51 +01:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
Text *BKE_text_copy(Main *bmain, const Text *ta)
|
|
|
|
{
|
|
|
|
Text *ta_copy;
|
|
|
|
BKE_id_copy_ex(bmain, &ta->id, (ID **)&ta_copy, 0, false);
|
|
|
|
return ta_copy;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2016-07-21 16:09:08 +02:00
|
|
|
void BKE_text_make_local(Main *bmain, Text *text, const bool lib_local)
|
|
|
|
{
|
|
|
|
BKE_id_make_local_generic(bmain, &text->id, true, lib_local);
|
|
|
|
}
|
|
|
|
|
2012-05-05 14:52:04 +00:00
|
|
|
void BKE_text_clear(Text *text) /* called directly from rna */
|
2009-09-16 06:02:56 +00:00
|
|
|
{
|
|
|
|
int oldstate;
|
|
|
|
|
2015-02-07 04:33:48 +11:00
|
|
|
oldstate = txt_get_undostate();
|
2012-04-29 17:11:40 +00:00
|
|
|
txt_set_undostate(1);
|
|
|
|
txt_sel_all(text);
|
2009-09-16 06:02:56 +00:00
|
|
|
txt_delete_sel(text);
|
2012-03-11 19:09:01 +00:00
|
|
|
txt_set_undostate(oldstate);
|
2009-09-16 06:02:56 +00:00
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
}
|
|
|
|
|
2012-05-05 14:52:04 +00:00
|
|
|
void BKE_text_write(Text *text, const char *str) /* called directly from rna */
|
2009-09-16 06:02:56 +00:00
|
|
|
{
|
|
|
|
int oldstate;
|
|
|
|
|
2012-03-11 19:09:01 +00:00
|
|
|
oldstate = txt_get_undostate();
|
|
|
|
txt_insert_buf(text, str);
|
|
|
|
txt_move_eof(text, 0);
|
|
|
|
txt_set_undostate(oldstate);
|
2009-09-16 06:02:56 +00:00
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
}
|
2009-09-04 21:02:43 +00:00
|
|
|
|
2014-01-28 01:55:10 +11:00
|
|
|
|
|
|
|
/* returns 0 if file on disk is the same or Text is in memory only
|
|
|
|
* returns 1 if file has been modified on disk since last local edit
|
|
|
|
* returns 2 if file on disk has been deleted
|
|
|
|
* -1 is returned if an error occurs */
|
|
|
|
|
|
|
|
int BKE_text_file_modified_check(Text *text)
|
|
|
|
{
|
2014-05-28 22:50:40 +06:00
|
|
|
BLI_stat_t st;
|
2014-01-28 01:55:10 +11:00
|
|
|
int result;
|
|
|
|
char file[FILE_MAX];
|
|
|
|
|
2014-10-06 12:23:47 +02:00
|
|
|
if (!text->name)
|
2014-01-28 01:55:10 +11:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
BLI_strncpy(file, text->name, FILE_MAX);
|
|
|
|
BLI_path_abs(file, G.main->name);
|
|
|
|
|
|
|
|
if (!BLI_exists(file))
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
result = BLI_stat(file, &st);
|
|
|
|
|
|
|
|
if (result == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if ((st.st_mode & S_IFMT) != S_IFREG)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (st.st_mtime > text->mtime)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_text_file_modified_ignore(Text *text)
|
|
|
|
{
|
2014-05-28 22:50:40 +06:00
|
|
|
BLI_stat_t st;
|
2014-01-28 01:55:10 +11:00
|
|
|
int result;
|
|
|
|
char file[FILE_MAX];
|
|
|
|
|
2014-10-06 12:23:47 +02:00
|
|
|
if (!text->name) return;
|
2014-01-28 01:55:10 +11:00
|
|
|
|
|
|
|
BLI_strncpy(file, text->name, FILE_MAX);
|
|
|
|
BLI_path_abs(file, G.main->name);
|
|
|
|
|
|
|
|
if (!BLI_exists(file)) return;
|
|
|
|
|
|
|
|
result = BLI_stat(file, &st);
|
|
|
|
|
|
|
|
if (result == -1 || (st.st_mode & S_IFMT) != S_IFREG)
|
|
|
|
return;
|
|
|
|
|
|
|
|
text->mtime = st.st_mtime;
|
|
|
|
}
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
/*****************************/
|
|
|
|
/* Editing utility functions */
|
|
|
|
/*****************************/
|
|
|
|
|
2012-04-06 05:53:01 +00:00
|
|
|
static void make_new_line(TextLine *line, char *newline)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2005-05-18 23:54:56 +00:00
|
|
|
if (line->line) MEM_freeN(line->line);
|
|
|
|
if (line->format) MEM_freeN(line->format);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
line->line = newline;
|
|
|
|
line->len = strlen(newline);
|
|
|
|
line->format = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2010-12-03 17:05:21 +00:00
|
|
|
static TextLine *txt_new_line(const char *str)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine *tmp;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (!str) str = "";
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
|
|
|
|
tmp->line = MEM_mallocN(strlen(str) + 1, "textline_string");
|
|
|
|
tmp->format = NULL;
|
2005-05-13 16:11:28 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
strcpy(tmp->line, str);
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp->len = strlen(str);
|
|
|
|
tmp->next = tmp->prev = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
2009-09-17 14:46:22 +00:00
|
|
|
static TextLine *txt_new_linen(const char *str, int n)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine *tmp;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
|
|
|
|
tmp->line = MEM_mallocN(n + 1, "textline_string");
|
|
|
|
tmp->format = NULL;
|
2005-05-13 16:11:28 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
BLI_strncpy(tmp->line, (str) ? str : "", n + 1);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp->len = strlen(tmp->line);
|
|
|
|
tmp->next = tmp->prev = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
void txt_clean_text(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine **top, **bot;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (!text->lines.first) {
|
2012-05-06 15:15:33 +00:00
|
|
|
if (text->lines.last) text->lines.first = text->lines.last;
|
|
|
|
else text->lines.first = text->lines.last = txt_new_line(NULL);
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (!text->lines.last) text->lines.last = text->lines.first;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
top = (TextLine **) &text->lines.first;
|
|
|
|
bot = (TextLine **) &text->lines.last;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
while ((*top)->prev) *top = (*top)->prev;
|
|
|
|
while ((*bot)->next) *bot = (*bot)->next;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!text->curl) {
|
2012-05-06 15:15:33 +00:00
|
|
|
if (text->sell) text->curl = text->sell;
|
|
|
|
else text->curl = text->lines.first;
|
|
|
|
text->curc = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!text->sell) {
|
2012-05-06 15:15:33 +00:00
|
|
|
text->sell = text->curl;
|
|
|
|
text->selc = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
int txt_get_span(TextLine *from, TextLine *to)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
int ret = 0;
|
|
|
|
TextLine *tmp = from;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (!to || !from) return 0;
|
2012-05-06 15:15:33 +00:00
|
|
|
if (from == to) return 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* Look forwards */
|
|
|
|
while (tmp) {
|
|
|
|
if (tmp == to) return ret;
|
|
|
|
ret++;
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = tmp->next;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Look backwards */
|
|
|
|
if (!tmp) {
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = from;
|
|
|
|
ret = 0;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (tmp) {
|
2002-10-12 11:37:38 +00:00
|
|
|
if (tmp == to) break;
|
|
|
|
ret--;
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = tmp->prev;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
if (!tmp) ret = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
return ret;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_make_dirty(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
text->flags |= TXT_ISDIRTY;
|
2010-10-31 04:11:39 +00:00
|
|
|
#ifdef WITH_PYTHON
|
2011-01-05 02:08:54 +00:00
|
|
|
if (text->compiled) BPY_text_free_code(text);
|
2008-10-28 18:47:13 +00:00
|
|
|
#endif
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************/
|
|
|
|
/* Cursor utility functions */
|
|
|
|
/****************************/
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_curs_cur(Text *text, TextLine ***linep, int **charp)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
*linep = &text->curl; *charp = &text->curc;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_curs_sel(Text *text, TextLine ***linep, int **charp)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
*linep = &text->sell; *charp = &text->selc;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2013-05-01 00:15:22 +00:00
|
|
|
bool txt_cursor_is_line_start(Text *text)
|
|
|
|
{
|
|
|
|
return (text->selc == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool txt_cursor_is_line_end(Text *text)
|
|
|
|
{
|
|
|
|
return (text->selc == text->sell->len);
|
|
|
|
}
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
/*****************************/
|
2002-10-12 11:37:38 +00:00
|
|
|
/* Cursor movement functions */
|
2012-01-16 16:23:25 +00:00
|
|
|
/*****************************/
|
|
|
|
|
2012-04-06 05:53:01 +00:00
|
|
|
int txt_utf8_offset_to_index(const char *str, int offset)
|
2012-01-16 16:23:25 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
int index = 0, pos = 0;
|
2012-01-16 16:23:25 +00:00
|
|
|
while (pos != offset) {
|
|
|
|
pos += BLI_str_utf8_size(str + pos);
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
2012-04-06 05:53:01 +00:00
|
|
|
int txt_utf8_index_to_offset(const char *str, int index)
|
2012-01-16 16:23:25 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
int offset = 0, pos = 0;
|
2012-01-16 16:23:25 +00:00
|
|
|
while (pos != index) {
|
|
|
|
offset += BLI_str_utf8_size(str + offset);
|
|
|
|
pos++;
|
|
|
|
}
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2013-03-12 07:25:53 +00:00
|
|
|
int txt_utf8_offset_to_column(const char *str, int offset)
|
|
|
|
{
|
|
|
|
int column = 0, pos = 0;
|
|
|
|
while (pos < offset) {
|
|
|
|
column += BLI_str_utf8_char_width_safe(str + pos);
|
|
|
|
pos += BLI_str_utf8_size_safe(str + pos);
|
|
|
|
}
|
|
|
|
return column;
|
|
|
|
}
|
|
|
|
|
|
|
|
int txt_utf8_column_to_offset(const char *str, int column)
|
|
|
|
{
|
|
|
|
int offset = 0, pos = 0, col;
|
2013-03-27 09:57:34 +00:00
|
|
|
while (*(str + offset) && pos < column) {
|
2013-03-12 07:25:53 +00:00
|
|
|
col = BLI_str_utf8_char_width_safe(str + offset);
|
|
|
|
if (pos + col > column)
|
|
|
|
break;
|
|
|
|
offset += BLI_str_utf8_size_safe(str + offset);
|
|
|
|
pos += col;
|
|
|
|
}
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_move_up(Text *text, const bool sel)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine **linep;
|
2012-01-22 17:26:56 +00:00
|
|
|
int *charp;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
|
|
|
|
if (!*linep) return;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if ((*linep)->prev) {
|
2013-03-12 07:25:53 +00:00
|
|
|
int column = txt_utf8_offset_to_column((*linep)->line, *charp);
|
2012-05-06 15:15:33 +00:00
|
|
|
*linep = (*linep)->prev;
|
2013-03-27 09:57:34 +00:00
|
|
|
*charp = txt_utf8_column_to_offset((*linep)->line, column);
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2008-07-26 22:37:05 +00:00
|
|
|
txt_move_bol(text, sel);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!sel) txt_pop_sel(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_move_down(Text *text, const bool sel)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine **linep;
|
2012-01-22 17:26:56 +00:00
|
|
|
int *charp;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
|
|
|
|
if (!*linep) return;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if ((*linep)->next) {
|
2013-03-12 07:25:53 +00:00
|
|
|
int column = txt_utf8_offset_to_column((*linep)->line, *charp);
|
2012-05-06 15:15:33 +00:00
|
|
|
*linep = (*linep)->next;
|
2013-03-27 09:57:34 +00:00
|
|
|
*charp = txt_utf8_column_to_offset((*linep)->line, column);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2008-07-26 22:37:05 +00:00
|
|
|
txt_move_eol(text, sel);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!sel) txt_pop_sel(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2016-03-11 00:04:13 +11:00
|
|
|
int txt_calc_tab_left(TextLine *tl, int ch)
|
|
|
|
{
|
|
|
|
/* do nice left only if there are only spaces */
|
|
|
|
|
|
|
|
int tabsize = (ch < TXT_TABSIZE) ? ch : TXT_TABSIZE;
|
|
|
|
|
|
|
|
for (int i = 0; i < ch; i++)
|
|
|
|
if (tl->line[i] != ' ') {
|
|
|
|
tabsize = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if in the middle of the space-tab */
|
|
|
|
if (tabsize && ch % TXT_TABSIZE != 0)
|
|
|
|
tabsize = (ch % TXT_TABSIZE);
|
|
|
|
return tabsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
int txt_calc_tab_right(TextLine *tl, int ch)
|
|
|
|
{
|
|
|
|
if (tl->line[ch] == ' ') {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ch; i++) {
|
|
|
|
if (tl->line[i] != ' ') {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int tabsize = (ch) % TXT_TABSIZE + 1;
|
|
|
|
for (i = ch + 1; tl->line[i] == ' ' && tabsize < TXT_TABSIZE; i++) {
|
|
|
|
tabsize++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return i - ch;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_move_left(Text *text, const bool sel)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine **linep;
|
2012-11-14 23:10:19 +00:00
|
|
|
int *charp;
|
2016-03-11 00:04:13 +11:00
|
|
|
int tabsize = 0;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
|
|
|
|
if (!*linep) return;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (*charp == 0) {
|
2012-01-16 16:23:25 +00:00
|
|
|
if ((*linep)->prev) {
|
|
|
|
txt_move_up(text, sel);
|
2012-05-06 15:15:33 +00:00
|
|
|
*charp = (*linep)->len;
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2016-03-11 00:04:13 +11:00
|
|
|
/* do nice left only if there are only spaces */
|
2012-01-16 16:23:25 +00:00
|
|
|
// TXT_TABSIZE hardcoded in DNA_text_types.h
|
|
|
|
if (text->flags & TXT_TABSTOSPACES) {
|
2016-03-11 00:04:13 +11:00
|
|
|
tabsize = txt_calc_tab_left(*linep, *charp);
|
2011-11-14 17:33:32 +00:00
|
|
|
}
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2016-03-11 00:04:13 +11:00
|
|
|
if (tabsize) {
|
2012-05-06 15:15:33 +00:00
|
|
|
(*charp) -= tabsize;
|
2016-03-11 00:04:13 +11:00
|
|
|
}
|
2012-01-16 16:23:25 +00:00
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
const char *prev = BLI_str_prev_char_utf8((*linep)->line + *charp);
|
|
|
|
*charp = prev - (*linep)->line;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
2011-11-14 17:33:32 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!sel) txt_pop_sel(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_move_right(Text *text, const bool sel)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine **linep;
|
2016-03-11 00:04:13 +11:00
|
|
|
int *charp;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
|
|
|
|
if (!*linep) return;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (*charp == (*linep)->len) {
|
2002-10-12 11:37:38 +00:00
|
|
|
if ((*linep)->next) {
|
|
|
|
txt_move_down(text, sel);
|
2012-05-06 15:15:33 +00:00
|
|
|
*charp = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2012-01-16 16:23:25 +00:00
|
|
|
else {
|
2016-03-11 00:04:13 +11:00
|
|
|
/* do nice right only if there are only spaces */
|
|
|
|
/* spaces hardcoded in DNA_text_types.h */
|
|
|
|
int tabsize = 0;
|
|
|
|
|
|
|
|
if (text->flags & TXT_TABSTOSPACES) {
|
|
|
|
tabsize = txt_calc_tab_right(*linep, *charp);
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
|
|
|
|
2016-03-11 00:04:13 +11:00
|
|
|
if (tabsize) {
|
|
|
|
(*charp) += tabsize;
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
2013-03-09 03:46:30 +00:00
|
|
|
else {
|
|
|
|
(*charp) += BLI_str_utf8_size((*linep)->line + *charp);
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!sel) txt_pop_sel(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_jump_left(Text *text, const bool sel, const bool use_init_step)
|
2008-06-04 23:20:54 +00:00
|
|
|
{
|
2012-05-08 11:18:20 +00:00
|
|
|
TextLine **linep;
|
2012-11-14 23:10:19 +00:00
|
|
|
int *charp;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2008-06-10 15:25:05 +00:00
|
|
|
else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
|
|
|
|
if (!*linep) return;
|
|
|
|
|
2012-03-07 15:55:12 +00:00
|
|
|
BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len,
|
2012-05-06 15:15:33 +00:00
|
|
|
charp, STRCUR_DIR_PREV,
|
2013-02-14 03:03:12 +00:00
|
|
|
STRCUR_JUMP_DELIM, use_init_step);
|
2012-05-08 11:18:20 +00:00
|
|
|
|
|
|
|
if (!sel) txt_pop_sel(text);
|
2008-06-04 23:20:54 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_jump_right(Text *text, const bool sel, const bool use_init_step)
|
2008-06-04 23:20:54 +00:00
|
|
|
{
|
2012-05-08 11:18:20 +00:00
|
|
|
TextLine **linep;
|
2012-11-14 23:10:19 +00:00
|
|
|
int *charp;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2008-06-10 15:25:05 +00:00
|
|
|
else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
|
|
|
|
if (!*linep) return;
|
2012-05-08 11:18:20 +00:00
|
|
|
|
2012-03-07 15:55:12 +00:00
|
|
|
BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len,
|
2012-05-06 15:15:33 +00:00
|
|
|
charp, STRCUR_DIR_NEXT,
|
2013-02-14 03:03:12 +00:00
|
|
|
STRCUR_JUMP_DELIM, use_init_step);
|
2012-05-08 11:18:20 +00:00
|
|
|
|
|
|
|
if (!sel) txt_pop_sel(text);
|
2008-06-04 23:20:54 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_move_bol(Text *text, const bool sel)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine **linep;
|
2012-11-14 23:10:19 +00:00
|
|
|
int *charp;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
else txt_curs_cur(text, &linep, &charp);
|
|
|
|
if (!*linep) return;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
*charp = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!sel) txt_pop_sel(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_move_eol(Text *text, const bool sel)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine **linep;
|
2012-11-14 23:10:19 +00:00
|
|
|
int *charp;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
else txt_curs_cur(text, &linep, &charp);
|
|
|
|
if (!*linep) return;
|
2012-11-14 23:10:19 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
*charp = (*linep)->len;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!sel) txt_pop_sel(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_move_bof(Text *text, const bool sel)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine **linep;
|
2012-11-14 23:10:19 +00:00
|
|
|
int *charp;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
else txt_curs_cur(text, &linep, &charp);
|
|
|
|
if (!*linep) return;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
*linep = text->lines.first;
|
|
|
|
*charp = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!sel) txt_pop_sel(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_move_eof(Text *text, const bool sel)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine **linep;
|
2012-11-14 23:10:19 +00:00
|
|
|
int *charp;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
else txt_curs_cur(text, &linep, &charp);
|
|
|
|
if (!*linep) return;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
*linep = text->lines.last;
|
|
|
|
*charp = (*linep)->len;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!sel) txt_pop_sel(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_move_toline(Text *text, unsigned int line, const bool sel)
|
2008-06-17 19:26:26 +00:00
|
|
|
{
|
|
|
|
txt_move_to(text, line, 0, sel);
|
|
|
|
}
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
/* Moves to a certain byte in a line, not a certain utf8-character! */
|
2014-01-04 17:16:19 +11:00
|
|
|
void txt_move_to(Text *text, unsigned int line, unsigned int ch, const bool sel)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-11-14 23:10:19 +00:00
|
|
|
TextLine **linep;
|
|
|
|
int *charp;
|
2002-10-12 11:37:38 +00:00
|
|
|
unsigned int i;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sel) txt_curs_sel(text, &linep, &charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
else txt_curs_cur(text, &linep, &charp);
|
|
|
|
if (!*linep) return;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
*linep = text->lines.first;
|
|
|
|
for (i = 0; i < line; i++) {
|
|
|
|
if ((*linep)->next) *linep = (*linep)->next;
|
2002-10-12 11:37:38 +00:00
|
|
|
else break;
|
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
if (ch > (unsigned int)((*linep)->len))
|
|
|
|
ch = (unsigned int)((*linep)->len);
|
|
|
|
*charp = ch;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!sel) txt_pop_sel(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************/
|
|
|
|
/* Text selection functions */
|
|
|
|
/****************************/
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_curs_swap(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine *tmpl;
|
|
|
|
int tmpc;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmpl = text->curl;
|
|
|
|
text->curl = text->sell;
|
|
|
|
text->sell = tmpl;
|
|
|
|
|
|
|
|
tmpc = text->curc;
|
|
|
|
text->curc = text->selc;
|
|
|
|
text->selc = tmpc;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_pop_first(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
if (txt_get_span(text->curl, text->sell) < 0 ||
|
2012-05-20 19:49:27 +00:00
|
|
|
(text->curl == text->sell && text->curc > text->selc))
|
|
|
|
{
|
2002-10-12 11:37:38 +00:00
|
|
|
txt_curs_swap(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
txt_pop_sel(text);
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_pop_last(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
if (txt_get_span(text->curl, text->sell) > 0 ||
|
2012-05-20 19:49:27 +00:00
|
|
|
(text->curl == text->sell && text->curc < text->selc))
|
|
|
|
{
|
2002-10-12 11:37:38 +00:00
|
|
|
txt_curs_swap(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
txt_pop_sel(text);
|
|
|
|
}
|
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
void txt_pop_sel(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
text->sell = text->curl;
|
|
|
|
text->selc = text->curc;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2013-09-02 00:47:27 +00:00
|
|
|
void txt_order_cursors(Text *text, const bool reverse)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
if (!text->curl) return;
|
|
|
|
if (!text->sell) return;
|
|
|
|
|
2013-09-02 00:47:27 +00:00
|
|
|
/* Flip so text->curl is before/after text->sell */
|
|
|
|
if (reverse == false) {
|
|
|
|
if ((txt_get_span(text->curl, text->sell) < 0) ||
|
|
|
|
(text->curl == text->sell && text->curc > text->selc))
|
|
|
|
{
|
|
|
|
txt_curs_swap(text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ((txt_get_span(text->curl, text->sell) > 0) ||
|
|
|
|
(text->curl == text->sell && text->curc < text->selc))
|
|
|
|
{
|
|
|
|
txt_curs_swap(text);
|
|
|
|
}
|
2012-04-28 06:31:57 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool txt_has_sel(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
return ((text->curl != text->sell) || (text->curc != text->selc));
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_delete_sel(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine *tmpl;
|
2008-07-28 11:05:35 +00:00
|
|
|
char *buf;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (!text->curl) return;
|
|
|
|
if (!text->sell) return;
|
|
|
|
|
|
|
|
if (!txt_has_sel(text)) return;
|
|
|
|
|
2013-09-02 00:47:27 +00:00
|
|
|
txt_order_cursors(text, false);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!undoing) {
|
2012-05-06 15:15:33 +00:00
|
|
|
buf = txt_sel_to_buf(text);
|
2012-11-14 23:10:19 +00:00
|
|
|
txt_undo_add_blockop(text, UNDO_DBLOCK, buf);
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(buf);
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf = MEM_mallocN(text->curc + (text->sell->len - text->selc) + 1, "textline_string");
|
2008-08-04 23:01:47 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
strncpy(buf, text->curl->line, text->curc);
|
2012-05-06 15:15:33 +00:00
|
|
|
strcpy(buf + text->curc, text->sell->line + text->selc);
|
|
|
|
buf[text->curc + (text->sell->len - text->selc)] = 0;
|
2005-05-13 16:11:28 +00:00
|
|
|
|
2008-07-28 11:05:35 +00:00
|
|
|
make_new_line(text->curl, buf);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmpl = text->sell;
|
2002-10-12 11:37:38 +00:00
|
|
|
while (tmpl != text->curl) {
|
2012-05-06 15:15:33 +00:00
|
|
|
tmpl = tmpl->prev;
|
2002-10-12 11:37:38 +00:00
|
|
|
if (!tmpl) break;
|
|
|
|
|
|
|
|
txt_delete_line(text, tmpl->next);
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->sell = text->curl;
|
|
|
|
text->selc = text->curc;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
void txt_sel_all(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
text->curl = text->lines.first;
|
|
|
|
text->curc = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->sell = text->lines.last;
|
|
|
|
text->selc = text->sell->len;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 14:52:23 +10:00
|
|
|
/**
|
|
|
|
* Reverse of #txt_pop_sel
|
|
|
|
* Clears the selection and ensures the cursor is located
|
|
|
|
* at the selection (where the cursor is visually while editing).
|
|
|
|
*/
|
|
|
|
void txt_sel_clear(Text *text)
|
|
|
|
{
|
|
|
|
if (text->sell) {
|
|
|
|
text->curl = text->sell;
|
|
|
|
text->curc = text->selc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
void txt_sel_line(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
if (!text->curl) return;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->curc = 0;
|
|
|
|
text->sell = text->curl;
|
|
|
|
text->selc = text->sell->len;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************/
|
|
|
|
/* Cut and paste functions */
|
|
|
|
/***************************/
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
char *txt_to_buf(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
int length;
|
|
|
|
TextLine *tmp, *linef, *linel;
|
|
|
|
int charf, charl;
|
|
|
|
char *buf;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (!text->curl) return NULL;
|
|
|
|
if (!text->sell) return NULL;
|
2008-07-18 23:35:34 +00:00
|
|
|
if (!text->lines.first) return NULL;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
linef = text->lines.first;
|
|
|
|
charf = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
linel = text->lines.last;
|
|
|
|
charl = linel->len;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (linef == text->lines.last) {
|
2012-05-06 15:15:33 +00:00
|
|
|
length = charl - charf;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf = MEM_mallocN(length + 2, "text buffer");
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
BLI_strncpy(buf, linef->line + charf, length + 1);
|
|
|
|
buf[length] = 0;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
length = linef->len - charf;
|
|
|
|
length += charl;
|
|
|
|
length += 2; /* For the 2 '\n' */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = linef->next;
|
|
|
|
while (tmp && tmp != linel) {
|
|
|
|
length += tmp->len + 1;
|
|
|
|
tmp = tmp->next;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf = MEM_mallocN(length + 1, "cut buffer");
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
strncpy(buf, linef->line + charf, linef->len - charf);
|
|
|
|
length = linef->len - charf;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf[length++] = '\n';
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = linef->next;
|
|
|
|
while (tmp && tmp != linel) {
|
|
|
|
strncpy(buf + length, tmp->line, tmp->len);
|
|
|
|
length += tmp->len;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf[length++] = '\n';
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = tmp->next;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
strncpy(buf + length, linel->line, charl);
|
|
|
|
length += charl;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* python compiler wants an empty end line */
|
2012-05-06 15:15:33 +00:00
|
|
|
buf[length++] = '\n';
|
|
|
|
buf[length] = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2011-11-05 11:04:28 +00:00
|
|
|
int txt_find_string(Text *text, const char *findstr, int wrap, int match_case)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
TextLine *tl, *startl;
|
2014-04-27 00:20:13 +10:00
|
|
|
const char *s = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2014-10-06 12:23:47 +02:00
|
|
|
if (!text->curl || !text->sell) return 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2013-09-02 00:47:27 +00:00
|
|
|
txt_order_cursors(text, false);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tl = startl = text->sell;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (match_case) s = strstr(&tl->line[text->selc], findstr);
|
|
|
|
else s = BLI_strcasestr(&tl->line[text->selc], findstr);
|
2002-10-12 11:37:38 +00:00
|
|
|
while (!s) {
|
2012-05-06 15:15:33 +00:00
|
|
|
tl = tl->next;
|
2008-07-23 19:35:13 +00:00
|
|
|
if (!tl) {
|
|
|
|
if (wrap)
|
2012-05-06 15:15:33 +00:00
|
|
|
tl = text->lines.first;
|
2008-07-23 19:35:13 +00:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (match_case) s = strstr(tl->line, findstr);
|
|
|
|
else s = BLI_strcasestr(tl->line, findstr);
|
|
|
|
if (tl == startl)
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s) {
|
2012-05-06 15:15:33 +00:00
|
|
|
int newl = txt_get_span(text->lines.first, tl);
|
|
|
|
int newc = (int)(s - tl->line);
|
2008-07-23 19:35:13 +00:00
|
|
|
txt_move_to(text, newl, newc, 0);
|
|
|
|
txt_move_to(text, newl, newc + strlen(findstr), 1);
|
2012-10-21 05:46:41 +00:00
|
|
|
return 1;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else
|
2002-10-12 11:37:38 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
char *txt_sel_to_buf(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
char *buf;
|
2012-05-06 15:15:33 +00:00
|
|
|
int length = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
TextLine *tmp, *linef, *linel;
|
|
|
|
int charf, charl;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (!text->curl) return NULL;
|
|
|
|
if (!text->sell) return NULL;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (text->curl == text->sell) {
|
|
|
|
linef = linel = text->curl;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (text->curc < text->selc) {
|
2012-05-06 15:15:33 +00:00
|
|
|
charf = text->curc;
|
|
|
|
charl = text->selc;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
charf = text->selc;
|
|
|
|
charl = text->curc;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (txt_get_span(text->curl, text->sell) < 0) {
|
|
|
|
linef = text->sell;
|
|
|
|
linel = text->curl;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
charf = text->selc;
|
|
|
|
charl = text->curc;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
linef = text->curl;
|
|
|
|
linel = text->sell;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
charf = text->curc;
|
|
|
|
charl = text->selc;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (linef == linel) {
|
2012-05-06 15:15:33 +00:00
|
|
|
length = charl - charf;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf = MEM_mallocN(length + 1, "sel buffer");
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
BLI_strncpy(buf, linef->line + charf, length + 1);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
length += linef->len - charf;
|
|
|
|
length += charl;
|
2002-10-12 11:37:38 +00:00
|
|
|
length++; /* For the '\n' */
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = linef->next;
|
|
|
|
while (tmp && tmp != linel) {
|
|
|
|
length += tmp->len + 1;
|
|
|
|
tmp = tmp->next;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf = MEM_mallocN(length + 1, "sel buffer");
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
strncpy(buf, linef->line + charf, linef->len - charf);
|
|
|
|
length = linef->len - charf;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf[length++] = '\n';
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = linef->next;
|
|
|
|
while (tmp && tmp != linel) {
|
|
|
|
strncpy(buf + length, tmp->line, tmp->len);
|
|
|
|
length += tmp->len;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf[length++] = '\n';
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = tmp->next;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
strncpy(buf + length, linel->line, charl);
|
|
|
|
length += charl;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf[length] = 0;
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2009-09-16 06:02:56 +00:00
|
|
|
void txt_insert_buf(Text *text, const char *in_buffer)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-11-23 14:33:14 +00:00
|
|
|
int l = 0, u, len;
|
2012-05-06 15:15:33 +00:00
|
|
|
size_t i = 0, j;
|
2002-10-12 11:37:38 +00:00
|
|
|
TextLine *add;
|
2012-01-16 16:23:25 +00:00
|
|
|
char *buffer;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (!in_buffer) return;
|
|
|
|
|
|
|
|
txt_delete_sel(text);
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
len = strlen(in_buffer);
|
|
|
|
buffer = BLI_strdupn(in_buffer, len);
|
|
|
|
len += txt_extended_ascii_as_utf8(&buffer);
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
if (!undoing) txt_undo_add_blockop(text, UNDO_IBLOCK, buffer);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
u = undoing;
|
|
|
|
undoing = 1;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* Read the first line (or as close as possible */
|
2012-05-06 15:15:33 +00:00
|
|
|
while (buffer[i] && buffer[i] != '\n')
|
2012-01-16 16:23:25 +00:00
|
|
|
txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &i));
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (buffer[i] == '\n') txt_split_curline(text);
|
2012-01-16 16:23:25 +00:00
|
|
|
else { undoing = u; MEM_freeN(buffer); return; }
|
2002-10-12 11:37:38 +00:00
|
|
|
i++;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
while (i < len) {
|
|
|
|
l = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
while (buffer[i] && buffer[i] != '\n') {
|
2002-10-12 11:37:38 +00:00
|
|
|
i++; l++;
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (buffer[i] == '\n') {
|
|
|
|
add = txt_new_linen(buffer + (i - l), l);
|
2002-10-12 11:37:38 +00:00
|
|
|
BLI_insertlinkbefore(&text->lines, text->curl, add);
|
|
|
|
i++;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
for (j = i - l; j < i && j < len; )
|
2012-01-16 16:23:25 +00:00
|
|
|
txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j));
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-01-16 16:23:25 +00:00
|
|
|
|
|
|
|
MEM_freeN(buffer);
|
2011-04-20 07:44:42 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
undoing = u;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************/
|
|
|
|
/* Undo functions */
|
|
|
|
/******************/
|
|
|
|
|
2014-02-05 22:36:15 +11:00
|
|
|
static bool max_undo_test(Text *text, int x)
|
2009-04-27 10:00:22 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
while (text->undo_pos + x >= text->undo_len) {
|
|
|
|
if (text->undo_len * 2 > TXT_MAX_UNDO) {
|
2009-04-27 10:00:22 +00:00
|
|
|
/* XXX error("Undo limit reached, buffer cleared\n"); */
|
|
|
|
MEM_freeN(text->undo_buf);
|
2010-01-16 14:05:39 +00:00
|
|
|
init_undo_text(text);
|
2014-12-01 17:11:18 +01:00
|
|
|
return false;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
void *tmp = text->undo_buf;
|
|
|
|
text->undo_buf = MEM_callocN(text->undo_len * 2, "undo buf");
|
2009-04-27 10:00:22 +00:00
|
|
|
memcpy(text->undo_buf, tmp, text->undo_len);
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_len *= 2;
|
2009-04-27 10:00:22 +00:00
|
|
|
MEM_freeN(tmp);
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
2009-04-27 10:00:22 +00:00
|
|
|
}
|
|
|
|
|
2013-07-21 17:05:41 +00:00
|
|
|
#if 0 /* UNUSED */
|
2006-11-26 16:03:36 +00:00
|
|
|
static void dump_buffer(Text *text)
|
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
int i = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
while (i++ < text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* Note: this function is outdated and must be updated if needed for future use */
|
2002-10-12 11:37:38 +00:00
|
|
|
void txt_print_undo(Text *text)
|
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
int i = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
int op;
|
2010-12-03 17:05:21 +00:00
|
|
|
const char *ops;
|
2002-10-12 11:37:38 +00:00
|
|
|
int linep, charp;
|
|
|
|
|
|
|
|
dump_buffer(text);
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
printf("---< Undo Buffer >---\n");
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
printf("UndoPosition is %d\n", text->undo_pos);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
while (i <= text->undo_pos) {
|
|
|
|
op = text->undo_buf[i];
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
if (op == UNDO_INSERT_1) {
|
2012-05-06 15:15:33 +00:00
|
|
|
ops = "Insert ascii ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_INSERT_2) {
|
|
|
|
ops = "Insert 2 bytes ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_INSERT_3) {
|
|
|
|
ops = "Insert 3 bytes ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_INSERT_4) {
|
|
|
|
ops = "Insert unicode ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_BS_1) {
|
|
|
|
ops = "Backspace for ascii ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_BS_2) {
|
|
|
|
ops = "Backspace for 2 bytes ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_BS_3) {
|
|
|
|
ops = "Backspace for 3 bytes ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_BS_4) {
|
|
|
|
ops = "Backspace for unicode ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_DEL_1) {
|
|
|
|
ops = "Delete ascii ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_DEL_2) {
|
|
|
|
ops = "Delete 2 bytes ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_DEL_3) {
|
|
|
|
ops = "Delete 3 bytes ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_DEL_4) {
|
|
|
|
ops = "Delete unicode ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_DBLOCK) {
|
|
|
|
ops = "Delete text block";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_IBLOCK) {
|
|
|
|
ops = "Insert text block";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_INDENT) {
|
|
|
|
ops = "Indent ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_UNINDENT) {
|
|
|
|
ops = "Unindent ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_COMMENT) {
|
|
|
|
ops = "Comment ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_UNCOMMENT) {
|
|
|
|
ops = "Uncomment ";
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
ops = "Unknown";
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
printf("Op (%o) at %d = %s", op, i, ops);
|
2012-01-16 16:23:25 +00:00
|
|
|
if (op >= UNDO_INSERT_1 && op <= UNDO_DEL_4) {
|
2002-10-12 11:37:38 +00:00
|
|
|
i++;
|
2012-05-06 15:15:33 +00:00
|
|
|
printf(" - Char is ");
|
2012-01-16 16:23:25 +00:00
|
|
|
switch (op) {
|
|
|
|
case UNDO_INSERT_1: case UNDO_BS_1: case UNDO_DEL_1:
|
2012-05-06 15:15:33 +00:00
|
|
|
printf("%c", text->undo_buf[i]);
|
2012-01-16 16:23:25 +00:00
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
case UNDO_INSERT_2: case UNDO_BS_2: case UNDO_DEL_2:
|
2012-05-06 15:15:33 +00:00
|
|
|
printf("%c%c", text->undo_buf[i], text->undo_buf[i + 1]);
|
|
|
|
i += 2;
|
2012-01-16 16:23:25 +00:00
|
|
|
break;
|
|
|
|
case UNDO_INSERT_3: case UNDO_BS_3: case UNDO_DEL_3:
|
2012-05-06 15:15:33 +00:00
|
|
|
printf("%c%c%c", text->undo_buf[i], text->undo_buf[i + 1], text->undo_buf[i + 2]);
|
|
|
|
i += 3;
|
2012-01-16 16:23:25 +00:00
|
|
|
break;
|
2012-09-08 08:59:47 +00:00
|
|
|
case UNDO_INSERT_4: case UNDO_BS_4: case UNDO_DEL_4:
|
|
|
|
{
|
2012-01-16 16:23:25 +00:00
|
|
|
unsigned int uc;
|
2012-05-06 15:15:33 +00:00
|
|
|
char c[BLI_UTF8_MAX + 1];
|
2012-01-16 16:23:25 +00:00
|
|
|
size_t c_len;
|
2012-05-06 15:15:33 +00:00
|
|
|
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';
|
2012-03-18 06:01:33 +00:00
|
|
|
puts(c);
|
2013-07-21 08:16:37 +00:00
|
|
|
break;
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_DBLOCK || op == UNDO_IBLOCK) {
|
2002-10-12 11:37:38 +00:00
|
|
|
i++;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
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++;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
printf(" (length %d) <", linep);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
while (linep > 0) {
|
2002-10-12 11:37:38 +00:00
|
|
|
putchar(text->undo_buf[i]);
|
|
|
|
linep--; i++;
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
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);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (op == UNDO_INDENT || op == UNDO_UNINDENT) {
|
2005-12-12 18:35:15 +00:00
|
|
|
i++;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
charp = text->undo_buf[i]; i++;
|
|
|
|
charp = charp + (text->undo_buf[i] << 8); i++;
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
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++;
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
printf("to <%d, %d> ", linep, charp);
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
charp = text->undo_buf[i]; i++;
|
|
|
|
charp = charp + (text->undo_buf[i] << 8); i++;
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
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++;
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
printf("from <%d, %d>", linep, charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
printf(" %d\n", i);
|
2002-10-12 11:37:38 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
2013-07-21 17:05:41 +00:00
|
|
|
#endif
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
static void txt_undo_store_uint16(char *undo_buf, int *undo_pos, unsigned short value)
|
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
undo_buf[*undo_pos] = (value) & 0xff;
|
2012-01-16 16:23:25 +00:00
|
|
|
(*undo_pos)++;
|
2012-05-06 15:15:33 +00:00
|
|
|
undo_buf[*undo_pos] = (value >> 8) & 0xff;
|
2012-01-16 16:23:25 +00:00
|
|
|
(*undo_pos)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int value)
|
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
undo_buf[*undo_pos] = (value) & 0xff;
|
2012-01-16 16:23:25 +00:00
|
|
|
(*undo_pos)++;
|
2012-05-06 15:15:33 +00:00
|
|
|
undo_buf[*undo_pos] = (value >> 8) & 0xff;
|
2012-01-16 16:23:25 +00:00
|
|
|
(*undo_pos)++;
|
2012-05-06 15:15:33 +00:00
|
|
|
undo_buf[*undo_pos] = (value >> 16) & 0xff;
|
2012-01-16 16:23:25 +00:00
|
|
|
(*undo_pos)++;
|
2012-05-06 15:15:33 +00:00
|
|
|
undo_buf[*undo_pos] = (value >> 24) & 0xff;
|
2012-01-16 16:23:25 +00:00
|
|
|
(*undo_pos)++;
|
|
|
|
}
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* store the cur cursor to the undo buffer */
|
|
|
|
static void txt_undo_store_cur(Text *text)
|
|
|
|
{
|
|
|
|
txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->curc);
|
|
|
|
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->curl));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store the sel cursor to the undo buffer */
|
|
|
|
static void txt_undo_store_sel(Text *text)
|
|
|
|
{
|
|
|
|
txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->selc);
|
|
|
|
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->sell));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store both cursors to the undo buffer */
|
|
|
|
static void txt_undo_store_cursors(Text *text)
|
|
|
|
{
|
|
|
|
txt_undo_store_cur(text);
|
|
|
|
txt_undo_store_sel(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store an operator along with a block of data */
|
|
|
|
static void txt_undo_add_blockop(Text *text, int op, const char *buf)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
unsigned int length = strlen(buf);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
if (!max_undo_test(text, length + 11 + 12))
|
2009-04-27 10:00:22 +00:00
|
|
|
return;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
text->undo_pos++;
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos] = op;
|
2002-10-12 11:37:38 +00:00
|
|
|
text->undo_pos++;
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
txt_undo_store_cursors(text);
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
strncpy(text->undo_buf + text->undo_pos, buf, length);
|
|
|
|
text->undo_pos += length;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos] = op;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos + 1] = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* store a regular operator */
|
|
|
|
void txt_undo_add_op(Text *text, int op)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!max_undo_test(text, 15))
|
2009-04-27 10:00:22 +00:00
|
|
|
return;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
text->undo_pos++;
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos] = op;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
text->undo_pos++;
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
txt_undo_store_cursors(text);
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos] = op;
|
2012-11-15 02:11:40 +00:00
|
|
|
text->undo_buf[text->undo_pos + 1] = 0;
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* store an operator for a single character */
|
2012-01-16 16:23:25 +00:00
|
|
|
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);
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
if (!max_undo_test(text, 3 + utf8_size + 12))
|
2012-01-16 16:23:25 +00:00
|
|
|
return;
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
text->undo_pos++;
|
2012-01-16 16:23:25 +00:00
|
|
|
|
|
|
|
if (utf8_size < 4) {
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos] = op_start + utf8_size - 1;
|
2012-01-16 16:23:25 +00:00
|
|
|
text->undo_pos++;
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
txt_undo_store_cur(text);
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
for (i = 0; i < utf8_size; i++) {
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos] = utf8[i];
|
2012-01-16 16:23:25 +00:00
|
|
|
text->undo_pos++;
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos] = op_start + utf8_size - 1;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos] = op_start + 3;
|
2012-01-16 16:23:25 +00:00
|
|
|
text->undo_pos++;
|
2012-11-14 23:10:19 +00:00
|
|
|
|
|
|
|
txt_undo_store_cursors(text);
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c);
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos] = op_start + 3;
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_buf[text->undo_pos + 1] = 0;
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2015-05-07 04:43:33 +10:00
|
|
|
/* extends Link */
|
|
|
|
struct LinkInt {
|
|
|
|
struct LinkInt *next, *prev;
|
|
|
|
int value;
|
|
|
|
};
|
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
/**
|
|
|
|
* UnindentLines points to a #ListBase composed of #LinkInt elements, listing the numbers
|
|
|
|
* of the lines that should not be indented back.
|
|
|
|
*/
|
|
|
|
static void txt_undo_add_unprefix_op(
|
|
|
|
Text *text, char undo_op,
|
|
|
|
const ListBase *line_index_mask, const int line_index_mask_len)
|
2015-05-07 04:43:33 +10:00
|
|
|
{
|
|
|
|
struct LinkInt *idata;
|
|
|
|
|
|
|
|
BLI_assert(BLI_listbase_count(line_index_mask) == line_index_mask_len);
|
|
|
|
|
|
|
|
/* OP byte + UInt32 count + counted UInt32 line numbers + UInt32 count + 12-bytes selection + OP byte */
|
|
|
|
if (!max_undo_test(text, 1 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Opening buffer sequence with OP */
|
|
|
|
text->undo_pos++;
|
2015-09-16 03:30:02 +10:00
|
|
|
text->undo_buf[text->undo_pos] = undo_op;
|
2015-05-07 04:43:33 +10:00
|
|
|
text->undo_pos++;
|
|
|
|
/* Adding number of line numbers to read */
|
|
|
|
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
|
|
|
|
|
|
|
|
/* Adding linenumbers of lines that shall not be indented if undoing */
|
|
|
|
for (idata = line_index_mask->first; idata; idata = idata->next) {
|
|
|
|
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, idata->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Adding number of line numbers to read again */
|
|
|
|
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
|
|
|
|
/* Adding current selection */
|
|
|
|
txt_undo_store_cursors(text);
|
|
|
|
/* Closing with OP (same as above) */
|
2015-09-16 03:30:02 +10:00
|
|
|
text->undo_buf[text->undo_pos] = undo_op;
|
2015-05-07 04:43:33 +10:00
|
|
|
/* Marking as last undo operation */
|
|
|
|
text->undo_buf[text->undo_pos + 1] = 0;
|
|
|
|
}
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos)
|
|
|
|
{
|
|
|
|
unsigned short val;
|
2012-05-06 15:15:33 +00:00
|
|
|
val = undo_buf[*undo_pos]; (*undo_pos)--;
|
|
|
|
val = (val << 8) + undo_buf[*undo_pos]; (*undo_pos)--;
|
2012-01-16 16:23:25 +00:00
|
|
|
return val;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
static unsigned int txt_undo_read_uint32(const char *undo_buf, int *undo_pos)
|
|
|
|
{
|
|
|
|
unsigned int val;
|
2012-05-06 15:15:33 +00:00
|
|
|
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)--;
|
2012-01-16 16:23:25 +00:00
|
|
|
return val;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* read the cur cursor from the undo buffer */
|
|
|
|
static void txt_undo_read_cur(const char *undo_buf, int *undo_pos, unsigned int *curln, unsigned short *curc)
|
|
|
|
{
|
|
|
|
*curln = txt_undo_read_uint32(undo_buf, undo_pos);
|
|
|
|
*curc = txt_undo_read_uint16(undo_buf, undo_pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read the sel cursor from the undo buffer */
|
|
|
|
static void txt_undo_read_sel(const char *undo_buf, int *undo_pos, unsigned int *selln, unsigned short *selc)
|
|
|
|
{
|
|
|
|
*selln = txt_undo_read_uint32(undo_buf, undo_pos);
|
|
|
|
*selc = txt_undo_read_uint16(undo_buf, undo_pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read both cursors from the undo buffer */
|
|
|
|
static void txt_undo_read_cursors(const char *undo_buf, int *undo_pos,
|
|
|
|
unsigned int *curln, unsigned short *curc,
|
|
|
|
unsigned int *selln, unsigned short *selc)
|
|
|
|
{
|
|
|
|
txt_undo_read_sel(undo_buf, undo_pos, selln, selc);
|
|
|
|
txt_undo_read_cur(undo_buf, undo_pos, curln, curc);
|
|
|
|
}
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, short bytes)
|
|
|
|
{
|
|
|
|
unsigned int unicode;
|
2012-05-06 15:15:33 +00:00
|
|
|
char utf8[BLI_UTF8_MAX + 1];
|
2012-01-16 16:23:25 +00:00
|
|
|
|
|
|
|
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)--;
|
2012-05-06 15:15:33 +00:00
|
|
|
unicode = BLI_str_utf8_as_unicode(utf8);
|
2012-01-16 16:23:25 +00:00
|
|
|
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)--;
|
2012-05-06 15:15:33 +00:00
|
|
|
unicode = BLI_str_utf8_as_unicode(utf8);
|
2012-01-16 16:23:25 +00:00
|
|
|
break;
|
|
|
|
case 4: /* 32-bit unicode symbol */
|
2012-05-06 15:15:33 +00:00
|
|
|
unicode = txt_undo_read_uint32(undo_buf, undo_pos);
|
2012-09-15 10:40:05 +00:00
|
|
|
break;
|
2012-01-22 17:26:56 +00:00
|
|
|
default:
|
|
|
|
/* should never happen */
|
|
|
|
BLI_assert(0);
|
2012-05-06 15:15:33 +00:00
|
|
|
unicode = 0;
|
2013-07-21 08:16:37 +00:00
|
|
|
break;
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return unicode;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
static unsigned short txt_redo_read_uint16(const char *undo_buf, int *undo_pos)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-01-16 16:23:25 +00:00
|
|
|
unsigned short val;
|
|
|
|
val = undo_buf[*undo_pos]; (*undo_pos)++;
|
2012-05-06 15:15:33 +00:00
|
|
|
val = val + (undo_buf[*undo_pos] << 8); (*undo_pos)++;
|
2012-01-16 16:23:25 +00:00
|
|
|
return val;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
static unsigned int txt_redo_read_uint32(const char *undo_buf, int *undo_pos)
|
|
|
|
{
|
|
|
|
unsigned int val;
|
2012-05-06 15:15:33 +00:00
|
|
|
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)++;
|
2012-01-16 16:23:25 +00:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* redo read cur cursor from the undo buffer */
|
|
|
|
static void txt_redo_read_cur(const char *undo_buf, int *undo_pos, unsigned int *curln, unsigned short *curc)
|
|
|
|
{
|
|
|
|
*curc = txt_redo_read_uint16(undo_buf, undo_pos);
|
|
|
|
*curln = txt_redo_read_uint32(undo_buf, undo_pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* redo read sel cursor from the undo buffer */
|
|
|
|
static void txt_redo_read_sel(const char *undo_buf, int *undo_pos, unsigned int *selln, unsigned short *selc)
|
|
|
|
{
|
|
|
|
*selc = txt_redo_read_uint16(undo_buf, undo_pos);
|
|
|
|
*selln = txt_redo_read_uint32(undo_buf, undo_pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* redo read both cursors from the undo buffer */
|
|
|
|
static void txt_redo_read_cursors(const char *undo_buf, int *undo_pos,
|
|
|
|
unsigned int *curln, unsigned short *curc,
|
|
|
|
unsigned int *selln, unsigned short *selc)
|
|
|
|
{
|
|
|
|
txt_redo_read_cur(undo_buf, undo_pos, curln, curc);
|
|
|
|
txt_redo_read_sel(undo_buf, undo_pos, selln, selc);
|
|
|
|
}
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, short bytes)
|
|
|
|
{
|
|
|
|
unsigned int unicode;
|
2012-05-06 15:15:33 +00:00
|
|
|
char utf8[BLI_UTF8_MAX + 1];
|
2012-01-16 16:23:25 +00:00
|
|
|
|
|
|
|
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';
|
2012-05-06 15:15:33 +00:00
|
|
|
unicode = BLI_str_utf8_as_unicode(utf8);
|
2012-01-16 16:23:25 +00:00
|
|
|
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';
|
2012-05-06 15:15:33 +00:00
|
|
|
unicode = BLI_str_utf8_as_unicode(utf8);
|
2012-01-16 16:23:25 +00:00
|
|
|
break;
|
|
|
|
case 4: /* 32-bit unicode symbol */
|
2012-05-06 15:15:33 +00:00
|
|
|
unicode = txt_undo_read_uint32(undo_buf, undo_pos);
|
2012-09-19 08:07:23 +00:00
|
|
|
break;
|
2012-01-20 15:18:57 +00:00
|
|
|
default:
|
|
|
|
/* should never happen */
|
|
|
|
BLI_assert(0);
|
2012-05-06 15:15:33 +00:00
|
|
|
unicode = 0;
|
2013-07-21 08:16:37 +00:00
|
|
|
break;
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return unicode;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void txt_do_undo(Text *text)
|
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
int op = text->undo_buf[text->undo_pos];
|
2013-09-05 21:36:19 +00:00
|
|
|
int prev_flags;
|
2015-11-23 11:27:02 +11:00
|
|
|
unsigned int linep;
|
2017-02-06 15:29:13 +01:00
|
|
|
unsigned int uni_char;
|
2012-11-14 23:10:19 +00:00
|
|
|
unsigned int curln, selln;
|
|
|
|
unsigned short curc, selc;
|
2002-10-12 11:37:38 +00:00
|
|
|
unsigned short charp;
|
|
|
|
char *buf;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (text->undo_pos < 0) {
|
2002-10-12 11:37:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
text->undo_pos--;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
undoing = 1;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (op) {
|
2012-11-14 23:10:19 +00:00
|
|
|
case UNDO_INSERT_1:
|
|
|
|
case UNDO_INSERT_2:
|
|
|
|
case UNDO_INSERT_3:
|
|
|
|
case UNDO_INSERT_4:
|
|
|
|
text->undo_pos -= op - UNDO_INSERT_1 + 1;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, curln, curc, 1);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
txt_delete_char(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
text->undo_pos--;
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
case UNDO_BS_1:
|
|
|
|
case UNDO_BS_2:
|
|
|
|
case UNDO_BS_3:
|
|
|
|
case UNDO_BS_4:
|
|
|
|
charp = op - UNDO_BS_1 + 1;
|
2017-02-06 15:29:13 +01:00
|
|
|
uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, curln, curc, 1);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2017-02-06 15:29:13 +01:00
|
|
|
txt_add_char(text, uni_char);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
text->undo_pos--;
|
2012-10-21 05:46:41 +00:00
|
|
|
break;
|
2012-11-14 23:10:19 +00:00
|
|
|
|
|
|
|
case UNDO_DEL_1:
|
|
|
|
case UNDO_DEL_2:
|
|
|
|
case UNDO_DEL_3:
|
|
|
|
case UNDO_DEL_4:
|
2012-01-16 16:23:25 +00:00
|
|
|
charp = op - UNDO_DEL_1 + 1;
|
2017-02-06 15:29:13 +01:00
|
|
|
uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
|
2012-11-14 23:10:19 +00:00
|
|
|
|
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, curln, curc, 1);
|
|
|
|
|
2017-02-06 15:29:13 +01:00
|
|
|
txt_add_char(text, uni_char);
|
2012-11-14 23:10:19 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
txt_move_left(text, 0);
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
text->undo_pos--;
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case UNDO_DBLOCK:
|
2015-11-23 11:27:02 +11:00
|
|
|
{
|
|
|
|
int i;
|
2012-11-14 23:10:19 +00:00
|
|
|
/* length of the string in the buffer */
|
2012-05-06 15:15:33 +00:00
|
|
|
linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf = MEM_mallocN(linep + 1, "dblock buffer");
|
|
|
|
for (i = 0; i < linep; i++) {
|
|
|
|
buf[(linep - 1) - i] = text->undo_buf[text->undo_pos];
|
2002-10-12 11:37:38 +00:00
|
|
|
text->undo_pos--;
|
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
buf[i] = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* skip over the length that was stored again */
|
2013-07-21 08:34:02 +00:00
|
|
|
text->undo_pos -= 4;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* Get the cursor positions */
|
|
|
|
txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
|
|
|
|
|
|
|
|
/* move cur to location that needs buff inserted */
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
|
|
|
|
txt_insert_buf(text, buf);
|
|
|
|
MEM_freeN(buf);
|
|
|
|
|
|
|
|
/* restore the cursors */
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, selln, selc, 1);
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
text->undo_pos--;
|
|
|
|
|
|
|
|
break;
|
2015-11-23 11:27:02 +11:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
case UNDO_IBLOCK:
|
2015-11-23 11:27:02 +11:00
|
|
|
{
|
|
|
|
int i;
|
2012-11-14 23:10:19 +00:00
|
|
|
/* length of the string in the buffer */
|
2012-05-06 15:15:33 +00:00
|
|
|
linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
|
2012-05-04 14:27:13 +00:00
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
/* txt_backspace_char removes utf8-characters, not bytes */
|
2012-05-06 15:15:33 +00:00
|
|
|
buf = MEM_mallocN(linep + 1, "iblock buffer");
|
|
|
|
for (i = 0; i < linep; i++) {
|
|
|
|
buf[(linep - 1) - i] = text->undo_buf[text->undo_pos];
|
2012-01-16 16:23:25 +00:00
|
|
|
text->undo_pos--;
|
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
buf[i] = 0;
|
2013-07-09 06:21:45 +00:00
|
|
|
linep = BLI_strlen_utf8(buf);
|
2012-01-16 16:23:25 +00:00
|
|
|
MEM_freeN(buf);
|
2012-05-04 14:27:13 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* skip over the length that was stored again */
|
2013-07-21 08:34:02 +00:00
|
|
|
text->undo_pos -= 4;
|
2012-11-14 23:10:19 +00:00
|
|
|
|
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
|
2012-11-30 22:46:28 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
txt_move_to(text, curln, curc, 0);
|
2012-11-30 22:46:28 +00:00
|
|
|
txt_move_to(text, selln, selc, 1);
|
|
|
|
|
|
|
|
if ((curln == selln) && (curc == selc)) {
|
2013-09-05 21:36:19 +00:00
|
|
|
/* disable tabs to spaces since moving right may involve skipping multiple spaces */
|
|
|
|
prev_flags = text->flags;
|
|
|
|
text->flags &= ~TXT_TABSTOSPACES;
|
|
|
|
|
2012-11-30 22:46:28 +00:00
|
|
|
for (i = 0; i < linep; i++)
|
|
|
|
txt_move_right(text, 1);
|
2013-09-05 21:36:19 +00:00
|
|
|
|
|
|
|
text->flags = prev_flags;
|
2012-11-30 22:46:28 +00:00
|
|
|
}
|
2012-05-04 14:27:13 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
txt_delete_selected(text);
|
|
|
|
|
|
|
|
text->undo_pos--;
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
2015-11-23 11:27:02 +11:00
|
|
|
}
|
2005-12-12 18:35:15 +00:00
|
|
|
case UNDO_INDENT:
|
|
|
|
case UNDO_COMMENT:
|
2012-11-14 23:10:19 +00:00
|
|
|
case UNDO_DUPLICATE:
|
|
|
|
case UNDO_MOVE_LINES_UP:
|
|
|
|
case UNDO_MOVE_LINES_DOWN:
|
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, selln, selc, 1);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (op == UNDO_INDENT) {
|
2011-05-23 08:14:29 +00:00
|
|
|
txt_unindent(text);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (op == UNDO_COMMENT) {
|
2011-05-23 08:14:29 +00:00
|
|
|
txt_uncomment(text);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-11-14 23:10:19 +00:00
|
|
|
else if (op == UNDO_DUPLICATE) {
|
|
|
|
txt_delete_line(text, text->curl->next);
|
|
|
|
}
|
|
|
|
else if (op == UNDO_MOVE_LINES_UP) {
|
|
|
|
txt_move_lines(text, TXT_MOVE_LINE_DOWN);
|
|
|
|
}
|
|
|
|
else if (op == UNDO_MOVE_LINES_DOWN) {
|
|
|
|
txt_move_lines(text, TXT_MOVE_LINE_UP);
|
|
|
|
}
|
2012-05-04 14:27:13 +00:00
|
|
|
|
2005-12-12 18:35:15 +00:00
|
|
|
text->undo_pos--;
|
|
|
|
break;
|
2015-05-07 04:43:33 +10:00
|
|
|
case UNDO_UNINDENT:
|
2015-09-16 03:30:02 +10:00
|
|
|
case UNDO_UNCOMMENT:
|
2015-05-07 04:43:33 +10:00
|
|
|
{
|
2015-09-16 03:30:02 +10:00
|
|
|
void (*txt_prefix_fn)(Text *);
|
|
|
|
void (*txt_unprefix_fn)(Text *);
|
2015-05-07 04:43:33 +10:00
|
|
|
int count;
|
|
|
|
int i;
|
|
|
|
/* Get and restore the cursors */
|
|
|
|
txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, selln, selc, 1);
|
|
|
|
|
|
|
|
/* Un-unindent */
|
2015-09-16 03:30:02 +10:00
|
|
|
if (op == UNDO_UNINDENT) {
|
|
|
|
txt_prefix_fn = txt_indent;
|
|
|
|
txt_unprefix_fn = txt_unindent;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
txt_prefix_fn = txt_comment;
|
|
|
|
txt_unprefix_fn = txt_uncomment;
|
|
|
|
}
|
|
|
|
|
|
|
|
txt_prefix_fn(text);
|
2015-05-07 04:43:33 +10:00
|
|
|
|
|
|
|
/* Get the count */
|
|
|
|
count = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
|
|
|
|
/* Iterate! */
|
|
|
|
txt_pop_sel(text);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
txt_move_to(text, txt_undo_read_uint32(text->undo_buf, &text->undo_pos), 0, 0);
|
2015-09-16 03:30:02 +10:00
|
|
|
/* Un-un-unindent/comment */
|
|
|
|
txt_unprefix_fn(text);
|
2015-05-07 04:43:33 +10:00
|
|
|
}
|
|
|
|
/* Restore selection */
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, selln, selc, 1);
|
|
|
|
/* Jumo over count */
|
|
|
|
txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
|
|
|
|
/* Jump over closing OP byte */
|
|
|
|
text->undo_pos--;
|
|
|
|
break;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
default:
|
2008-01-01 18:16:10 +00:00
|
|
|
//XXX error("Undo buffer error - resetting");
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_pos = -1;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
undoing = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void txt_do_redo(Text *text)
|
|
|
|
{
|
|
|
|
char op;
|
|
|
|
char *buf;
|
2012-11-14 23:10:19 +00:00
|
|
|
unsigned int linep;
|
|
|
|
unsigned short charp;
|
2017-02-06 15:29:13 +01:00
|
|
|
unsigned int uni_uchar;
|
2012-11-14 23:10:19 +00:00
|
|
|
unsigned int curln, selln;
|
|
|
|
unsigned short curc, selc;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
text->undo_pos++;
|
2012-05-06 15:15:33 +00:00
|
|
|
op = text->undo_buf[text->undo_pos];
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (!op) {
|
|
|
|
text->undo_pos--;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
undoing = 1;
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (op) {
|
2012-11-14 23:10:19 +00:00
|
|
|
case UNDO_INSERT_1:
|
|
|
|
case UNDO_INSERT_2:
|
|
|
|
case UNDO_INSERT_3:
|
|
|
|
case UNDO_INSERT_4:
|
|
|
|
text->undo_pos++;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, curln, curc, 1);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
charp = op - UNDO_INSERT_1 + 1;
|
2017-02-06 15:29:13 +01:00
|
|
|
uni_uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2017-02-06 15:29:13 +01:00
|
|
|
txt_add_char(text, uni_uchar);
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
case UNDO_BS_1:
|
|
|
|
case UNDO_BS_2:
|
|
|
|
case UNDO_BS_3:
|
|
|
|
case UNDO_BS_4:
|
2002-10-12 11:37:38 +00:00
|
|
|
text->undo_pos++;
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, curln, curc, 1);
|
|
|
|
|
|
|
|
text->undo_pos += op - UNDO_BS_1 + 1;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* move right so we backspace the correct char */
|
|
|
|
txt_move_right(text, 0);
|
|
|
|
txt_backspace_char(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
case UNDO_DEL_1:
|
|
|
|
case UNDO_DEL_2:
|
|
|
|
case UNDO_DEL_3:
|
|
|
|
case UNDO_DEL_4:
|
2002-10-12 11:37:38 +00:00
|
|
|
text->undo_pos++;
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, curln, curc, 1);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
text->undo_pos += op - UNDO_DEL_1 + 1;
|
|
|
|
|
|
|
|
txt_delete_char(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UNDO_DBLOCK:
|
|
|
|
text->undo_pos++;
|
2012-11-14 23:10:19 +00:00
|
|
|
|
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, selln, selc, 1);
|
|
|
|
|
|
|
|
/* length of the block */
|
2012-05-06 15:15:33 +00:00
|
|
|
linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_pos += linep;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* skip over the length that was stored again */
|
2013-07-21 08:34:02 +00:00
|
|
|
text->undo_pos += 4;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
txt_delete_sel(text);
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case UNDO_IBLOCK:
|
|
|
|
text->undo_pos++;
|
2012-11-14 23:10:19 +00:00
|
|
|
|
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, curln, curc, 1);
|
|
|
|
|
|
|
|
/* length of the block */
|
2012-05-06 15:15:33 +00:00
|
|
|
linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
buf = MEM_mallocN(linep + 1, "iblock buffer");
|
|
|
|
memcpy(buf, &text->undo_buf[text->undo_pos], linep);
|
|
|
|
text->undo_pos += linep;
|
|
|
|
buf[linep] = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
txt_insert_buf(text, buf);
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(buf);
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
/* skip over the length that was stored again */
|
2013-07-21 08:34:02 +00:00
|
|
|
text->undo_pos += 4;
|
2012-11-14 23:10:19 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2005-12-12 18:35:15 +00:00
|
|
|
case UNDO_INDENT:
|
|
|
|
case UNDO_COMMENT:
|
|
|
|
case UNDO_UNCOMMENT:
|
2012-11-14 23:10:19 +00:00
|
|
|
case UNDO_DUPLICATE:
|
|
|
|
case UNDO_MOVE_LINES_UP:
|
|
|
|
case UNDO_MOVE_LINES_DOWN:
|
2005-12-12 18:35:15 +00:00
|
|
|
text->undo_pos++;
|
2012-11-14 23:10:19 +00:00
|
|
|
|
|
|
|
/* get and restore the cursors */
|
|
|
|
txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, selln, selc, 1);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (op == UNDO_INDENT) {
|
2011-05-23 08:14:29 +00:00
|
|
|
txt_indent(text);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (op == UNDO_COMMENT) {
|
2011-05-23 08:14:29 +00:00
|
|
|
txt_comment(text);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (op == UNDO_UNCOMMENT) {
|
2011-05-23 08:14:29 +00:00
|
|
|
txt_uncomment(text);
|
2005-12-12 18:35:15 +00:00
|
|
|
}
|
2012-11-14 23:10:19 +00:00
|
|
|
else if (op == UNDO_DUPLICATE) {
|
|
|
|
txt_duplicate_line(text);
|
|
|
|
}
|
|
|
|
else if (op == UNDO_MOVE_LINES_UP) {
|
|
|
|
/* offset the cursor by + 1 */
|
|
|
|
txt_move_to(text, curln + 1, curc, 0);
|
|
|
|
txt_move_to(text, selln + 1, selc, 1);
|
|
|
|
|
|
|
|
txt_move_lines(text, TXT_MOVE_LINE_UP);
|
|
|
|
}
|
|
|
|
else if (op == UNDO_MOVE_LINES_DOWN) {
|
|
|
|
/* offset the cursor by - 1 */
|
|
|
|
txt_move_to(text, curln - 1, curc, 0);
|
|
|
|
txt_move_to(text, selln - 1, selc, 1);
|
|
|
|
|
|
|
|
txt_move_lines(text, TXT_MOVE_LINE_DOWN);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* re-restore the cursors since they got moved when redoing */
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, selln, selc, 1);
|
|
|
|
|
2012-05-04 14:27:13 +00:00
|
|
|
break;
|
2015-05-07 04:43:33 +10:00
|
|
|
case UNDO_UNINDENT:
|
|
|
|
{
|
|
|
|
int count;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
text->undo_pos++;
|
|
|
|
/* Scan all the stuff described in txt_undo_add_unindent_op */
|
|
|
|
count = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
|
|
|
|
}
|
|
|
|
/* Count again */
|
|
|
|
txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
|
|
|
|
/* Get the selection and re-unindent */
|
|
|
|
txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
|
|
|
|
txt_move_to(text, curln, curc, 0);
|
|
|
|
txt_move_to(text, selln, selc, 1);
|
|
|
|
txt_unindent(text);
|
|
|
|
break;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
default:
|
2008-01-01 18:16:10 +00:00
|
|
|
//XXX error("Undo buffer error - resetting");
|
2012-05-06 15:15:33 +00:00
|
|
|
text->undo_pos = -1;
|
2012-05-04 14:27:13 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
undoing = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**************************/
|
|
|
|
/* Line editing functions */
|
|
|
|
/**************************/
|
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
void txt_split_curline(Text *text)
|
2006-11-26 16:03:36 +00:00
|
|
|
{
|
2002-10-12 11:37:38 +00:00
|
|
|
TextLine *ins;
|
2008-07-28 11:05:35 +00:00
|
|
|
char *left, *right;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (!text->curl) return;
|
|
|
|
|
2008-08-04 23:01:47 +00:00
|
|
|
txt_delete_sel(text);
|
|
|
|
|
2012-11-30 22:46:28 +00:00
|
|
|
if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, '\n');
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
/* Make the two half strings */
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
left = MEM_mallocN(text->curc + 1, "textline_string");
|
2002-10-12 11:37:38 +00:00
|
|
|
if (text->curc) memcpy(left, text->curl->line, text->curc);
|
2012-05-06 15:15:33 +00:00
|
|
|
left[text->curc] = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
right = MEM_mallocN(text->curl->len - text->curc + 1, "textline_string");
|
|
|
|
memcpy(right, text->curl->line + text->curc, text->curl->len - text->curc + 1);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
MEM_freeN(text->curl->line);
|
2005-05-19 03:15:49 +00:00
|
|
|
if (text->curl->format) MEM_freeN(text->curl->format);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* Make the new TextLine */
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
ins = MEM_mallocN(sizeof(TextLine), "textline");
|
|
|
|
ins->line = left;
|
|
|
|
ins->format = NULL;
|
|
|
|
ins->len = text->curc;
|
|
|
|
|
|
|
|
text->curl->line = right;
|
|
|
|
text->curl->format = NULL;
|
|
|
|
text->curl->len = text->curl->len - text->curc;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
BLI_insertlinkbefore(&text->lines, text->curl, ins);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->curc = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
|
|
|
|
txt_pop_sel(text);
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_delete_line(Text *text, TextLine *line)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
if (!text->curl) return;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
BLI_remlink(&text->lines, line);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (line->line) MEM_freeN(line->line);
|
2005-05-13 16:11:28 +00:00
|
|
|
if (line->format) MEM_freeN(line->format);
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(line);
|
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2013-07-23 12:49:30 +00:00
|
|
|
char *tmp, *s;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!linea || !lineb) return;
|
2008-08-04 23:01:47 +00:00
|
|
|
|
2012-11-15 02:11:40 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = MEM_mallocN(linea->len + lineb->len + 1, "textline_string");
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2013-07-23 12:49:30 +00:00
|
|
|
s = tmp;
|
|
|
|
s += BLI_strcpy_rlen(s, linea->line);
|
|
|
|
s += BLI_strcpy_rlen(s, lineb->line);
|
|
|
|
(void)s;
|
2005-05-13 16:11:28 +00:00
|
|
|
|
2008-07-28 11:05:35 +00:00
|
|
|
make_new_line(linea, tmp);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2008-08-04 23:01:47 +00:00
|
|
|
txt_delete_line(text, lineb);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
}
|
|
|
|
|
2012-04-29 18:53:43 +00:00
|
|
|
void txt_duplicate_line(Text *text)
|
|
|
|
{
|
|
|
|
TextLine *textline;
|
|
|
|
|
2014-10-06 12:23:47 +02:00
|
|
|
if (!text->curl) return;
|
2012-04-29 18:53:43 +00:00
|
|
|
|
|
|
|
if (text->curl == text->sell) {
|
|
|
|
textline = txt_new_line(text->curl->line);
|
|
|
|
BLI_insertlinkafter(&text->lines, text->curl, textline);
|
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
|
|
|
|
if (!undoing) txt_undo_add_op(text, UNDO_DUPLICATE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
void txt_delete_char(Text *text)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
unsigned int c = '\n';
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (!text->curl) return;
|
|
|
|
|
2003-11-10 05:51:55 +00:00
|
|
|
if (txt_has_sel(text)) { /* deleting a selection */
|
2008-08-04 23:01:47 +00:00
|
|
|
txt_delete_sel(text);
|
2008-08-13 17:29:51 +00:00
|
|
|
txt_make_dirty(text);
|
2008-08-04 23:01:47 +00:00
|
|
|
return;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (text->curc == text->curl->len) { /* Appending two lines */
|
2002-10-12 11:37:38 +00:00
|
|
|
if (text->curl->next) {
|
|
|
|
txt_combine_lines(text, text->curl, text->curl->next);
|
|
|
|
txt_pop_sel(text);
|
|
|
|
}
|
2012-04-19 09:27:11 +00:00
|
|
|
else
|
|
|
|
return;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else { /* Just deleting a char */
|
2012-01-16 16:23:25 +00:00
|
|
|
size_t c_len = 0;
|
2012-05-06 15:15:33 +00:00
|
|
|
c = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &c_len);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
memmove(text->curl->line + text->curc, text->curl->line + text->curc + c_len, text->curl->len - text->curc - c_len + 1);
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->curl->len -= c_len;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
txt_pop_sel(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!undoing) txt_undo_add_charop(text, UNDO_DEL_1, c);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
void txt_delete_word(Text *text)
|
2008-06-04 23:20:54 +00:00
|
|
|
{
|
2013-02-14 03:03:12 +00:00
|
|
|
txt_jump_right(text, true, true);
|
2008-06-10 15:25:05 +00:00
|
|
|
txt_delete_sel(text);
|
2014-10-29 13:51:27 +01:00
|
|
|
txt_make_dirty(text);
|
2008-06-04 23:20:54 +00:00
|
|
|
}
|
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
void txt_backspace_char(Text *text)
|
2006-11-26 16:03:36 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
unsigned int c = '\n';
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (!text->curl) return;
|
|
|
|
|
2003-11-10 05:51:55 +00:00
|
|
|
if (txt_has_sel(text)) { /* deleting a selection */
|
2008-08-04 23:01:47 +00:00
|
|
|
txt_delete_sel(text);
|
2008-08-13 17:29:51 +00:00
|
|
|
txt_make_dirty(text);
|
2008-08-04 23:01:47 +00:00
|
|
|
return;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (text->curc == 0) { /* Appending two lines */
|
2008-06-04 16:03:19 +00:00
|
|
|
if (!text->curl->prev) return;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->curl = text->curl->prev;
|
|
|
|
text->curc = text->curl->len;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2008-06-04 16:03:19 +00:00
|
|
|
txt_combine_lines(text, text->curl, text->curl->next);
|
|
|
|
txt_pop_sel(text);
|
2008-08-04 23:01:47 +00:00
|
|
|
}
|
2003-11-10 05:51:55 +00:00
|
|
|
else { /* Just backspacing a char */
|
2012-01-16 16:23:25 +00:00
|
|
|
size_t c_len = 0;
|
2014-04-27 00:20:13 +10:00
|
|
|
const char *prev = BLI_str_prev_char_utf8(text->curl->line + text->curc);
|
2012-05-06 15:15:33 +00:00
|
|
|
c = BLI_str_utf8_as_unicode_and_size(prev, &c_len);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-04-26 02:24:55 +00:00
|
|
|
/* source and destination overlap, don't use memcpy() */
|
|
|
|
memmove(text->curl->line + text->curc - c_len,
|
|
|
|
text->curl->line + text->curc,
|
|
|
|
text->curl->len - text->curc + 1);
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->curl->len -= c_len;
|
|
|
|
text->curc -= c_len;
|
2008-08-04 23:01:47 +00:00
|
|
|
|
|
|
|
txt_pop_sel(text);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!undoing) txt_undo_add_charop(text, UNDO_BS_1, c);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
void txt_backspace_word(Text *text)
|
2008-06-04 23:20:54 +00:00
|
|
|
{
|
2013-02-14 03:03:12 +00:00
|
|
|
txt_jump_left(text, true, true);
|
2008-06-10 15:25:05 +00:00
|
|
|
txt_delete_sel(text);
|
2014-10-29 13:51:27 +01:00
|
|
|
txt_make_dirty(text);
|
2008-06-04 23:20:54 +00:00
|
|
|
}
|
|
|
|
|
2009-11-20 19:15:57 +00:00
|
|
|
/* Max spaces to replace a tab with, currently hardcoded to TXT_TABSIZE = 4.
|
2012-03-01 12:20:18 +00:00
|
|
|
* Used by txt_convert_tab_to_spaces, indent and unindent.
|
2009-11-20 19:15:57 +00:00
|
|
|
* Remember to change this string according to max tab size */
|
|
|
|
static char tab_to_spaces[] = " ";
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
static void txt_convert_tab_to_spaces(Text *text)
|
2009-11-20 19:15:57 +00:00
|
|
|
{
|
2010-02-09 11:18:17 +00:00
|
|
|
/* sb aims to pad adjust the tab-width needed so that the right number of spaces
|
|
|
|
* is added so that the indention of the line is the right width (i.e. aligned
|
|
|
|
* to multiples of TXT_TABSIZE)
|
|
|
|
*/
|
2014-04-27 00:20:13 +10:00
|
|
|
const char *sb = &tab_to_spaces[text->curc % TXT_TABSIZE];
|
2009-11-20 19:15:57 +00:00
|
|
|
txt_insert_buf(text, sb);
|
|
|
|
}
|
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
|
2006-11-26 16:03:36 +00:00
|
|
|
{
|
2012-01-16 16:23:25 +00:00
|
|
|
char *tmp, ch[BLI_UTF8_MAX];
|
|
|
|
size_t add_len;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (!text->curl) return 0;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (add == '\n') {
|
2002-10-12 11:37:38 +00:00
|
|
|
txt_split_curline(text);
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2011-05-28 13:11:24 +00:00
|
|
|
/* insert spaces rather than tabs */
|
2011-04-20 07:44:42 +00:00
|
|
|
if (add == '\t' && replace_tabs) {
|
2009-11-20 19:15:57 +00:00
|
|
|
txt_convert_tab_to_spaces(text);
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
2009-11-18 01:16:49 +00:00
|
|
|
}
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
txt_delete_sel(text);
|
|
|
|
|
2012-11-14 23:10:19 +00:00
|
|
|
if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add);
|
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
add_len = BLI_str_utf8_from_unicode(add, ch);
|
2008-08-04 23:01:47 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
tmp = MEM_mallocN(text->curl->len + add_len + 1, "textline_string");
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
memcpy(tmp, text->curl->line, text->curc);
|
2012-05-06 15:15:33 +00:00
|
|
|
memcpy(tmp + text->curc, ch, add_len);
|
|
|
|
memcpy(tmp + text->curc + add_len, text->curl->line + text->curc, text->curl->len - text->curc + 1);
|
2012-01-16 16:23:25 +00:00
|
|
|
|
2008-07-28 11:05:35 +00:00
|
|
|
make_new_line(text->curl, tmp);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
text->curc += add_len;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
txt_pop_sel(text);
|
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2004-10-14 23:37:04 +00:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
bool txt_add_char(Text *text, unsigned int add)
|
2011-04-20 07:44:42 +00:00
|
|
|
{
|
2014-04-01 11:34:00 +11:00
|
|
|
return txt_add_char_intern(text, add, (text->flags & TXT_TABSTOSPACES) != 0);
|
2011-04-20 07:44:42 +00:00
|
|
|
}
|
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
bool txt_add_raw_char(Text *text, unsigned int add)
|
2011-04-20 07:44:42 +00:00
|
|
|
{
|
|
|
|
return txt_add_char_intern(text, add, 0);
|
|
|
|
}
|
|
|
|
|
2.5: Text Editor back.
There was very little structure in this code, using many globals
and duplicated code. Now it should be better structured. Most
things should work, the main parts that are not back yet are the
python plugins and markers. Notes:
* Blenfont is used for drawing the text, nicely anti-aliased.
* A monospace truetype font was added, since that is needed for
the text editor. It's Bitstream Vera Sans Mono. This is the
default gnome terminal font, but it doesn't fit entirely well
with the other font I think, can be changed easily of course.
* Clipboard copy/cut/paste now always uses the system clipboard,
the code for the own cut buffer was removed.
* The interface buttons should support copy/cut/paste again now
as well.
* WM_clipboard_text_get/WM_clipboard_text_set were added to the
windowmanager code.
* Find panel is now a kind of second header, instead of a panel.
This needs especially a way to start editing the text field
immediately on open still.
* Operators are independent of the actual space when possible,
was a bit of puzzling but got it solved nice with notifiers,
and some lazy init for syntax highlight in the drawing code.
* RNA was created for the text editor space and used for buttons.
* Operators:
* New, Open, Reload, Save, Save As, Make Internal
* Run Script, Refresh Pyconstraints
* Copy, Cut, Paste
* Convert Whitespace, Uncomment, Comment, Indent, Unindent
* Line Break, Insert
* Next Marker, Previous Marker, Clear All Markers, Mark All
* Select Line, Select All
* Jump, Move, Move Select, Delete, Toggle Overwrite
* Scroll, Scroll Bar, Set Cursor, Line Number
* Find and Replace, Find, Replace, Find Set Selected,
Replace Set Selected
* To 3D Object
* Resolve Conflict
2009-02-28 23:33:35 +00:00
|
|
|
void txt_delete_selected(Text *text)
|
|
|
|
{
|
|
|
|
txt_delete_sel(text);
|
|
|
|
txt_make_dirty(text);
|
|
|
|
}
|
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
bool txt_replace_char(Text *text, unsigned int add)
|
2008-06-04 12:32:06 +00:00
|
|
|
{
|
2012-01-16 16:23:25 +00:00
|
|
|
unsigned int del;
|
|
|
|
size_t del_size = 0, add_size;
|
|
|
|
char ch[BLI_UTF8_MAX];
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2014-12-01 17:11:18 +01:00
|
|
|
if (!text->curl) return false;
|
2008-06-04 12:32:06 +00:00
|
|
|
|
|
|
|
/* If text is selected or we're at the end of the line just use txt_add_char */
|
2012-05-06 15:15:33 +00:00
|
|
|
if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') {
|
2012-11-23 14:33:14 +00:00
|
|
|
return txt_add_char(text, add);
|
2008-06-04 12:32:06 +00:00
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
del = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size);
|
|
|
|
add_size = BLI_str_utf8_from_unicode(add, ch);
|
2012-01-16 16:23:25 +00:00
|
|
|
|
|
|
|
if (add_size > del_size) {
|
2012-05-06 15:15:33 +00:00
|
|
|
char *tmp = MEM_mallocN(text->curl->len + add_size - del_size + 1, "textline_string");
|
2012-01-16 16:23:25 +00:00
|
|
|
memcpy(tmp, text->curl->line, text->curc);
|
2012-05-06 15:15:33 +00:00
|
|
|
memcpy(tmp + text->curc + add_size, text->curl->line + text->curc + del_size, text->curl->len - text->curc - del_size + 1);
|
2012-01-16 16:23:25 +00:00
|
|
|
MEM_freeN(text->curl->line);
|
|
|
|
text->curl->line = tmp;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (add_size < del_size) {
|
2012-05-06 15:15:33 +00:00
|
|
|
char *tmp = text->curl->line;
|
|
|
|
memmove(tmp + text->curc + add_size, tmp + text->curc + del_size, text->curl->len - text->curc - del_size + 1);
|
2012-01-16 16:23:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(text->curl->line + text->curc, ch, add_size);
|
2012-05-06 15:15:33 +00:00
|
|
|
text->curc += add_size;
|
2013-02-28 00:08:47 +00:00
|
|
|
text->curl->len += add_size - del_size;
|
2008-06-04 12:32:06 +00:00
|
|
|
|
2012-01-16 16:23:25 +00:00
|
|
|
txt_pop_sel(text);
|
2008-06-04 12:32:06 +00:00
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
|
|
|
|
/* Should probably create a new op for this */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!undoing) {
|
2012-01-16 16:23:25 +00:00
|
|
|
txt_undo_add_charop(text, UNDO_INSERT_1, add);
|
2014-01-20 22:12:35 +01:00
|
|
|
text->curc -= add_size;
|
|
|
|
txt_pop_sel(text);
|
2012-11-14 23:10:19 +00:00
|
|
|
txt_undo_add_charop(text, UNDO_DEL_1, del);
|
2014-01-20 22:12:35 +01:00
|
|
|
text->curc += add_size;
|
|
|
|
txt_pop_sel(text);
|
2008-06-04 12:32:06 +00:00
|
|
|
}
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
2008-06-04 12:32:06 +00:00
|
|
|
}
|
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
/**
|
|
|
|
* Generic prefix operation, use for comment & indent.
|
|
|
|
*
|
|
|
|
* \note caller must handle undo.
|
|
|
|
*/
|
|
|
|
static void txt_select_prefix(Text *text, const char *add)
|
2004-10-14 23:37:04 +00:00
|
|
|
{
|
2012-11-05 13:31:26 +00:00
|
|
|
int len, num, curc_old;
|
2008-07-28 11:05:35 +00:00
|
|
|
char *tmp;
|
2010-01-17 03:15:27 +00:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
const int indentlen = strlen(add);
|
2010-01-17 03:15:27 +00:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
BLI_assert(!ELEM(NULL, text->curl, text->sell));
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2012-11-05 13:31:26 +00:00
|
|
|
curc_old = text->curc;
|
|
|
|
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
num = 0;
|
2014-04-01 11:34:00 +11:00
|
|
|
while (true) {
|
2005-05-13 16:11:28 +00:00
|
|
|
|
2013-11-26 04:38:53 -02:00
|
|
|
/* don't indent blank lines */
|
|
|
|
if (text->curl->len != 0) {
|
|
|
|
tmp = MEM_mallocN(text->curl->len + indentlen + 1, "textline_string");
|
|
|
|
|
|
|
|
text->curc = 0;
|
|
|
|
if (text->curc) memcpy(tmp, text->curl->line, text->curc); /* XXX never true, check prev line */
|
|
|
|
memcpy(tmp + text->curc, add, indentlen);
|
|
|
|
|
|
|
|
len = text->curl->len - text->curc;
|
|
|
|
if (len > 0) memcpy(tmp + text->curc + indentlen, text->curl->line + text->curc, len);
|
|
|
|
tmp[text->curl->len + indentlen] = 0;
|
|
|
|
|
|
|
|
make_new_line(text->curl, tmp);
|
|
|
|
|
|
|
|
text->curc += indentlen;
|
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
}
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (text->curl == text->sell) {
|
2012-11-05 13:31:26 +00:00
|
|
|
text->selc += indentlen;
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
break;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
text->curl = text->curl->next;
|
|
|
|
num++;
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
}
|
2012-11-05 13:31:26 +00:00
|
|
|
if (!curc_old) text->curc = 0;
|
|
|
|
else text->curc = curc_old + indentlen;
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
while (num > 0) {
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
text->curl = text->curl->prev;
|
|
|
|
num--;
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
/* caller must handle undo */
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
/**
|
|
|
|
* Generic un-prefix operation, use for comment & indent.
|
|
|
|
*
|
|
|
|
* \param r_line_index_mask: List of lines that are already at indent level 0,
|
|
|
|
* to store them later into the undo buffer.
|
|
|
|
*
|
|
|
|
* \note caller must handle undo.
|
|
|
|
*/
|
|
|
|
static void txt_select_unprefix(
|
|
|
|
Text *text, const char *remove,
|
|
|
|
ListBase *r_line_index_mask, int *r_line_index_mask_len)
|
2004-10-14 23:37:04 +00:00
|
|
|
{
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
int num = 0;
|
2015-09-16 03:30:02 +10:00
|
|
|
const int indentlen = strlen(remove);
|
2014-04-01 11:34:00 +11:00
|
|
|
bool unindented_first = false;
|
2015-05-07 04:43:33 +10:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
int curl_span_init = 0;
|
2010-01-17 03:15:27 +00:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
BLI_assert(!ELEM(NULL, text->curl, text->sell));
|
2012-01-20 23:03:41 +00:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
BLI_listbase_clear(r_line_index_mask);
|
|
|
|
*r_line_index_mask_len = 0;
|
2009-11-20 19:15:57 +00:00
|
|
|
|
2015-05-07 04:43:33 +10:00
|
|
|
if (!undoing) {
|
|
|
|
curl_span_init = txt_get_span(text->lines.first, text->curl);
|
|
|
|
}
|
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
while (true) {
|
2014-04-14 13:26:12 +10:00
|
|
|
bool changed = false;
|
2015-01-26 16:03:11 +01:00
|
|
|
if (STREQLEN(text->curl->line, remove, indentlen)) {
|
2014-04-01 11:34:00 +11:00
|
|
|
if (num == 0)
|
|
|
|
unindented_first = true;
|
2012-11-05 13:31:26 +00:00
|
|
|
text->curl->len -= indentlen;
|
2014-04-14 13:26:12 +10:00
|
|
|
memmove(text->curl->line, text->curl->line + indentlen, text->curl->len + 1);
|
|
|
|
changed = true;
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
2015-05-07 04:43:33 +10:00
|
|
|
else {
|
|
|
|
if (!undoing) {
|
|
|
|
/* Create list element for 0 indent line */
|
|
|
|
struct LinkInt *idata = MEM_mallocN(sizeof(struct LinkInt), __func__);
|
|
|
|
idata->value = curl_span_init + num;
|
|
|
|
BLI_assert(idata->value == txt_get_span(text->lines.first, text->curl));
|
2015-09-16 03:30:02 +10:00
|
|
|
BLI_addtail(r_line_index_mask, idata);
|
|
|
|
(*r_line_index_mask_len) += 1;
|
2015-05-07 04:43:33 +10:00
|
|
|
}
|
|
|
|
}
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
|
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (text->curl == text->sell) {
|
2014-04-14 13:26:12 +10:00
|
|
|
if (changed)
|
|
|
|
text->selc = MAX2(text->selc - indentlen, 0);
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
break;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
text->curl = text->curl->next;
|
|
|
|
num++;
|
2015-05-07 04:43:33 +10:00
|
|
|
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
|
|
|
|
}
|
2012-11-05 13:31:26 +00:00
|
|
|
|
2014-04-14 13:26:12 +10:00
|
|
|
if (unindented_first)
|
|
|
|
text->curc = MAX2(text->curc - indentlen, 0);
|
2012-11-05 13:31:26 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
while (num > 0) {
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
text->curl = text->curl->prev;
|
|
|
|
num--;
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
2015-05-07 04:43:33 +10:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
/* caller must handle undo */
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
|
|
|
|
2011-05-23 08:14:29 +00:00
|
|
|
void txt_comment(Text *text)
|
2004-10-14 23:37:04 +00:00
|
|
|
{
|
2015-09-16 03:30:02 +10:00
|
|
|
const char *prefix = "#";
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
if (ELEM(NULL, text->curl, text->sell)) {
|
|
|
|
return;
|
|
|
|
}
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
txt_select_prefix(text, prefix);
|
2005-05-13 16:11:28 +00:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (!undoing) {
|
2012-11-14 23:10:19 +00:00
|
|
|
txt_undo_add_op(text, UNDO_COMMENT);
|
2005-12-12 18:35:15 +00:00
|
|
|
}
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
|
|
|
|
2011-05-23 08:14:29 +00:00
|
|
|
void txt_uncomment(Text *text)
|
2004-10-14 23:37:04 +00:00
|
|
|
{
|
2015-09-16 03:30:02 +10:00
|
|
|
const char *prefix = "#";
|
|
|
|
ListBase line_index_mask;
|
|
|
|
int line_index_mask_len;
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
if (ELEM(NULL, text->curl, text->sell)) {
|
|
|
|
return;
|
|
|
|
}
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
|
|
|
|
|
|
|
|
if (!undoing) {
|
|
|
|
txt_undo_add_unprefix_op(text, UNDO_UNCOMMENT, &line_index_mask, line_index_mask_len);
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
}
|
2015-09-16 03:30:02 +10:00
|
|
|
|
|
|
|
BLI_freelistN(&line_index_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
void txt_indent(Text *text)
|
|
|
|
{
|
|
|
|
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
|
|
|
|
|
|
|
|
if (ELEM(NULL, text->curl, text->sell)) {
|
|
|
|
return;
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
}
|
2015-09-16 03:30:02 +10:00
|
|
|
|
|
|
|
txt_select_prefix(text, prefix);
|
|
|
|
|
|
|
|
if (!undoing) {
|
|
|
|
txt_undo_add_op(text, UNDO_INDENT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void txt_unindent(Text *text)
|
|
|
|
{
|
|
|
|
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
|
|
|
|
ListBase line_index_mask;
|
|
|
|
int line_index_mask_len;
|
2005-12-12 18:35:15 +00:00
|
|
|
|
2015-09-16 03:30:02 +10:00
|
|
|
if (ELEM(NULL, text->curl, text->sell)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
|
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (!undoing) {
|
2015-09-16 03:30:02 +10:00
|
|
|
txt_undo_add_unprefix_op(text, UNDO_UNINDENT, &line_index_mask, line_index_mask_len);
|
2005-12-12 18:35:15 +00:00
|
|
|
}
|
2015-09-16 03:30:02 +10:00
|
|
|
|
|
|
|
BLI_freelistN(&line_index_mask);
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
|
|
|
|
2012-05-04 16:17:09 +00:00
|
|
|
void txt_move_lines(struct Text *text, const int direction)
|
2012-05-04 14:27:13 +00:00
|
|
|
{
|
2012-05-04 16:17:09 +00:00
|
|
|
TextLine *line_other;
|
|
|
|
|
|
|
|
BLI_assert(ELEM(direction, TXT_MOVE_LINE_UP, TXT_MOVE_LINE_DOWN));
|
|
|
|
|
2014-10-06 12:23:47 +02:00
|
|
|
if (!text->curl || !text->sell) return;
|
2012-05-04 14:27:13 +00:00
|
|
|
|
2013-09-02 00:47:27 +00:00
|
|
|
txt_order_cursors(text, false);
|
2012-05-04 16:17:09 +00:00
|
|
|
|
|
|
|
line_other = (direction == TXT_MOVE_LINE_DOWN) ? text->sell->next : text->curl->prev;
|
2012-05-04 14:27:13 +00:00
|
|
|
|
2012-05-04 16:17:09 +00:00
|
|
|
if (!line_other) return;
|
2012-05-04 14:27:13 +00:00
|
|
|
|
2012-05-04 16:17:09 +00:00
|
|
|
BLI_remlink(&text->lines, line_other);
|
|
|
|
|
|
|
|
if (direction == TXT_MOVE_LINE_DOWN) {
|
|
|
|
BLI_insertlinkbefore(&text->lines, text->curl, line_other);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_insertlinkafter(&text->lines, text->sell, line_other);
|
|
|
|
}
|
|
|
|
|
2012-05-04 14:27:13 +00:00
|
|
|
txt_make_dirty(text);
|
|
|
|
txt_clean_text(text);
|
|
|
|
|
2012-05-04 16:17:09 +00:00
|
|
|
if (!undoing) {
|
|
|
|
txt_undo_add_op(text, (direction == TXT_MOVE_LINE_DOWN) ? UNDO_MOVE_LINES_DOWN : UNDO_MOVE_LINES_UP);
|
2012-05-04 14:27:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-14 05:52:30 +00:00
|
|
|
int txt_setcurr_tab_spaces(Text *text, int space)
|
2004-10-14 23:37:04 +00:00
|
|
|
{
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
int i = 0;
|
|
|
|
int test = 0;
|
2010-07-29 22:34:46 +00:00
|
|
|
const char *word = ":";
|
|
|
|
const char *comm = "#";
|
2012-05-06 15:15:33 +00:00
|
|
|
const char indent = (text->flags & TXT_TABSTOSPACES) ? ' ' : '\t';
|
|
|
|
static const char *back_words[] = {"return", "break", "continue", "pass", "yield", NULL};
|
2014-10-06 12:23:47 +02:00
|
|
|
|
2005-04-28 14:37:15 +00:00
|
|
|
if (!text->curl) return 0;
|
2010-07-29 22:34:46 +00:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
while (text->curl->line[i] == indent) {
|
2010-07-29 22:34:46 +00:00
|
|
|
//we only count those tabs/spaces that are before any text or before the curs;
|
2012-04-28 06:31:57 +00:00
|
|
|
if (i == text->curc) {
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
return i;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
2012-04-28 06:31:57 +00:00
|
|
|
if (strstr(text->curl->line, word)) {
|
2010-12-31 04:09:15 +00:00
|
|
|
/* if we find a ':' on this line, then add a tab but not if it is:
|
2012-05-06 15:15:33 +00:00
|
|
|
* 1) in a comment
|
|
|
|
* 2) within an identifier
|
2010-12-31 04:09:15 +00:00
|
|
|
* 3) after the cursor (text->curc), i.e. when creating space before a function def [#25414]
|
|
|
|
*/
|
2014-04-11 11:25:41 +10:00
|
|
|
int a;
|
|
|
|
bool is_indent = false;
|
2012-05-06 15:15:33 +00:00
|
|
|
for (a = 0; (a < text->curc) && (text->curl->line[a] != '\0'); a++) {
|
|
|
|
char ch = text->curl->line[a];
|
|
|
|
if (ch == '#') {
|
2008-03-01 12:31:00 +00:00
|
|
|
break;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (ch == ':') {
|
2011-05-23 08:14:29 +00:00
|
|
|
is_indent = 1;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (ch != ' ' && ch != '\t') {
|
2011-05-23 08:14:29 +00:00
|
|
|
is_indent = 0;
|
2008-03-01 12:31:00 +00:00
|
|
|
}
|
|
|
|
}
|
2011-05-23 08:14:29 +00:00
|
|
|
if (is_indent) {
|
2010-07-29 22:34:46 +00:00
|
|
|
i += space;
|
2005-05-13 16:11:28 +00:00
|
|
|
}
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
}
|
2004-10-14 23:37:04 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
for (test = 0; back_words[test]; test++) {
|
2010-07-26 18:50:38 +00:00
|
|
|
/* if there are these key words then remove a tab because we are done with the block */
|
2012-04-28 06:31:57 +00:00
|
|
|
if (strstr(text->curl->line, back_words[test]) && i > 0) {
|
|
|
|
if (strcspn(text->curl->line, back_words[test]) < strcspn(text->curl->line, comm)) {
|
2010-07-29 22:34:46 +00:00
|
|
|
i -= space;
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Bugfix for disappearing hilight bug and code re-org for text editor
from Ricki Myers (themyers).
Comes with nice juicy commit msg, too!
- source/blender/blenkernel/BKE_text.h
- Removed indent_paste, uncommen, unindent_lines, comment_paste,
uncomment_paste, uncomment, set_tabs.
All these functions cut and re-added text (I felt this was
unsafe). whicch is was caused the highlight loss.
- Now the only functions are Indent, Unindent, comment, uncomment,
setcurr_tab. All these functions only take one @parm (struct Text)
-indent(struct Text *text)
copy's the selected text in a MEM_mallocN line by line added a
tab at the begginning
- Unindent(struct Text *text)
Tests if current line starts with a tab.
if TAB remove it
- comment(struct Text *text)
copy's the selected text in a MEM_mallocN and adding a # at the begginning
- Uncomment(struct Text *text)
Tests if current line starts with a #.
if # remove it
- setcurr_tab (Text *text)
Checks for Tabs pri. to any text
if : is found and not in a comment then Tabs is increased by one
if "return", "break", "pass" is found then Tabs is decreased
- blender/source/blender/src/header_text.c
Changed: txt_cut_sel(text);
indent_paste(text);
TO:
txt_order_cursors(text);
indent(text);
* no more cutting of the text
- source/blender/src/drawtext.c
set_tabs(Text *text) just calls setcurr_tab(text);
2005-04-10 14:01:41 +00:00
|
|
|
return i;
|
2004-10-14 23:37:04 +00:00
|
|
|
}
|
2005-04-28 14:37:15 +00:00
|
|
|
|
2009-09-22 16:23:46 +00:00
|
|
|
/*******************************/
|
|
|
|
/* Character utility functions */
|
|
|
|
/*******************************/
|
|
|
|
|
2012-04-06 05:53:01 +00:00
|
|
|
int text_check_bracket(const char ch)
|
2009-09-22 16:23:46 +00:00
|
|
|
{
|
|
|
|
int a;
|
|
|
|
char opens[] = "([{";
|
|
|
|
char close[] = ")]}";
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
for (a = 0; a < (sizeof(opens) - 1); a++) {
|
|
|
|
if (ch == opens[a])
|
|
|
|
return a + 1;
|
|
|
|
else if (ch == close[a])
|
|
|
|
return -(a + 1);
|
2009-09-22 16:23:46 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-04-06 05:53:01 +00:00
|
|
|
/* TODO, have a function for operators - http://docs.python.org/py3k/reference/lexical_analysis.html#operators */
|
2014-02-03 18:55:59 +11:00
|
|
|
bool text_check_delim(const char ch)
|
2009-09-22 16:23:46 +00:00
|
|
|
{
|
|
|
|
int a;
|
2012-04-06 05:53:01 +00:00
|
|
|
char delims[] = "():\"\' ~!%^&*-+=[]{};/<>|.#\t,@";
|
2009-09-22 16:23:46 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
for (a = 0; a < (sizeof(delims) - 1); a++) {
|
|
|
|
if (ch == delims[a])
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
2009-09-22 16:23:46 +00:00
|
|
|
}
|
2014-12-01 17:11:18 +01:00
|
|
|
return false;
|
2009-09-22 16:23:46 +00:00
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool text_check_digit(const char ch)
|
2009-09-22 16:23:46 +00:00
|
|
|
{
|
2014-12-01 17:11:18 +01:00
|
|
|
if (ch < '0') return false;
|
|
|
|
if (ch <= '9') return true;
|
|
|
|
return false;
|
2009-09-22 16:23:46 +00:00
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool text_check_identifier(const char ch)
|
2009-09-22 16:23:46 +00:00
|
|
|
{
|
2014-12-01 17:11:18 +01:00
|
|
|
if (ch < '0') return false;
|
|
|
|
if (ch <= '9') return true;
|
|
|
|
if (ch < 'A') return false;
|
|
|
|
if (ch <= 'Z' || ch == '_') return true;
|
|
|
|
if (ch < 'a') return false;
|
|
|
|
if (ch <= 'z') return true;
|
|
|
|
return false;
|
2009-09-22 16:23:46 +00:00
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool text_check_identifier_nodigit(const char ch)
|
2013-01-16 04:43:37 +00:00
|
|
|
{
|
2014-12-01 17:11:18 +01:00
|
|
|
if (ch <= '9') return false;
|
|
|
|
if (ch < 'A') return false;
|
|
|
|
if (ch <= 'Z' || ch == '_') return true;
|
|
|
|
if (ch < 'a') return false;
|
|
|
|
if (ch <= 'z') return true;
|
|
|
|
return false;
|
2013-01-16 04:43:37 +00:00
|
|
|
}
|
|
|
|
|
2013-02-19 16:13:41 +00:00
|
|
|
#ifndef WITH_PYTHON
|
2014-02-27 21:16:01 +01:00
|
|
|
int text_check_identifier_unicode(const unsigned int ch)
|
2013-02-19 16:13:41 +00:00
|
|
|
{
|
2014-02-27 21:16:01 +01:00
|
|
|
return (ch < 255 && text_check_identifier((unsigned int)ch));
|
2013-02-19 16:13:41 +00:00
|
|
|
}
|
|
|
|
|
2014-02-27 21:16:01 +01:00
|
|
|
int text_check_identifier_nodigit_unicode(const unsigned int ch)
|
2013-02-19 16:13:41 +00:00
|
|
|
{
|
|
|
|
return (ch < 255 && text_check_identifier_nodigit((char)ch));
|
|
|
|
}
|
|
|
|
#endif /* WITH_PYTHON */
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool text_check_whitespace(const char ch)
|
2009-09-22 16:23:46 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
2009-09-22 16:23:46 +00:00
|
|
|
}
|
2012-12-31 16:24:49 +00:00
|
|
|
|
|
|
|
int text_find_identifier_start(const char *str, int i)
|
|
|
|
{
|
2012-12-31 17:19:55 +00:00
|
|
|
if (UNLIKELY(i <= 0)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-12-31 16:24:49 +00:00
|
|
|
while (i--) {
|
|
|
|
if (!text_check_identifier(str[i])) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
return i;
|
|
|
|
}
|