Blender V5.0
text_format.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstring>
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_listbase.h"
14#include "BLI_path_utils.hh"
15#include "BLI_string.h"
16#include "BLI_string_utf8.h"
17#include "BLI_string_utils.hh"
18
19#include "DNA_space_types.h"
20#include "DNA_text_types.h"
21
22#include "ED_text.hh"
23
24#include "text_format.hh"
25
26/****************** flatten string **********************/
27
28static void flatten_string_append(FlattenString *fs, const char *c, int accum, int len)
29{
30 int i;
31
32 if (fs->pos + len > fs->len) {
33 char *nbuf;
34 int *naccum;
35 fs->len *= 2;
36
37 nbuf = MEM_calloc_arrayN<char>(fs->len, "fs->buf");
38 memcpy(nbuf, fs->buf, sizeof(*fs->buf) * fs->pos);
39
40 naccum = MEM_calloc_arrayN<int>(fs->len, "fs->accum");
41 memcpy(naccum, fs->accum, sizeof(*fs->accum) * fs->pos);
42
43 if (fs->buf != fs->fixedbuf) {
44 MEM_freeN(fs->buf);
45 MEM_freeN(fs->accum);
46 }
47
48 fs->buf = nbuf;
49 fs->accum = naccum;
50 }
51
52 for (i = 0; i < len; i++) {
53 fs->buf[fs->pos + i] = c[i];
54 fs->accum[fs->pos + i] = accum;
55 }
56
57 fs->pos += len;
58}
59
60int flatten_string(const SpaceText *st, FlattenString *fs, const char *in)
61{
62 int r, i, total = 0;
63
64 memset(fs, 0, sizeof(FlattenString));
65 fs->buf = fs->fixedbuf;
66 fs->accum = fs->fixedaccum;
67 fs->len = sizeof(fs->fixedbuf);
68
69 for (r = 0, i = 0; *in; r++) {
70 if (*in == '\t') {
71 i = st->tabnumber - (total % st->tabnumber);
72 total += i;
73
74 while (i--) {
75 flatten_string_append(fs, " ", r, 1);
76 }
77
78 in++;
79 }
80 else {
83 in += len;
84 total++;
85 }
86 }
87
88 flatten_string_append(fs, "\0", r, 1);
89
90 return total;
91}
92
94{
95 if (fs->buf != fs->fixedbuf) {
96 MEM_freeN(fs->buf);
97 }
98 if (fs->accum != fs->fixedaccum) {
99 MEM_freeN(fs->accum);
100 }
101}
102
104{
105 const int len = (fs->pos - int(str - fs->buf)) - 1;
106 BLI_assert(strlen(str) == len);
107 return len;
108}
109
111{
112 if (line->format) {
113 if (strlen(line->format) < len) {
114 MEM_freeN(line->format);
115 line->format = MEM_malloc_arrayN<char>(len + 2, "SyntaxFormat");
116 if (!line->format) {
117 return 0;
118 }
119 }
120 }
121 else {
122 line->format = MEM_malloc_arrayN<char>(len + 2, "SyntaxFormat");
123 if (!line->format) {
124 return 0;
125 }
126 }
127
128 return 1;
129}
130
131void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len)
132{
133 const char *str = *str_p;
134 char *fmt = *fmt_p;
135 int i = 0;
136
137 while (i < len) {
138 const int size = BLI_str_utf8_size_safe(str);
139 *fmt++ = type;
140
141 str += size;
142 i += 1;
143 }
144
145 str--;
146 fmt--;
147
148 BLI_assert(*str != '\0');
149
150 *str_p = str;
151 *fmt_p = fmt;
152}
153void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len)
154{
155 const char *str = *str_p;
156 char *fmt = *fmt_p;
157
158 memset(fmt, type, len);
159
160 str += len - 1;
161 fmt += len - 1;
162
163 BLI_assert(*str != '\0');
164
165 *str_p = str;
166 *fmt_p = fmt;
167}
168
169/* *** Registration *** */
170static ListBase tft_lb = {nullptr, nullptr};
175
177{
178 if (text) {
179 const char *text_ext = strchr(text->id.name + 2, '.');
180 if (text_ext) {
181 text_ext++; /* Skip the `.`. */
182 /* Check all text formats in the static list. */
184 /* All formats should have an ext, but just in case. */
185 const char **ext;
186 for (ext = tft->ext; *ext; ext++) {
187 /* If extension matches text name, return the matching tft. */
188 if (BLI_strcasecmp(text_ext, *ext) == 0) {
189 return tft;
190 }
191 }
192 }
193 }
194
195 /* If we make it here we never found an extension that worked - return
196 * the "default" text format. */
197 return static_cast<TextFormatType *>(tft_lb.first);
198 }
199
200 /* Return the "default" text format. */
201 return static_cast<TextFormatType *>(tft_lb.first);
202}
203
205{
207 return format->comment_line;
208}
209
211{
212 if (text == nullptr) {
213 return false;
214 }
215
216 const char *text_ext = BLI_path_extension(text->id.name + 2);
217 if (text_ext == nullptr) {
218 /* Extensionless data-blocks are considered highlightable as Python. */
219 return true;
220 }
221 text_ext++; /* Skip the `.`. */
222 if (BLI_string_is_decimal(text_ext)) {
223 /* `Text.001` is treated as extensionless, and thus highlightable. */
224 return true;
225 }
226
227 /* Check all text formats in the static list. */
229 /* All formats should have an ext, but just in case. */
230 const char **ext;
231 for (ext = tft->ext; *ext; ext++) {
232 /* If extension matches text name, return the matching tft. */
233 if (BLI_strcasecmp(text_ext, *ext) == 0) {
234 return true;
235 }
236 }
237 }
238
239 /* The filename has a non-numerical extension that we could not highlight. */
240 return false;
241}
242
243int text_format_string_literal_find(const Span<const char *> string_literals, const char *text)
244{
245 auto cmp_fn = [](const char *text, const char *string_literal) {
246 return strcmp(text, string_literal) < 0;
247 };
248 const char *const *string_literal_p = std::upper_bound(
249 std::begin(string_literals), std::end(string_literals), text, cmp_fn);
250
251 if (string_literal_p != std::begin(string_literals)) {
252 const char *string = *(string_literal_p - 1);
253 const size_t string_len = strlen(string);
254 if (strncmp(string, text, string_len) == 0) {
255 return string_len;
256 }
257 }
258
259 return 0;
260}
261
262#ifndef NDEBUG
264{
265 return std::is_sorted(string_literals.begin(),
266 string_literals.end(),
267 [](const char *a, const char *b) { return strcmp(a, b) < 0; });
268}
269#endif
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
const char * BLI_path_extension(const char *filepath) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
int char char int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
int BLI_str_utf8_size_safe(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
bool BLI_string_is_decimal(const char *string) ATTR_NONNULL(1)
unsigned int uint
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr const T * end() const
Definition BLI_span.hh:224
constexpr const T * begin() const
Definition BLI_span.hh:220
#define str(s)
#define in
format
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
int fixedaccum[256]
char fixedbuf[256]
char name[258]
Definition DNA_ID.h:432
char * format
i
Definition text_draw.cc:230
int flatten_string_strlen(FlattenString *fs, const char *str)
static void flatten_string_append(FlattenString *fs, const char *c, int accum, int len)
int flatten_string(const SpaceText *st, FlattenString *fs, const char *in)
void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len)
void flatten_string_free(FlattenString *fs)
const char * ED_text_format_comment_line_prefix(Text *text)
int text_format_string_literal_find(const Span< const char * > string_literals, const char *text)
static ListBase tft_lb
TextFormatType * ED_text_format_get(Text *text)
void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len)
bool ED_text_is_syntax_highlight_supported(Text *text)
void ED_text_format_register(TextFormatType *tft)
int text_check_format_len(TextLine *line, uint len)
bool text_format_string_literals_check_sorted_array(const Span< const char * > string_literals)
uint len