1 /* Bluefish HTML Editor
2  * bftextview2_private.h
3  *
4  * Copyright (C) 2012,2013,2014 Olivier Sessink
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef _BFTEXTVIEW2_PRIVATE_H_
21 #define _BFTEXTVIEW2_PRIVATE_H_
22 
23 #define CONDITIONALPATTERN
24 
25 #if defined(__GNUC__) || (defined(__SUNPRO_C) && __SUNPRO_C > 0x580)
26 #define DBG_NONE(args...)
27  /**/
28 #else							/* notdef __GNUC__ || __SUNPRO_C */
29 extern void g_none(char *first, ...);
30 #define DBG_NONE g_none
31 #endif
32  /**/
33 
34 #define BF_OFFSET_UNDEFINED G_MAXINT32
35 #define BF_POSITION_UNDEFINED G_MAXINT32
36 
37 /*#define DUMP_CONTEXTS*/
38 /*#define DUMP_PATTERNS*/
39 /*#define DUMP_SCANCACHE*/
40 /*#define DUMP_SCANCACHE_UPDATE_OFFSET*/
41 /*#define CHECK_CONSISTENCY*/
42 
43 #define DBG_MSG DBG_NONE
44 #define DBG_SCANCACHE DBG_NONE
45 #define DBG_SCANNING DBG_NONE
46 #define DBG_BLOCKMATCH DBG_NONE
47 #define DBG_PATCOMPILE DBG_NONE
48 #define DBG_SIGNALS DBG_NONE
49 #define DBG_AUTOCOMP DBG_NONE
50 #define DBG_DELAYSCANNING DBG_NONE
51 #define DBG_FOLD DBG_NONE
52 #define DBG_MARGIN DBG_NONE
53 #define DBG_PARSING DBG_NONE
54 #define DBG_TOOLTIP DBG_NONE
55 #define DBG_SPELL DBG_NONE
56 #define DBG_IDENTIFIER DBG_NONE
57 #define DBG_MARKREGION DBG_NONE
58 
59 #ifdef UPDATE_OFFSET_DELAYED
60 #include "bf_lib.h"
61 typedef struct {
62 	BF_ELIST_HEAD;
63 	guint32 startpos;
64 	gint32 offset;
65 } Toffsetupdate;
66 #define OFFSETUPDATE(var) ((Toffsetupdate *)var)
67 #endif /*UPDATE_OFFSET_DELAYED*/
68 
69 #define NUMSCANCHARS 127		/* 128 is ascii, but the last character is never scanned (DEL)
70 								   and the Ttablerow has one more 16bit value. By setting this to 127 instead of 128
71 								   we dont need padding to align the Ttablerow in memory
72 								   (Ttablerow = (127+1)*16=2048 bits or 256 bytes) */
73 /*****************************************************************/
74 /* building the automata and autocompletion cache */
75 /*****************************************************************/
76 #define COMMENT_INDEX_INHERIT 255
77 #define COMMENT_INDEX_NONE 254
78 #define SPELLCHECK_INHERIT 255
79 #define SPELLCHECK_ENABLED 1
80 #define SPELLCHECK_DISABLED 0
81 typedef struct {
82 	GArray *table; /* a pointer to the DFA table for this context */
83 	GCompletion *ac;			/* autocompletion items in this context */
84 	GHashTable *patternhash;	/* a hash table where the pattern and its autocompletion	strings are the keys, and an integer
85 										to the ID of the pattern is the value. Only patterns that have backup cursor, a condition, or
86 										a reference set are required in this hash. */
87 	GtkTextTag *contexttag;		/* if the context area itself needs some kind of style (to implement a string context for example) */
88 	gchar *contexthighlight;	/* the string that has the id for the highlight */
89 	guint8 has_tagclose_from_blockstack;	/* this context has xml end patterns that need autoclosing for generix xml tags, based on the tag that is on top of the blockstack */
90 	guint8 comment_block;		/* block comment index in array scantable->comments
91 								   or COMMENT_INDEX_INHERIT (which means inherit)
92 								   or COMMENT_INDEX_NONE if there is no block comment  */
93 	guint8 comment_line;		/* index in array scantable->comments for line comments; see comment_block */
94 	guint8 autocomplete_case_insens;
95 	guint8 autocomplete_has_conditions; /* 0 means any autocomplete item is valid, 1 means we have to check for runtime conditions */
96 	guint8 default_spellcheck;
97 	guint8 dump_dfa_run;
98 } Tcontext;
99 /*
100 32bit size = 5*32 + 7*8 = 208 + 8 padding bits = 28 bytes
101 64bit size = 5*64 + 7*8 = 368 + 8 padding bits = 48 bytes
102 */
103 
104 typedef struct {
105 	gchar *refname; 	/* because we can match the name only after all contexts are loaded, we store it in the structure */
106 	guint16 ref; 			/* if the reference was a context, the ID of that context, if the reference
107 									was a pattern, the ID of that pattern, otherwise 0 */
108 	gint8 parentrelation; /* -1 means any parent, 0 = direct parent, 1= grandparent, etc. */
109 	guint8 relationtype; /* 1 = valid if relation with context matches,
110 									2 = invalid if relation with context matches,
111 									3 = valid if relation with block matches
112 									4 = invalid if relation with block matches
113 									*/
114 } Tpattern_condition;
115 
116 typedef struct {
117 	gchar *autocomplete_string;
118 	guint16 condition; /* 0 for most patterns, only blocks that are (in)valid in a certain condition have this set (refers to a Tpattern_condition) */
119 	guint8 autocomplete_backup_cursor;	/* number of characters to backup the cursor after autocompletion (max 256) */
120 	guint8 trigger_new_autocomp_popup; /* if a new autocompletion popup should be triggered immediately after the text of
121 													this one is inserted. Useful for example to autocomplete the values of an attribute
122 													after an attribute has been inserted. */
123 } Tpattern_autocomplete;
124 /*
125 32bit size = 32 + 16 + 2*8 = 64 + 0 padding bits = 8 bytes
126 64bit size = 64 + 16 + 2*8 = 96 + 32 padding bits = 16 bytes
127 */
128 
129 typedef struct {
130 	gchar *name;
131 	GtkTextTag *tag;		/* if this pattern ends a context or a block, we can highlight
132 								   the region within the start and end pattern with this tag */
133 	gchar *highlight;		/* a string for the highlight corresponding to the  blocktag */
134 	gboolean foldable;
135 } Tpattern_block;
136 
137 typedef struct {
138 	GtkTextTag *selftag;		/* the tag used to highlight this pattern */
139 	gchar *reference;			/* the reference data, or NULL. may be inserted in hash tables for multiple keys in multiple contexts */
140 	gchar *pattern;				/* the pattern itself. stored in the Tpattern so we can re-use it in another context */
141 	GSList *autocomp_items; /* a list of Tpattern_autocomplete - a pattern can autocomplete in multiple ways, for
142 										example with and without closing tag, or with and without function arguments.
143 										to be able to recompile a pattern in multiple contexts we need this information in Tpattern */
144 	gchar *selfhighlight;		/* a string with the highlight for this pattern. used when re-linking highlights and textstyles
145 								   if the user changed any of these in the preferences */
146 	guint16 condition; /* 0 for most patterns, only blocks that are (in)valid in a certain condition have this set */
147 	guint16 block;			/* this is 0 for most blocks, only blocks that need a tag have this set, refers to a a position in an array of Tpattern_block*/
148 	gint16 blockstartpattern;	/* the number of the pattern that may start this block, or -1 to end the last started block, also used for stretch block */
149 	gint16 nextcontext;			/* 0, or if this pattern starts a new context the number of the context, or -1 or -2 etc.
150 								   to pop a context of the stack */
151 	guint8 identmode :2;
152 	guint8 identaction :2; /* 2 bits, first bit is add to jump hashtable, second bit is autocomplete */
153 	/* we use 1 bit integers here because these values are all booleans */
154 	guint8 starts_block :1;		/* wether or not this pattern may start a block */
155 	guint8 ends_block :1;			/* wether or not this pattern may end a block */
156 	guint8 tagclose_from_blockstack :1;	/* this is a generix xml close tag that needs the blockstack to autoclose */
157 	guint8 stretch_blockstart :1; /* the end of this match is the new end-of-blockstart, used for HTML/XML tags */
158 	guint8 case_insens :1;
159 	guint8 is_regex :1;
160 } Tpattern;
161 /*
162 32bit size = 5*32 + 4*16 + 2*2 + 6*1 = 234 + 22 padding bits = 32 bytes
163 64bit size = 5*64 + 4*16 + 2*2 + 6*1 = 394 + 54 padding bits = 56 bytes
164 */
165 
166 typedef struct {
167 	guint16 row[NUMSCANCHARS];	/* contains for each character the number of the next state
168 								   because we use a 16bit unsigned number we can support only 65535 states
169 								   at maximum!!!!!!! but we use half the size of the scanning table, which
170 								   hopefully helps to keep the scanning table in the L2 cache of the CPU */
171 	guint16 match;				/* 0 == no match, refers to the index number in array 'matches' */
172 } Ttablerow;					/* a row in the DFA, right now exactly 256 bytes */
173 
174 
175 /*#define character_is_symbol(st,context,c) (g_array_index((GArray *)g_array_index(st->contexts, Tcontext, context).table, Ttablerow, 1).row[c] != 1)*/
176 gboolean character_is_symbol(Tscantable *st,guint16 context, gunichar uc);
177 
178 #define get_table(scantable, context) ((GArray *)g_array_index(scantable->contexts, Tcontext, context).table)
179 
180 #define get_tablerow(scantable, context, curstate) (g_array_index(g_array_index(scantable->contexts, Tcontext, context).table, Ttablerow, curstate))
181 
182 /*****************************************************************/
183 /* scanning the text and caching the results */
184 /*****************************************************************/
185 typedef struct {
186 	gpointer parentfblock;
187 	guint32 start1_o;
188 	guint32 end1_o;
189 	guint32 start2_o;
190 	guint32 end2_o;
191 	gint16 patternum;			/* which pattern (number of the array element in scantable->matches) started the block */
192 	guint8 folded;
193 	guint8 foldable;			/* FALSE on a single line */
194 } Tfoundblock;					/* Once a start-of-block is found start1 and end1 are set
195 								   and the Tfoundblock is added to the foundcache.
196 								   The previous foundblock is set as parentfblock
197 								   so we can later on find what the current blockstack looks like.
198 								   Once the end-of-block is found, start2 and end2 are set
199 								   The Tfoundblock is popped as current block, and the parent
200 								   is active again. This is also put on the foundcache
201 
202 								   on 64bit this type has size 8+4+4+4+4+2+1+1 + 4 padding = 32 bytes
203 								   on 32bit this type has size 4+4+4+4+4+2+1+1 NO padding = 24 bytes
204 								 */
205 
206 typedef struct {
207 	gpointer parentfcontext;
208 	guint32 start_o;
209 	guint32 end_o;
210 	gint16 context;				/* number of the element in scantable->contexts */
211 } Tfoundcontext;				/* Once a start-of-context is found start is set
212 								   and the Tfoundcontext is added to the current foundcache.
213 								   The previous fcontext is set in parentfcontext
214 								   so we can later on find what the current contextstack looks like.
215 								   once the end-of-context is found, end is set
216 								   The Tfoundcontext is popped from the current stack and
217 								   this entry is also added to the foundcache
218 
219 								   on 64bit this type has size 8+4+4+2 + 6 padding = 24 bytes
220 								   on 32bit this type has size 4+4+4+2 + 2 padding = 16 bytes
221 								 */
222 
223 typedef struct {
224 	Tfoundcontext *fcontext;	/* if numcontextchange == 0 this points to the current active context
225 								   if numcontextchange > 0 this points to the pushed context, which also happens to be the current context
226 								   if numcontextchange < 0 this points to the top of the stack at this position, to get the current position
227 								   you'll have to pop N items (where N is -1 * numcontextchange). */
228 	Tfoundblock *fblock;		/* if numblockchange == 0 this points to the current active block
229 								   if numblockchange > 0 this points to the pushed block, which also happens to be the current block
230 								   if numblockchange < 0 this points to the top of the stack at this position, to get the current position
231 								   you'll have to pop N items (where N is -1 * numblockchange). */
232 	guint32 charoffset_o;
233 	gint16 numblockchange;		/* there are files that have > 127 pops in a single position
234 								   for example html files that don't close paragrahs or tablerows */
235 	gint8 numcontextchange;		/* 0 means no change, 1 means 1 push, -2 means 2 popped etc. */
236 } Tfound;						/*
237 								   on 64bit this type has size 8+8+4+2+1 + 1 padding = 24 bytes
238 								   on 32bit this type has size 4+4+4+2+1 + 1 padding = 16 bytes
239 								 */
240 
241 #define IS_FOUNDMODE_CONTEXTPUSH(i)   (i->numcontextchange > 0)
242 #define IS_FOUNDMODE_CONTEXTPOP(i)   (i->numcontextchange < 0)
243 #define IS_FOUNDMODE_BLOCKPUSH(i)   (i->numblockchange ==1)
244 #define IS_FOUNDMODE_BLOCKPOP(i)   (i->numblockchange < 0)
245 
246 #endif /* _BFTEXTVIEW2_PRIVATE_H_ */
247