Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / space_text / text_format.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program; if not, write to the Free Software Foundation,
13  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14  *
15  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
16  * All rights reserved.
17  */
18
19 /** \file
20  * \ingroup sptext
21  */
22
23 #include <string.h>
24
25 #include "MEM_guardedalloc.h"
26
27 #include "BLI_blenlib.h"
28
29 #include "DNA_text_types.h"
30 #include "DNA_space_types.h"
31
32 #include "text_format.h"
33
34 /****************** flatten string **********************/
35
36 static void flatten_string_append(FlattenString *fs, const char *c, int accum, int len)
37 {
38   int i;
39
40   if (fs->pos + len > fs->len) {
41     char *nbuf;
42     int *naccum;
43     fs->len *= 2;
44
45     nbuf = MEM_callocN(sizeof(*fs->buf) * fs->len, "fs->buf");
46     naccum = MEM_callocN(sizeof(*fs->accum) * fs->len, "fs->accum");
47
48     memcpy(nbuf, fs->buf, fs->pos * sizeof(*fs->buf));
49     memcpy(naccum, fs->accum, fs->pos * sizeof(*fs->accum));
50
51     if (fs->buf != fs->fixedbuf) {
52       MEM_freeN(fs->buf);
53       MEM_freeN(fs->accum);
54     }
55
56     fs->buf = nbuf;
57     fs->accum = naccum;
58   }
59
60   for (i = 0; i < len; i++) {
61     fs->buf[fs->pos + i] = c[i];
62     fs->accum[fs->pos + i] = accum;
63   }
64
65   fs->pos += len;
66 }
67
68 int flatten_string(const SpaceText *st, FlattenString *fs, const char *in)
69 {
70   int r, i, total = 0;
71
72   memset(fs, 0, sizeof(FlattenString));
73   fs->buf = fs->fixedbuf;
74   fs->accum = fs->fixedaccum;
75   fs->len = sizeof(fs->fixedbuf);
76
77   for (r = 0, i = 0; *in; r++) {
78     if (*in == '\t') {
79       i = st->tabnumber - (total % st->tabnumber);
80       total += i;
81
82       while (i--) {
83         flatten_string_append(fs, " ", r, 1);
84       }
85
86       in++;
87     }
88     else {
89       size_t len = BLI_str_utf8_size_safe(in);
90       flatten_string_append(fs, in, r, len);
91       in += len;
92       total++;
93     }
94   }
95
96   flatten_string_append(fs, "\0", r, 1);
97
98   return total;
99 }
100
101 void flatten_string_free(FlattenString *fs)
102 {
103   if (fs->buf != fs->fixedbuf) {
104     MEM_freeN(fs->buf);
105   }
106   if (fs->accum != fs->fixedaccum) {
107     MEM_freeN(fs->accum);
108   }
109 }
110
111 /* takes a string within fs->buf and returns its length */
112 int flatten_string_strlen(FlattenString *fs, const char *str)
113 {
114   const int len = (fs->pos - (int)(str - fs->buf)) - 1;
115   BLI_assert(strlen(str) == len);
116   return len;
117 }
118
119 /* Ensures the format string for the given line is long enough, reallocating
120  * as needed. Allocation is done here, alone, to ensure consistency. */
121 int text_check_format_len(TextLine *line, unsigned int len)
122 {
123   if (line->format) {
124     if (strlen(line->format) < len) {
125       MEM_freeN(line->format);
126       line->format = MEM_mallocN(len + 2, "SyntaxFormat");
127       if (!line->format) {
128         return 0;
129       }
130     }
131   }
132   else {
133     line->format = MEM_mallocN(len + 2, "SyntaxFormat");
134     if (!line->format) {
135       return 0;
136     }
137   }
138
139   return 1;
140 }
141
142 /**
143  * Fill the string with formatting constant,
144  * advancing \a str_p and \a fmt_p
145  *
146  * \param len: length in bytes of \a fmt_p to fill.
147  */
148 void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len)
149 {
150   const char *str = *str_p;
151   char *fmt = *fmt_p;
152   int i = 0;
153
154   while (i < len) {
155     const int size = BLI_str_utf8_size_safe(str);
156     *fmt++ = type;
157
158     str += size;
159     i += 1;
160   }
161
162   str--;
163   fmt--;
164
165   BLI_assert(*str != '\0');
166
167   *str_p = str;
168   *fmt_p = fmt;
169 }
170 /**
171  * ascii version of #text_format_fill,
172  * use when we no the text being stepped over is ascii (as is the case for most keywords)
173  */
174 void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len)
175 {
176   const char *str = *str_p;
177   char *fmt = *fmt_p;
178
179   memset(fmt, type, len);
180
181   str += len - 1;
182   fmt += len - 1;
183
184   BLI_assert(*str != '\0');
185
186   *str_p = str;
187   *fmt_p = fmt;
188 }
189
190 /* *** Registration *** */
191 static ListBase tft_lb = {NULL, NULL};
192 void ED_text_format_register(TextFormatType *tft)
193 {
194   BLI_addtail(&tft_lb, tft);
195 }
196
197 TextFormatType *ED_text_format_get(Text *text)
198 {
199   TextFormatType *tft;
200
201   if (text) {
202     const char *text_ext = strchr(text->id.name + 2, '.');
203     if (text_ext) {
204       text_ext++; /* skip the '.' */
205       /* Check all text formats in the static list */
206       for (tft = tft_lb.first; tft; tft = tft->next) {
207         /* All formats should have an ext, but just in case */
208         const char **ext;
209         for (ext = tft->ext; *ext; ext++) {
210           /* If extension matches text name, return the matching tft */
211           if (BLI_strcasecmp(text_ext, *ext) == 0) {
212             return tft;
213           }
214         }
215       }
216     }
217
218     /* If we make it here we never found an extension that worked - return
219      * the "default" text format */
220     return tft_lb.first;
221   }
222   else {
223     /* Return the "default" text format */
224     return tft_lb.first;
225   }
226 }