Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / space_text / text_format_pov.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
16 /** \file
17  * \ingroup sptext
18  */
19
20 #include <string.h>
21
22 #include "BLI_blenlib.h"
23
24 #include "DNA_text_types.h"
25 #include "DNA_space_types.h"
26
27 #include "BKE_text.h"
28
29 #include "text_format.h"
30
31 /* *** POV Keywords (for format_line) *** */
32
33 /**
34  * Checks the specified source string for a POV keyword (minus boolean & 'nil').
35  * This name must start at the beginning of the source string and must be
36  * followed by a non-identifier (see #text_check_identifier(char)) or null char.
37  *
38  * If a keyword is found, the length of the matching word is returned.
39  * Otherwise, -1 is returned.
40  *
41  * See:
42  * http://www.povray.org/documentation/view/3.7.0/212/
43  */
44 static int txtfmt_pov_find_keyword(const char *string)
45 {
46   /* Keep aligned args for readability. */
47   /* clang-format off */
48
49   int i, len;
50   /* Language Directives */
51   if      (STR_LITERAL_STARTSWITH(string, "deprecated",  len)) { i = len;
52   } else if (STR_LITERAL_STARTSWITH(string, "persistent",  len)) { i = len;
53   } else if (STR_LITERAL_STARTSWITH(string, "statistics",  len)) { i = len;
54   } else if (STR_LITERAL_STARTSWITH(string, "version",     len)) { i = len;
55   } else if (STR_LITERAL_STARTSWITH(string, "warning",     len)) { i = len;
56   } else if (STR_LITERAL_STARTSWITH(string, "declare",     len)) { i = len;
57   } else if (STR_LITERAL_STARTSWITH(string, "default",     len)) { i = len;
58   } else if (STR_LITERAL_STARTSWITH(string, "include",     len)) { i = len;
59   } else if (STR_LITERAL_STARTSWITH(string, "append",      len)) { i = len;
60   } else if (STR_LITERAL_STARTSWITH(string, "elseif",      len)) { i = len;
61   } else if (STR_LITERAL_STARTSWITH(string, "debug",       len)) { i = len;
62   } else if (STR_LITERAL_STARTSWITH(string, "break",       len)) { i = len;
63   } else if (STR_LITERAL_STARTSWITH(string, "else",        len)) { i = len;
64   } else if (STR_LITERAL_STARTSWITH(string, "error",       len)) { i = len;
65   } else if (STR_LITERAL_STARTSWITH(string, "fclose",      len)) { i = len;
66   } else if (STR_LITERAL_STARTSWITH(string, "fopen",       len)) { i = len;
67   } else if (STR_LITERAL_STARTSWITH(string, "ifndef",      len)) { i = len;
68   } else if (STR_LITERAL_STARTSWITH(string, "ifdef",       len)) { i = len;
69   } else if (STR_LITERAL_STARTSWITH(string, "patch",       len)) { i = len;
70   } else if (STR_LITERAL_STARTSWITH(string, "local",       len)) { i = len;
71   } else if (STR_LITERAL_STARTSWITH(string, "macro",       len)) { i = len;
72   } else if (STR_LITERAL_STARTSWITH(string, "range",       len)) { i = len;
73   } else if (STR_LITERAL_STARTSWITH(string, "read",        len)) { i = len;
74   } else if (STR_LITERAL_STARTSWITH(string, "render",      len)) { i = len;
75   } else if (STR_LITERAL_STARTSWITH(string, "switch",      len)) { i = len;
76   } else if (STR_LITERAL_STARTSWITH(string, "undef",       len)) { i = len;
77   } else if (STR_LITERAL_STARTSWITH(string, "while",       len)) { i = len;
78   } else if (STR_LITERAL_STARTSWITH(string, "write",       len)) { i = len;
79   } else if (STR_LITERAL_STARTSWITH(string, "case",        len)) { i = len;
80   } else if (STR_LITERAL_STARTSWITH(string, "end",         len)) { i = len;
81   } else if (STR_LITERAL_STARTSWITH(string, "for",         len)) { i = len;
82   } else if (STR_LITERAL_STARTSWITH(string, "if",          len)) { i = len;
83   } else {                                                         i = 0;
84 }
85
86   /* clang-format on */
87
88   /* If next source char is an identifier (eg. 'i' in "definite") no match */
89   return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
90 }
91
92 static int txtfmt_pov_find_reserved_keywords(const char *string)
93 {
94   int i, len;
95   /* POV-Ray Built-in Variables
96    * list is from...
97    * http://www.povray.org/documentation/view/3.7.0/212/
98    */
99
100   /* Keep aligned args for readability. */
101   /* clang-format off */
102
103   /* Float Functions */
104   if      (STR_LITERAL_STARTSWITH(string, "conserve_energy",    len)) { i = len;
105   } else if (STR_LITERAL_STARTSWITH(string, "max_intersections",  len)) { i = len;
106   } else if (STR_LITERAL_STARTSWITH(string, "dimension_size",     len)) { i = len;
107   } else if (STR_LITERAL_STARTSWITH(string, "bitwise_and",        len)) { i = len;
108   } else if (STR_LITERAL_STARTSWITH(string, "bitwise_or",         len)) { i = len;
109   } else if (STR_LITERAL_STARTSWITH(string, "bitwise_xor",        len)) { i = len;
110   } else if (STR_LITERAL_STARTSWITH(string, "file_exists",        len)) { i = len;
111   } else if (STR_LITERAL_STARTSWITH(string, "precompute",         len)) { i = len;
112   } else if (STR_LITERAL_STARTSWITH(string, "dimensions",         len)) { i = len;
113   } else if (STR_LITERAL_STARTSWITH(string, "clipped_by",         len)) { i = len;
114   } else if (STR_LITERAL_STARTSWITH(string, "shadowless",         len)) { i = len;
115   } else if (STR_LITERAL_STARTSWITH(string, "turb_depth",         len)) { i = len;
116   } else if (STR_LITERAL_STARTSWITH(string, "reciprocal",         len)) { i = len;
117   } else if (STR_LITERAL_STARTSWITH(string, "quaternion",         len)) { i = len;
118   } else if (STR_LITERAL_STARTSWITH(string, "phong_size",         len)) { i = len;
119   } else if (STR_LITERAL_STARTSWITH(string, "tesselate",          len)) { i = len;
120   } else if (STR_LITERAL_STARTSWITH(string, "save_file",          len)) { i = len;
121   } else if (STR_LITERAL_STARTSWITH(string, "load_file",          len)) { i = len;
122   } else if (STR_LITERAL_STARTSWITH(string, "max_trace",          len)) { i = len;
123   } else if (STR_LITERAL_STARTSWITH(string, "transform",          len)) { i = len;
124   } else if (STR_LITERAL_STARTSWITH(string, "translate",          len)) { i = len;
125   } else if (STR_LITERAL_STARTSWITH(string, "direction",          len)) { i = len;
126   } else if (STR_LITERAL_STARTSWITH(string, "roughness",          len)) { i = len;
127   } else if (STR_LITERAL_STARTSWITH(string, "metallic",           len)) { i = len;
128   } else if (STR_LITERAL_STARTSWITH(string, "gts_load",           len)) { i = len;
129   } else if (STR_LITERAL_STARTSWITH(string, "gts_save",           len)) { i = len;
130   } else if (STR_LITERAL_STARTSWITH(string, "location",           len)) { i = len;
131   } else if (STR_LITERAL_STARTSWITH(string, "altitude",           len)) { i = len;
132   } else if (STR_LITERAL_STARTSWITH(string, "function",           len)) { i = len;
133   } else if (STR_LITERAL_STARTSWITH(string, "evaluate",           len)) { i = len;
134   } else if (STR_LITERAL_STARTSWITH(string, "inverse",            len)) { i = len;
135   } else if (STR_LITERAL_STARTSWITH(string, "collect",            len)) { i = len;
136   } else if (STR_LITERAL_STARTSWITH(string, "target",             len)) { i = len;
137   } else if (STR_LITERAL_STARTSWITH(string, "albedo",             len)) { i = len;
138   } else if (STR_LITERAL_STARTSWITH(string, "rotate",             len)) { i = len;
139   } else if (STR_LITERAL_STARTSWITH(string, "matrix",             len)) { i = len;
140   } else if (STR_LITERAL_STARTSWITH(string, "look_at",            len)) { i = len;
141   } else if (STR_LITERAL_STARTSWITH(string, "jitter",             len)) { i = len;
142   } else if (STR_LITERAL_STARTSWITH(string, "angle",              len)) { i = len;
143   } else if (STR_LITERAL_STARTSWITH(string, "right",              len)) { i = len;
144   } else if (STR_LITERAL_STARTSWITH(string, "scale",              len)) { i = len;
145   } else if (STR_LITERAL_STARTSWITH(string, "child",              len)) { i = len;
146   } else if (STR_LITERAL_STARTSWITH(string, "crand",              len)) { i = len;
147   } else if (STR_LITERAL_STARTSWITH(string, "blink",              len)) { i = len;
148   } else if (STR_LITERAL_STARTSWITH(string, "defined",            len)) { i = len;
149   } else if (STR_LITERAL_STARTSWITH(string, "degrees",            len)) { i = len;
150   } else if (STR_LITERAL_STARTSWITH(string, "inside",             len)) { i = len;
151   } else if (STR_LITERAL_STARTSWITH(string, "radians",            len)) { i = len;
152   } else if (STR_LITERAL_STARTSWITH(string, "vlength",            len)) { i = len;
153   } else if (STR_LITERAL_STARTSWITH(string, "select",             len)) { i = len;
154   } else if (STR_LITERAL_STARTSWITH(string, "floor",              len)) { i = len;
155   } else if (STR_LITERAL_STARTSWITH(string, "strcmp",             len)) { i = len;
156   } else if (STR_LITERAL_STARTSWITH(string, "strlen",             len)) { i = len;
157   } else if (STR_LITERAL_STARTSWITH(string, "tessel",             len)) { i = len;
158   } else if (STR_LITERAL_STARTSWITH(string, "sturm",              len)) { i = len;
159   } else if (STR_LITERAL_STARTSWITH(string, "abs",                len)) { i = len;
160   } else if (STR_LITERAL_STARTSWITH(string, "acosh",              len)) { i = len;
161   } else if (STR_LITERAL_STARTSWITH(string, "prod",               len)) { i = len;
162   } else if (STR_LITERAL_STARTSWITH(string, "with",               len)) { i = len;
163   } else if (STR_LITERAL_STARTSWITH(string, "acos",               len)) { i = len;
164   } else if (STR_LITERAL_STARTSWITH(string, "asc",                len)) { i = len;
165   } else if (STR_LITERAL_STARTSWITH(string, "asinh",              len)) { i = len;
166   } else if (STR_LITERAL_STARTSWITH(string, "asin",               len)) { i = len;
167   } else if (STR_LITERAL_STARTSWITH(string, "atan2",              len)) { i = len;
168   } else if (STR_LITERAL_STARTSWITH(string, "atand",              len)) { i = len;
169   } else if (STR_LITERAL_STARTSWITH(string, "atanh",              len)) { i = len;
170   } else if (STR_LITERAL_STARTSWITH(string, "atan",               len)) { i = len;
171   } else if (STR_LITERAL_STARTSWITH(string, "ceil",               len)) { i = len;
172   } else if (STR_LITERAL_STARTSWITH(string, "warp",               len)) { i = len;
173   } else if (STR_LITERAL_STARTSWITH(string, "cosh",               len)) { i = len;
174   } else if (STR_LITERAL_STARTSWITH(string, "log",                len)) { i = len;
175   } else if (STR_LITERAL_STARTSWITH(string, "max",                len)) { i = len;
176   } else if (STR_LITERAL_STARTSWITH(string, "min",                len)) { i = len;
177   } else if (STR_LITERAL_STARTSWITH(string, "mod",                len)) { i = len;
178   } else if (STR_LITERAL_STARTSWITH(string, "pow",                len)) { i = len;
179   } else if (STR_LITERAL_STARTSWITH(string, "rand",               len)) { i = len;
180   } else if (STR_LITERAL_STARTSWITH(string, "seed",               len)) { i = len;
181   } else if (STR_LITERAL_STARTSWITH(string, "form",               len)) { i = len;
182   } else if (STR_LITERAL_STARTSWITH(string, "sinh",               len)) { i = len;
183   } else if (STR_LITERAL_STARTSWITH(string, "sqrt",               len)) { i = len;
184   } else if (STR_LITERAL_STARTSWITH(string, "tanh",               len)) { i = len;
185   } else if (STR_LITERAL_STARTSWITH(string, "vdot",               len)) { i = len;
186   } else if (STR_LITERAL_STARTSWITH(string, "sin",                len)) { i = len;
187   } else if (STR_LITERAL_STARTSWITH(string, "sqr",                len)) { i = len;
188   } else if (STR_LITERAL_STARTSWITH(string, "sum",                len)) { i = len;
189   } else if (STR_LITERAL_STARTSWITH(string, "pwr",                len)) { i = len;
190   } else if (STR_LITERAL_STARTSWITH(string, "tan",                len)) { i = len;
191   } else if (STR_LITERAL_STARTSWITH(string, "val",                len)) { i = len;
192   } else if (STR_LITERAL_STARTSWITH(string, "cos",                len)) { i = len;
193   } else if (STR_LITERAL_STARTSWITH(string, "div",                len)) { i = len;
194   } else if (STR_LITERAL_STARTSWITH(string, "exp",                len)) { i = len;
195   } else if (STR_LITERAL_STARTSWITH(string, "int",                len)) { i = len;
196   } else if (STR_LITERAL_STARTSWITH(string, "sky",                len)) { i = len;
197   } else if (STR_LITERAL_STARTSWITH(string, "up",                 len)) { i = len;
198   } else if (STR_LITERAL_STARTSWITH(string, "ln",                 len)) { i = len;
199   /* Color Identifiers */
200   } else if (STR_LITERAL_STARTSWITH(string, "transmit",            len)) { i = len;
201   } else if (STR_LITERAL_STARTSWITH(string, "filter",              len)) { i = len;
202   } else if (STR_LITERAL_STARTSWITH(string, "srgbft",              len)) { i = len;
203   } else if (STR_LITERAL_STARTSWITH(string, "srgbf",               len)) { i = len;
204   } else if (STR_LITERAL_STARTSWITH(string, "srgbt",               len)) { i = len;
205   } else if (STR_LITERAL_STARTSWITH(string, "rgbft",               len)) { i = len;
206   } else if (STR_LITERAL_STARTSWITH(string, "gamma",               len)) { i = len;
207   } else if (STR_LITERAL_STARTSWITH(string, "green",               len)) { i = len;
208   } else if (STR_LITERAL_STARTSWITH(string, "blue",                len)) { i = len;
209   } else if (STR_LITERAL_STARTSWITH(string, "gray",                len)) { i = len;
210   } else if (STR_LITERAL_STARTSWITH(string, "srgb",                len)) { i = len;
211   } else if (STR_LITERAL_STARTSWITH(string, "sRGB",                len)) { i = len;
212   } else if (STR_LITERAL_STARTSWITH(string, "SRGB",                len)) { i = len;
213   } else if (STR_LITERAL_STARTSWITH(string, "rgbf",                len)) { i = len;
214   } else if (STR_LITERAL_STARTSWITH(string, "rgbt",                len)) { i = len;
215   } else if (STR_LITERAL_STARTSWITH(string, "rgb",                 len)) { i = len;
216   } else if (STR_LITERAL_STARTSWITH(string, "red",                 len)) { i = len;
217   /* Color Spaces */
218   } else if (STR_LITERAL_STARTSWITH(string, "pov",                 len)) { i = len;
219   } else if (STR_LITERAL_STARTSWITH(string, "hsl",                 len)) { i = len;
220   } else if (STR_LITERAL_STARTSWITH(string, "hsv",                 len)) { i = len;
221   } else if (STR_LITERAL_STARTSWITH(string, "xyl",                 len)) { i = len;
222   } else if (STR_LITERAL_STARTSWITH(string, "xyv",                 len)) { i = len;
223   /* Vector Functions */
224   } else if (STR_LITERAL_STARTSWITH(string, "vaxis_rotate",       len)) { i = len;
225   } else if (STR_LITERAL_STARTSWITH(string, "vturbulence",        len)) { i = len;
226   } else if (STR_LITERAL_STARTSWITH(string, "min_extent",         len)) { i = len;
227   } else if (STR_LITERAL_STARTSWITH(string, "vnormalize",         len)) { i = len;
228   } else if (STR_LITERAL_STARTSWITH(string, "max_extent",         len)) { i = len;
229   } else if (STR_LITERAL_STARTSWITH(string, "vrotate",            len)) { i = len;
230   } else if (STR_LITERAL_STARTSWITH(string, "vcross",             len)) { i = len;
231   } else if (STR_LITERAL_STARTSWITH(string, "trace",              len)) { i = len;
232   /* String Functions */
233   } else if (STR_LITERAL_STARTSWITH(string, "file_time",          len)) { i = len;
234   } else if (STR_LITERAL_STARTSWITH(string, "datetime",           len)) { i = len;
235   } else if (STR_LITERAL_STARTSWITH(string, "concat",             len)) { i = len;
236   } else if (STR_LITERAL_STARTSWITH(string, "strlwr",             len)) { i = len;
237   } else if (STR_LITERAL_STARTSWITH(string, "strupr",             len)) { i = len;
238   } else if (STR_LITERAL_STARTSWITH(string, "substr",             len)) { i = len;
239   } else if (STR_LITERAL_STARTSWITH(string, "vstr",               len)) { i = len;
240   } else if (STR_LITERAL_STARTSWITH(string, "chr",                len)) { i = len;
241   } else if (STR_LITERAL_STARTSWITH(string, "str",                len)) { i = len;
242   } else {                                                                i = 0;
243 }
244
245   /* clang-format on */
246
247   /* If next source char is an identifier (eg. 'i' in "definite") no match */
248   return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
249 }
250
251 static int txtfmt_pov_find_reserved_builtins(const char *string)
252 {
253   int i, len;
254
255   /* POV-Ray Built-in Variables
256    * list is from...
257    * http://www.povray.org/documentation/view/3.7.0/212/
258    */
259
260   /* Keep aligned args for readability. */
261   /* clang-format off */
262
263   /* Language Keywords */
264   if      (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) { i = len;
265   } else if (STR_LITERAL_STARTSWITH(string, "area_illumination",   len)) { i = len;
266   } else if (STR_LITERAL_STARTSWITH(string, "all_intersections",   len)) { i = len;
267   } else if (STR_LITERAL_STARTSWITH(string, "cutaway_textures",    len)) { i = len;
268   } else if (STR_LITERAL_STARTSWITH(string, "smooth_triangle",     len)) { i = len;
269   } else if (STR_LITERAL_STARTSWITH(string, "lommel_seeliger",     len)) { i = len;
270   } else if (STR_LITERAL_STARTSWITH(string, "falloff_angle",       len)) { i = len;
271   } else if (STR_LITERAL_STARTSWITH(string, "aa_threshold",        len)) { i = len;
272   } else if (STR_LITERAL_STARTSWITH(string, "hypercomplex",        len)) { i = len;
273   } else if (STR_LITERAL_STARTSWITH(string, "major_radius",        len)) { i = len;
274   } else if (STR_LITERAL_STARTSWITH(string, "max_distance",        len)) { i = len;
275   } else if (STR_LITERAL_STARTSWITH(string, "max_iteration",       len)) { i = len;
276   } else if (STR_LITERAL_STARTSWITH(string, "colour_space",        len)) { i = len;
277   } else if (STR_LITERAL_STARTSWITH(string, "color_space",         len)) { i = len;
278   } else if (STR_LITERAL_STARTSWITH(string, "iridescence",         len)) { i = len;
279   } else if (STR_LITERAL_STARTSWITH(string, "subsurface",          len)) { i = len;
280   } else if (STR_LITERAL_STARTSWITH(string, "scattering",          len)) { i = len;
281   } else if (STR_LITERAL_STARTSWITH(string, "absorption",          len)) { i = len;
282   } else if (STR_LITERAL_STARTSWITH(string, "water_level",         len)) { i = len;
283   } else if (STR_LITERAL_STARTSWITH(string, "reflection",          len)) { i = len;
284   } else if (STR_LITERAL_STARTSWITH(string, "max_extent",          len)) { i = len;
285   } else if (STR_LITERAL_STARTSWITH(string, "oren_nayar",          len)) { i = len;
286   } else if (STR_LITERAL_STARTSWITH(string, "refraction",          len)) { i = len;
287   } else if (STR_LITERAL_STARTSWITH(string, "hierarchy",           len)) { i = len;
288   } else if (STR_LITERAL_STARTSWITH(string, "radiosity",           len)) { i = len;
289   } else if (STR_LITERAL_STARTSWITH(string, "tolerance",           len)) { i = len;
290   } else if (STR_LITERAL_STARTSWITH(string, "interior",            len)) { i = len;
291   } else if (STR_LITERAL_STARTSWITH(string, "toroidal",            len)) { i = len;
292   } else if (STR_LITERAL_STARTSWITH(string, "emission",            len)) { i = len;
293   } else if (STR_LITERAL_STARTSWITH(string, "material",            len)) { i = len;
294   } else if (STR_LITERAL_STARTSWITH(string, "internal",            len)) { i = len;
295   } else if (STR_LITERAL_STARTSWITH(string, "photons",             len)) { i = len;
296   } else if (STR_LITERAL_STARTSWITH(string, "arc_angle",           len)) { i = len;
297   } else if (STR_LITERAL_STARTSWITH(string, "minnaert",            len)) { i = len;
298   } else if (STR_LITERAL_STARTSWITH(string, "texture",             len)) { i = len;
299   } else if (STR_LITERAL_STARTSWITH(string, "array",               len)) { i = len;
300   } else if (STR_LITERAL_STARTSWITH(string, "black_hole",          len)) { i = len;
301   } else if (STR_LITERAL_STARTSWITH(string, "component",           len)) { i = len;
302   } else if (STR_LITERAL_STARTSWITH(string, "composite",           len)) { i = len;
303   } else if (STR_LITERAL_STARTSWITH(string, "coords",              len)) { i = len;
304   } else if (STR_LITERAL_STARTSWITH(string, "cube",                len)) { i = len;
305   } else if (STR_LITERAL_STARTSWITH(string, "dist_exp",            len)) { i = len;
306   } else if (STR_LITERAL_STARTSWITH(string, "exterior",            len)) { i = len;
307   } else if (STR_LITERAL_STARTSWITH(string, "file_gamma",          len)) { i = len;
308   } else if (STR_LITERAL_STARTSWITH(string, "flatness",            len)) { i = len;
309   } else if (STR_LITERAL_STARTSWITH(string, "planet",              len)) { i = len;
310   } else if (STR_LITERAL_STARTSWITH(string, "screw",               len)) { i = len;
311   } else if (STR_LITERAL_STARTSWITH(string, "keep",                len)) { i = len;
312   } else if (STR_LITERAL_STARTSWITH(string, "flip",                len)) { i = len;
313   } else if (STR_LITERAL_STARTSWITH(string, "move",                len)) { i = len;
314   } else if (STR_LITERAL_STARTSWITH(string, "roll",                len)) { i = len;
315   } else if (STR_LITERAL_STARTSWITH(string, "look_at",             len)) { i = len;
316   } else if (STR_LITERAL_STARTSWITH(string, "metric",              len)) { i = len;
317   } else if (STR_LITERAL_STARTSWITH(string, "offset",              len)) { i = len;
318   } else if (STR_LITERAL_STARTSWITH(string, "orientation",         len)) { i = len;
319   } else if (STR_LITERAL_STARTSWITH(string, "pattern",             len)) { i = len;
320   } else if (STR_LITERAL_STARTSWITH(string, "precision",           len)) { i = len;
321   } else if (STR_LITERAL_STARTSWITH(string, "width",               len)) { i = len;
322   } else if (STR_LITERAL_STARTSWITH(string, "repeat",              len)) { i = len;
323   } else if (STR_LITERAL_STARTSWITH(string, "bend",                len)) { i = len;
324   } else if (STR_LITERAL_STARTSWITH(string, "size",                len)) { i = len;
325   } else if (STR_LITERAL_STARTSWITH(string, "alpha",               len)) { i = len;
326   } else if (STR_LITERAL_STARTSWITH(string, "slice",               len)) { i = len;
327   } else if (STR_LITERAL_STARTSWITH(string, "smooth",              len)) { i = len;
328   } else if (STR_LITERAL_STARTSWITH(string, "solid",               len)) { i = len;
329   } else if (STR_LITERAL_STARTSWITH(string, "all",                 len)) { i = len;
330   } else if (STR_LITERAL_STARTSWITH(string, "now",                 len)) { i = len;
331   } else if (STR_LITERAL_STARTSWITH(string, "pot",                 len)) { i = len;
332   } else if (STR_LITERAL_STARTSWITH(string, "type",                len)) { i = len;
333   /* Animation Options */
334   } else if (STR_LITERAL_STARTSWITH(string, "global_settings",     len)) { i = len;
335   } else if (STR_LITERAL_STARTSWITH(string, "input_file_name",     len)) { i = len;
336   } else if (STR_LITERAL_STARTSWITH(string, "initial_clock",       len)) { i = len;
337   } else if (STR_LITERAL_STARTSWITH(string, "initial_frame",       len)) { i = len;
338   } else if (STR_LITERAL_STARTSWITH(string, "frame_number",        len)) { i = len;
339   } else if (STR_LITERAL_STARTSWITH(string, "image_height",        len)) { i = len;
340   } else if (STR_LITERAL_STARTSWITH(string, "image_width",         len)) { i = len;
341   } else if (STR_LITERAL_STARTSWITH(string, "final_clock",         len)) { i = len;
342   } else if (STR_LITERAL_STARTSWITH(string, "final_frame",         len)) { i = len;
343   } else if (STR_LITERAL_STARTSWITH(string, "clock_delta",         len)) { i = len;
344   } else if (STR_LITERAL_STARTSWITH(string, "clock_on",            len)) { i = len;
345   } else if (STR_LITERAL_STARTSWITH(string, "clock",               len)) { i = len;
346   /* Spline Identifiers */
347   } else if (STR_LITERAL_STARTSWITH(string, "extended_x_spline",   len)) { i = len;
348   } else if (STR_LITERAL_STARTSWITH(string, "general_x_spline",    len)) { i = len;
349   } else if (STR_LITERAL_STARTSWITH(string, "quadratic_spline",    len)) { i = len;
350   } else if (STR_LITERAL_STARTSWITH(string, "basic_x_spline",      len)) { i = len;
351   } else if (STR_LITERAL_STARTSWITH(string, "natural_spline",      len)) { i = len;
352   } else if (STR_LITERAL_STARTSWITH(string, "linear_spline",       len)) { i = len;
353   } else if (STR_LITERAL_STARTSWITH(string, "bezier_spline",       len)) { i = len;
354   } else if (STR_LITERAL_STARTSWITH(string, "akima_spline",        len)) { i = len;
355   } else if (STR_LITERAL_STARTSWITH(string, "cubic_spline",        len)) { i = len;
356   } else if (STR_LITERAL_STARTSWITH(string, "sor_spline",          len)) { i = len;
357   } else if (STR_LITERAL_STARTSWITH(string, "tcb_spline",          len)) { i = len;
358   } else if (STR_LITERAL_STARTSWITH(string, "linear_sweep",        len)) { i = len;
359   } else if (STR_LITERAL_STARTSWITH(string, "conic_sweep",         len)) { i = len;
360   } else if (STR_LITERAL_STARTSWITH(string, "b_spline",            len)) { i = len;
361   /* Patterns */
362   } else if (STR_LITERAL_STARTSWITH(string, "pigment_pattern",     len)) { i = len;
363   } else if (STR_LITERAL_STARTSWITH(string, "image_pattern",       len)) { i = len;
364   } else if (STR_LITERAL_STARTSWITH(string, "density_file",        len)) { i = len;
365   } else if (STR_LITERAL_STARTSWITH(string, "cylindrical",         len)) { i = len;
366   } else if (STR_LITERAL_STARTSWITH(string, "proportion",          len)) { i = len;
367   } else if (STR_LITERAL_STARTSWITH(string, "triangular",          len)) { i = len;
368   } else if (STR_LITERAL_STARTSWITH(string, "image_map",           len)) { i = len;
369   } else if (STR_LITERAL_STARTSWITH(string, "proximity",           len)) { i = len;
370   } else if (STR_LITERAL_STARTSWITH(string, "spherical",           len)) { i = len;
371   } else if (STR_LITERAL_STARTSWITH(string, "bump_map",            len)) { i = len;
372   } else if (STR_LITERAL_STARTSWITH(string, "wrinkles",            len)) { i = len;
373   } else if (STR_LITERAL_STARTSWITH(string, "average",             len)) { i = len;
374   } else if (STR_LITERAL_STARTSWITH(string, "voronoi",             len)) { i = len;
375   } else if (STR_LITERAL_STARTSWITH(string, "masonry",             len)) { i = len;
376   } else if (STR_LITERAL_STARTSWITH(string, "binary",              len)) { i = len;
377   } else if (STR_LITERAL_STARTSWITH(string, "boxed",               len)) { i = len;
378   } else if (STR_LITERAL_STARTSWITH(string, "bozo",                len)) { i = len;
379   } else if (STR_LITERAL_STARTSWITH(string, "brick",               len)) { i = len;
380   } else if (STR_LITERAL_STARTSWITH(string, "bumps",               len)) { i = len;
381   } else if (STR_LITERAL_STARTSWITH(string, "cells",               len)) { i = len;
382   } else if (STR_LITERAL_STARTSWITH(string, "checker",             len)) { i = len;
383   } else if (STR_LITERAL_STARTSWITH(string, "crackle",             len)) { i = len;
384   } else if (STR_LITERAL_STARTSWITH(string, "cubic",               len)) { i = len;
385   } else if (STR_LITERAL_STARTSWITH(string, "dents",               len)) { i = len;
386   } else if (STR_LITERAL_STARTSWITH(string, "facets",              len)) { i = len;
387   } else if (STR_LITERAL_STARTSWITH(string, "gradient",            len)) { i = len;
388   } else if (STR_LITERAL_STARTSWITH(string, "granite",             len)) { i = len;
389   } else if (STR_LITERAL_STARTSWITH(string, "hexagon",             len)) { i = len;
390   } else if (STR_LITERAL_STARTSWITH(string, "julia",               len)) { i = len;
391   } else if (STR_LITERAL_STARTSWITH(string, "leopard",             len)) { i = len;
392   } else if (STR_LITERAL_STARTSWITH(string, "magnet",              len)) { i = len;
393   } else if (STR_LITERAL_STARTSWITH(string, "mandel",              len)) { i = len;
394   } else if (STR_LITERAL_STARTSWITH(string, "marble",              len)) { i = len;
395   } else if (STR_LITERAL_STARTSWITH(string, "onion",               len)) { i = len;
396   } else if (STR_LITERAL_STARTSWITH(string, "pavement",            len)) { i = len;
397   } else if (STR_LITERAL_STARTSWITH(string, "planar",              len)) { i = len;
398   } else if (STR_LITERAL_STARTSWITH(string, "quilted",             len)) { i = len;
399   } else if (STR_LITERAL_STARTSWITH(string, "radial",              len)) { i = len;
400   } else if (STR_LITERAL_STARTSWITH(string, "ripples",             len)) { i = len;
401   } else if (STR_LITERAL_STARTSWITH(string, "slope",               len)) { i = len;
402   } else if (STR_LITERAL_STARTSWITH(string, "spiral1",             len)) { i = len;
403   } else if (STR_LITERAL_STARTSWITH(string, "spiral2",             len)) { i = len;
404   } else if (STR_LITERAL_STARTSWITH(string, "spotted",             len)) { i = len;
405   } else if (STR_LITERAL_STARTSWITH(string, "square",              len)) { i = len;
406   } else if (STR_LITERAL_STARTSWITH(string, "tile2",               len)) { i = len;
407   } else if (STR_LITERAL_STARTSWITH(string, "tiling",              len)) { i = len;
408   } else if (STR_LITERAL_STARTSWITH(string, "tiles",               len)) { i = len;
409   } else if (STR_LITERAL_STARTSWITH(string, "waves",               len)) { i = len;
410   } else if (STR_LITERAL_STARTSWITH(string, "wood",                len)) { i = len;
411   } else if (STR_LITERAL_STARTSWITH(string, "agate",               len)) { i = len;
412   } else if (STR_LITERAL_STARTSWITH(string, "aoi",                 len)) { i = len;
413   /* Objects */
414   } else if (STR_LITERAL_STARTSWITH(string, "superellipsoid",      len)) { i = len;
415   } else if (STR_LITERAL_STARTSWITH(string, "bicubic_patch",       len)) { i = len;
416   } else if (STR_LITERAL_STARTSWITH(string, "julia_fractal",       len)) { i = len;
417   } else if (STR_LITERAL_STARTSWITH(string, "height_field",        len)) { i = len;
418   } else if (STR_LITERAL_STARTSWITH(string, "cubic_spline",        len)) { i = len;
419   } else if (STR_LITERAL_STARTSWITH(string, "sphere_sweep",        len)) { i = len;
420   } else if (STR_LITERAL_STARTSWITH(string, "light_group",         len)) { i = len;
421   } else if (STR_LITERAL_STARTSWITH(string, "light_source",        len)) { i = len;
422   } else if (STR_LITERAL_STARTSWITH(string, "intersection",        len)) { i = len;
423   } else if (STR_LITERAL_STARTSWITH(string, "isosurface",          len)) { i = len;
424   } else if (STR_LITERAL_STARTSWITH(string, "background",          len)) { i = len;
425   } else if (STR_LITERAL_STARTSWITH(string, "sky_sphere",          len)) { i = len;
426   } else if (STR_LITERAL_STARTSWITH(string, "cylinder",            len)) { i = len;
427   } else if (STR_LITERAL_STARTSWITH(string, "difference",          len)) { i = len;
428   } else if (STR_LITERAL_STARTSWITH(string, "brilliance",          len)) { i = len;
429   } else if (STR_LITERAL_STARTSWITH(string, "parametric",          len)) { i = len;
430   } else if (STR_LITERAL_STARTSWITH(string, "interunion",          len)) { i = len;
431   } else if (STR_LITERAL_STARTSWITH(string, "intermerge",          len)) { i = len;
432   } else if (STR_LITERAL_STARTSWITH(string, "polynomial",          len)) { i = len;
433   } else if (STR_LITERAL_STARTSWITH(string, "displace",            len)) { i = len;
434   } else if (STR_LITERAL_STARTSWITH(string, "specular",            len)) { i = len;
435   } else if (STR_LITERAL_STARTSWITH(string, "ambient",             len)) { i = len;
436   } else if (STR_LITERAL_STARTSWITH(string, "diffuse",             len)) { i = len;
437   } else if (STR_LITERAL_STARTSWITH(string, "polygon",             len)) { i = len;
438   } else if (STR_LITERAL_STARTSWITH(string, "quadric",             len)) { i = len;
439   } else if (STR_LITERAL_STARTSWITH(string, "quartic",             len)) { i = len;
440   } else if (STR_LITERAL_STARTSWITH(string, "rainbow",             len)) { i = len;
441   } else if (STR_LITERAL_STARTSWITH(string, "sphere",              len)) { i = len;
442   } else if (STR_LITERAL_STARTSWITH(string, "spline",              len)) { i = len;
443   } else if (STR_LITERAL_STARTSWITH(string, "prism",               len)) { i = len;
444   } else if (STR_LITERAL_STARTSWITH(string, "camera",              len)) { i = len;
445   } else if (STR_LITERAL_STARTSWITH(string, "galley",              len)) { i = len;
446   } else if (STR_LITERAL_STARTSWITH(string, "cubic",               len)) { i = len;
447   } else if (STR_LITERAL_STARTSWITH(string, "phong",               len)) { i = len;
448   } else if (STR_LITERAL_STARTSWITH(string, "cone",                len)) { i = len;
449   } else if (STR_LITERAL_STARTSWITH(string, "blob",                len)) { i = len;
450   } else if (STR_LITERAL_STARTSWITH(string, "box",                 len)) { i = len;
451   } else if (STR_LITERAL_STARTSWITH(string, "disc",                len)) { i = len;
452   } else if (STR_LITERAL_STARTSWITH(string, "fog",                 len)) { i = len;
453   } else if (STR_LITERAL_STARTSWITH(string, "lathe",               len)) { i = len;
454   } else if (STR_LITERAL_STARTSWITH(string, "merge",               len)) { i = len;
455   } else if (STR_LITERAL_STARTSWITH(string, "mesh2",               len)) { i = len;
456   } else if (STR_LITERAL_STARTSWITH(string, "mesh",                len)) { i = len;
457   } else if (STR_LITERAL_STARTSWITH(string, "object",              len)) { i = len;
458   } else if (STR_LITERAL_STARTSWITH(string, "ovus",                len)) { i = len;
459   } else if (STR_LITERAL_STARTSWITH(string, "lemon",               len)) { i = len;
460   } else if (STR_LITERAL_STARTSWITH(string, "plane",               len)) { i = len;
461   } else if (STR_LITERAL_STARTSWITH(string, "poly",                len)) { i = len;
462   } else if (STR_LITERAL_STARTSWITH(string, "irid",                len)) { i = len;
463   } else if (STR_LITERAL_STARTSWITH(string, "sor",                 len)) { i = len;
464   } else if (STR_LITERAL_STARTSWITH(string, "text",                len)) { i = len;
465   } else if (STR_LITERAL_STARTSWITH(string, "torus",               len)) { i = len;
466   } else if (STR_LITERAL_STARTSWITH(string, "triangle",            len)) { i = len;
467   } else if (STR_LITERAL_STARTSWITH(string, "union",               len)) { i = len;
468   } else if (STR_LITERAL_STARTSWITH(string, "colour",              len)) { i = len;
469   } else if (STR_LITERAL_STARTSWITH(string, "color",               len)) { i = len;
470   } else if (STR_LITERAL_STARTSWITH(string, "media",               len)) { i = len;
471   /* Built-in Vectors */
472   } else if (STR_LITERAL_STARTSWITH(string, "t",                   len)) { i = len;
473   } else if (STR_LITERAL_STARTSWITH(string, "u",                   len)) { i = len;
474   } else if (STR_LITERAL_STARTSWITH(string, "v",                   len)) { i = len;
475   } else if (STR_LITERAL_STARTSWITH(string, "x",                   len)) { i = len;
476   } else if (STR_LITERAL_STARTSWITH(string, "y",                   len)) { i = len;
477   } else if (STR_LITERAL_STARTSWITH(string, "z",                   len)) { i = len;
478   } else {                                                                 i = 0;
479 }
480
481   /* clang-format off */
482
483   /* If next source char is an identifier (eg. 'i' in "definite") no match */
484   return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
485 }
486
487
488 /**
489  * Checks the specified source string for a POV modifiers. This
490  * name must start at the beginning of the source string and must be followed
491  * by a non-identifier (see #text_check_identifier(char)) or null character.
492  *
493  * If a special name is found, the length of the matching name is returned.
494  * Otherwise, -1 is returned.
495  *
496  * See:
497  * http://www.povray.org/documentation/view/3.7.0/212/
498  */
499 static int txtfmt_pov_find_specialvar(const char *string)
500 {
501   int i, len;
502   /* Modifiers */
503   if      (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) { i = len;
504   } else if (STR_LITERAL_STARTSWITH(string, "projected_through",  len)) { i = len;
505   } else if (STR_LITERAL_STARTSWITH(string, "double_illuminate",  len)) { i = len;
506   } else if (STR_LITERAL_STARTSWITH(string, "expand_thresholds",  len)) { i = len;
507   } else if (STR_LITERAL_STARTSWITH(string, "media_interaction",  len)) { i = len;
508   } else if (STR_LITERAL_STARTSWITH(string, "media_attenuation",  len)) { i = len;
509   } else if (STR_LITERAL_STARTSWITH(string, "low_error_factor",   len)) { i = len;
510   } else if (STR_LITERAL_STARTSWITH(string, "recursion_limit",    len)) { i = len;
511   } else if (STR_LITERAL_STARTSWITH(string, "interior_texture",   len)) { i = len;
512   } else if (STR_LITERAL_STARTSWITH(string, "max_trace_level",    len)) { i = len;
513   } else if (STR_LITERAL_STARTSWITH(string, "gray_threshold",     len)) { i = len;
514   } else if (STR_LITERAL_STARTSWITH(string, "pretrace_start",     len)) { i = len;
515   } else if (STR_LITERAL_STARTSWITH(string, "normal_indices",     len)) { i = len;
516   } else if (STR_LITERAL_STARTSWITH(string, "normal_vectors",     len)) { i = len;
517   } else if (STR_LITERAL_STARTSWITH(string, "vertex_vectors",     len)) { i = len;
518   } else if (STR_LITERAL_STARTSWITH(string, "noise_generator",    len)) { i = len;
519   } else if (STR_LITERAL_STARTSWITH(string, "irid_wavelength",    len)) { i = len;
520   } else if (STR_LITERAL_STARTSWITH(string, "number_of_waves",    len)) { i = len;
521   } else if (STR_LITERAL_STARTSWITH(string, "ambient_light",      len)) { i = len;
522   } else if (STR_LITERAL_STARTSWITH(string, "inside_vector",      len)) { i = len;
523   } else if (STR_LITERAL_STARTSWITH(string, "face_indices",       len)) { i = len;
524   } else if (STR_LITERAL_STARTSWITH(string, "texture_list",       len)) { i = len;
525   } else if (STR_LITERAL_STARTSWITH(string, "max_gradient",       len)) { i = len;
526   } else if (STR_LITERAL_STARTSWITH(string, "uv_indices",         len)) { i = len;
527   } else if (STR_LITERAL_STARTSWITH(string, "uv_vectors",         len)) { i = len;
528   } else if (STR_LITERAL_STARTSWITH(string, "fade_distance",      len)) { i = len;
529   } else if (STR_LITERAL_STARTSWITH(string, "global_lights",      len)) { i = len;
530   } else if (STR_LITERAL_STARTSWITH(string, "no_bump_scale",      len)) { i = len;
531   } else if (STR_LITERAL_STARTSWITH(string, "pretrace_end",       len)) { i = len;
532   } else if (STR_LITERAL_STARTSWITH(string, "no_radiosity",       len)) { i = len;
533   } else if (STR_LITERAL_STARTSWITH(string, "no_reflection",      len)) { i = len;
534   } else if (STR_LITERAL_STARTSWITH(string, "assumed_gamma",      len)) { i = len;
535   } else if (STR_LITERAL_STARTSWITH(string, "scallop_wave",       len)) { i = len;
536   } else if (STR_LITERAL_STARTSWITH(string, "triangle_wave",      len)) { i = len;
537   } else if (STR_LITERAL_STARTSWITH(string, "nearest_count",      len)) { i = len;
538   } else if (STR_LITERAL_STARTSWITH(string, "maximum_reuse",      len)) { i = len;
539   } else if (STR_LITERAL_STARTSWITH(string, "minimum_reuse",      len)) { i = len;
540   } else if (STR_LITERAL_STARTSWITH(string, "always_sample",      len)) { i = len;
541   } else if (STR_LITERAL_STARTSWITH(string, "translucency",       len)) { i = len;
542   } else if (STR_LITERAL_STARTSWITH(string, "eccentricity",       len)) { i = len;
543   } else if (STR_LITERAL_STARTSWITH(string, "contained_by",       len)) { i = len;
544   } else if (STR_LITERAL_STARTSWITH(string, "inside_point",       len)) { i = len;
545   } else if (STR_LITERAL_STARTSWITH(string, "adc_bailout",        len)) { i = len;
546   } else if (STR_LITERAL_STARTSWITH(string, "density_map",        len)) { i = len;
547   } else if (STR_LITERAL_STARTSWITH(string, "split_union",        len)) { i = len;
548   } else if (STR_LITERAL_STARTSWITH(string, "mm_per_unit",        len)) { i = len;
549   } else if (STR_LITERAL_STARTSWITH(string, "agate_turb",         len)) { i = len;
550   } else if (STR_LITERAL_STARTSWITH(string, "bounded_by",         len)) { i = len;
551   } else if (STR_LITERAL_STARTSWITH(string, "brick_size",         len)) { i = len;
552   } else if (STR_LITERAL_STARTSWITH(string, "hf_gray_16",         len)) { i = len;
553   } else if (STR_LITERAL_STARTSWITH(string, "dispersion",         len)) { i = len;
554   } else if (STR_LITERAL_STARTSWITH(string, "extinction",         len)) { i = len;
555   } else if (STR_LITERAL_STARTSWITH(string, "thickness",          len)) { i = len;
556   } else if (STR_LITERAL_STARTSWITH(string, "color_map",          len)) { i = len;
557   } else if (STR_LITERAL_STARTSWITH(string, "colour_map",         len)) { i = len;
558   } else if (STR_LITERAL_STARTSWITH(string, "cubic_wave",         len)) { i = len;
559   } else if (STR_LITERAL_STARTSWITH(string, "fade_colour",        len)) { i = len;
560   } else if (STR_LITERAL_STARTSWITH(string, "fade_power",         len)) { i = len;
561   } else if (STR_LITERAL_STARTSWITH(string, "fade_color",         len)) { i = len;
562   } else if (STR_LITERAL_STARTSWITH(string, "normal_map",         len)) { i = len;
563   } else if (STR_LITERAL_STARTSWITH(string, "pigment_map",        len)) { i = len;
564   } else if (STR_LITERAL_STARTSWITH(string, "quick_color",        len)) { i = len;
565   } else if (STR_LITERAL_STARTSWITH(string, "quick_colour",       len)) { i = len;
566   } else if (STR_LITERAL_STARTSWITH(string, "material_map",       len)) { i = len;
567   } else if (STR_LITERAL_STARTSWITH(string, "pass_through",       len)) { i = len;
568   } else if (STR_LITERAL_STARTSWITH(string, "interpolate",        len)) { i = len;
569   } else if (STR_LITERAL_STARTSWITH(string, "texture_map",        len)) { i = len;
570   } else if (STR_LITERAL_STARTSWITH(string, "error_bound",        len)) { i = len;
571   } else if (STR_LITERAL_STARTSWITH(string, "brightness",         len)) { i = len;
572   } else if (STR_LITERAL_STARTSWITH(string, "use_color",          len)) { i = len;
573   } else if (STR_LITERAL_STARTSWITH(string, "use_alpha",          len)) { i = len;
574   } else if (STR_LITERAL_STARTSWITH(string, "use_colour",         len)) { i = len;
575   } else if (STR_LITERAL_STARTSWITH(string, "use_index",          len)) { i = len;
576   } else if (STR_LITERAL_STARTSWITH(string, "uv_mapping",         len)) { i = len;
577   } else if (STR_LITERAL_STARTSWITH(string, "importance",         len)) { i = len;
578   } else if (STR_LITERAL_STARTSWITH(string, "max_sample",         len)) { i = len;
579   } else if (STR_LITERAL_STARTSWITH(string, "intervals",          len)) { i = len;
580   } else if (STR_LITERAL_STARTSWITH(string, "sine_wave",          len)) { i = len;
581   } else if (STR_LITERAL_STARTSWITH(string, "slope_map",          len)) { i = len;
582   } else if (STR_LITERAL_STARTSWITH(string, "poly_wave",          len)) { i = len;
583   } else if (STR_LITERAL_STARTSWITH(string, "no_shadow",          len)) { i = len;
584   } else if (STR_LITERAL_STARTSWITH(string, "ramp_wave",          len)) { i = len;
585   } else if (STR_LITERAL_STARTSWITH(string, "precision",          len)) { i = len;
586   } else if (STR_LITERAL_STARTSWITH(string, "original",           len)) { i = len;
587   } else if (STR_LITERAL_STARTSWITH(string, "accuracy",           len)) { i = len;
588   } else if (STR_LITERAL_STARTSWITH(string, "map_type",           len)) { i = len;
589   } else if (STR_LITERAL_STARTSWITH(string, "no_image",           len)) { i = len;
590   } else if (STR_LITERAL_STARTSWITH(string, "distance",           len)) { i = len;
591   } else if (STR_LITERAL_STARTSWITH(string, "autostop",           len)) { i = len;
592   } else if (STR_LITERAL_STARTSWITH(string, "caustics",           len)) { i = len;
593   } else if (STR_LITERAL_STARTSWITH(string, "octaves",            len)) { i = len;
594   } else if (STR_LITERAL_STARTSWITH(string, "aa_level",           len)) { i = len;
595   } else if (STR_LITERAL_STARTSWITH(string, "frequency",          len)) { i = len;
596   } else if (STR_LITERAL_STARTSWITH(string, "fog_offset",         len)) { i = len;
597   } else if (STR_LITERAL_STARTSWITH(string, "modulation",         len)) { i = len;
598   } else if (STR_LITERAL_STARTSWITH(string, "outbound",           len)) { i = len;
599   } else if (STR_LITERAL_STARTSWITH(string, "no_cache",           len)) { i = len;
600   } else if (STR_LITERAL_STARTSWITH(string, "pigment",            len)) { i = len;
601   } else if (STR_LITERAL_STARTSWITH(string, "charset",            len)) { i = len;
602   } else if (STR_LITERAL_STARTSWITH(string, "inbound",            len)) { i = len;
603   } else if (STR_LITERAL_STARTSWITH(string, "outside",            len)) { i = len;
604   } else if (STR_LITERAL_STARTSWITH(string, "inner",              len)) { i = len;
605   } else if (STR_LITERAL_STARTSWITH(string, "turbulence",         len)) { i = len;
606   } else if (STR_LITERAL_STARTSWITH(string, "threshold",          len)) { i = len;
607   } else if (STR_LITERAL_STARTSWITH(string, "accuracy",           len)) { i = len;
608   } else if (STR_LITERAL_STARTSWITH(string, "polarity",           len)) { i = len;
609   } else if (STR_LITERAL_STARTSWITH(string, "bump_size",          len)) { i = len;
610   } else if (STR_LITERAL_STARTSWITH(string, "circular",           len)) { i = len;
611   } else if (STR_LITERAL_STARTSWITH(string, "control0",           len)) { i = len;
612   } else if (STR_LITERAL_STARTSWITH(string, "control1",           len)) { i = len;
613   } else if (STR_LITERAL_STARTSWITH(string, "maximal",            len)) { i = len;
614   } else if (STR_LITERAL_STARTSWITH(string, "minimal",            len)) { i = len;
615   } else if (STR_LITERAL_STARTSWITH(string, "fog_type",           len)) { i = len;
616   } else if (STR_LITERAL_STARTSWITH(string, "fog_alt",            len)) { i = len;
617   } else if (STR_LITERAL_STARTSWITH(string, "samples",            len)) { i = len;
618   } else if (STR_LITERAL_STARTSWITH(string, "origin",             len)) { i = len;
619   } else if (STR_LITERAL_STARTSWITH(string, "amount",             len)) { i = len;
620   } else if (STR_LITERAL_STARTSWITH(string, "adaptive",           len)) { i = len;
621   } else if (STR_LITERAL_STARTSWITH(string, "exponent",           len)) { i = len;
622   } else if (STR_LITERAL_STARTSWITH(string, "strength",           len)) { i = len;
623   } else if (STR_LITERAL_STARTSWITH(string, "density",            len)) { i = len;
624   } else if (STR_LITERAL_STARTSWITH(string, "fresnel",            len)) { i = len;
625   } else if (STR_LITERAL_STARTSWITH(string, "albinos",            len)) { i = len;
626   } else if (STR_LITERAL_STARTSWITH(string, "finish",             len)) { i = len;
627   } else if (STR_LITERAL_STARTSWITH(string, "method",             len)) { i = len;
628   } else if (STR_LITERAL_STARTSWITH(string, "omega",              len)) { i = len;
629   } else if (STR_LITERAL_STARTSWITH(string, "fixed",              len)) { i = len;
630   } else if (STR_LITERAL_STARTSWITH(string, "spacing",            len)) { i = len;
631   } else if (STR_LITERAL_STARTSWITH(string, "u_steps",            len)) { i = len;
632   } else if (STR_LITERAL_STARTSWITH(string, "v_steps",            len)) { i = len;
633   } else if (STR_LITERAL_STARTSWITH(string, "offset",             len)) { i = len;
634   } else if (STR_LITERAL_STARTSWITH(string, "hollow",             len)) { i = len;
635   } else if (STR_LITERAL_STARTSWITH(string, "gather",             len)) { i = len;
636   } else if (STR_LITERAL_STARTSWITH(string, "lambda",             len)) { i = len;
637   } else if (STR_LITERAL_STARTSWITH(string, "mortar",             len)) { i = len;
638   } else if (STR_LITERAL_STARTSWITH(string, "cubic",              len)) { i = len;
639   } else if (STR_LITERAL_STARTSWITH(string, "count",              len)) { i = len;
640   } else if (STR_LITERAL_STARTSWITH(string, "once",               len)) { i = len;
641   } else if (STR_LITERAL_STARTSWITH(string, "orient",             len)) { i = len;
642   } else if (STR_LITERAL_STARTSWITH(string, "normal",             len)) { i = len;
643   } else if (STR_LITERAL_STARTSWITH(string, "phase",              len)) { i = len;
644   } else if (STR_LITERAL_STARTSWITH(string, "ratio",              len)) { i = len;
645   } else if (STR_LITERAL_STARTSWITH(string, "open",               len)) { i = len;
646   } else if (STR_LITERAL_STARTSWITH(string, "ior",                len)) { i = len;
647   /* Light Types and options*/
648   } else if (STR_LITERAL_STARTSWITH(string, "area_light",         len)) { i = len;
649   } else if (STR_LITERAL_STARTSWITH(string, "looks_like",         len)) { i = len;
650   } else if (STR_LITERAL_STARTSWITH(string, "fade_power",         len)) { i = len;
651   } else if (STR_LITERAL_STARTSWITH(string, "tightness",          len)) { i = len;
652   } else if (STR_LITERAL_STARTSWITH(string, "spotlight",          len)) { i = len;
653   } else if (STR_LITERAL_STARTSWITH(string, "parallel",           len)) { i = len;
654   } else if (STR_LITERAL_STARTSWITH(string, "point_at",           len)) { i = len;
655   } else if (STR_LITERAL_STARTSWITH(string, "falloff",            len)) { i = len;
656   } else if (STR_LITERAL_STARTSWITH(string, "radius",             len)) { i = len;
657   /* Camera Types and options*/
658   } else if (STR_LITERAL_STARTSWITH(string, "omni_directional_stereo",  len)) { i = len;
659   } else if (STR_LITERAL_STARTSWITH(string, "lambert_cylindrical",      len)) { i = len;
660   } else if (STR_LITERAL_STARTSWITH(string, "miller_cylindrical",       len)) { i = len;
661   } else if (STR_LITERAL_STARTSWITH(string, "lambert_azimuthal",        len)) { i = len;
662   } else if (STR_LITERAL_STARTSWITH(string, "ultra_wide_angle",         len)) { i = len;
663   } else if (STR_LITERAL_STARTSWITH(string, "camera_direction",         len)) { i = len;
664   } else if (STR_LITERAL_STARTSWITH(string, "camera_location ",         len)) { i = len;
665   } else if (STR_LITERAL_STARTSWITH(string, "van_der_grinten",          len)) { i = len;
666   } else if (STR_LITERAL_STARTSWITH(string, "aitoff_hammer",            len)) { i = len;
667   } else if (STR_LITERAL_STARTSWITH(string, "smyth_craster",            len)) { i = len;
668   } else if (STR_LITERAL_STARTSWITH(string, "orthographic",             len)) { i = len;
669   } else if (STR_LITERAL_STARTSWITH(string, "camera_right",             len)) { i = len;
670   } else if (STR_LITERAL_STARTSWITH(string, "blur_samples",             len)) { i = len;
671   } else if (STR_LITERAL_STARTSWITH(string, "plate_carree",             len)) { i = len;
672   } else if (STR_LITERAL_STARTSWITH(string, "camera_type",              len)) { i = len;
673   } else if (STR_LITERAL_STARTSWITH(string, "perspective",              len)) { i = len;
674   } else if (STR_LITERAL_STARTSWITH(string, "mesh_camera",              len)) { i = len;
675   } else if (STR_LITERAL_STARTSWITH(string, "focal_point",              len)) { i = len;
676   } else if (STR_LITERAL_STARTSWITH(string, "balthasart",               len)) { i = len;
677   } else if (STR_LITERAL_STARTSWITH(string, "confidence",               len)) { i = len;
678   } else if (STR_LITERAL_STARTSWITH(string, "parallaxe",                len)) { i = len;
679   } else if (STR_LITERAL_STARTSWITH(string, "hobo_dyer",                len)) { i = len;
680   } else if (STR_LITERAL_STARTSWITH(string, "camera_up",                len)) { i = len;
681   } else if (STR_LITERAL_STARTSWITH(string, "panoramic",                len)) { i = len;
682   } else if (STR_LITERAL_STARTSWITH(string, "eckert_vi",                len)) { i = len;
683   } else if (STR_LITERAL_STARTSWITH(string, "eckert_iv",                len)) { i = len;
684   } else if (STR_LITERAL_STARTSWITH(string, "mollweide",                len)) { i = len;
685   } else if (STR_LITERAL_STARTSWITH(string, "aperture",                 len)) { i = len;
686   } else if (STR_LITERAL_STARTSWITH(string, "behrmann",                 len)) { i = len;
687   } else if (STR_LITERAL_STARTSWITH(string, "variance",                 len)) { i = len;
688   } else if (STR_LITERAL_STARTSWITH(string, "stereo",                   len)) { i = len;
689   } else if (STR_LITERAL_STARTSWITH(string, "icosa",                    len)) { i = len;
690   } else if (STR_LITERAL_STARTSWITH(string, "tetra",                    len)) { i = len;
691   } else if (STR_LITERAL_STARTSWITH(string, "octa",                     len)) { i = len;
692   } else if (STR_LITERAL_STARTSWITH(string, "mercator",                 len)) { i = len;
693   } else if (STR_LITERAL_STARTSWITH(string, "omnimax",                  len)) { i = len;
694   } else if (STR_LITERAL_STARTSWITH(string, "fisheye",                  len)) { i = len;
695   } else if (STR_LITERAL_STARTSWITH(string, "edwards",                  len)) { i = len;
696   } else if (STR_LITERAL_STARTSWITH(string, "peters",                   len)) { i = len;
697   } else if (STR_LITERAL_STARTSWITH(string, "gall",                     len)) { i = len;
698   } else {                                                                i = 0;
699 }
700
701   /* If next source char is an identifier (eg. 'i' in "definite") no match */
702   return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
703 }
704
705 static int txtfmt_pov_find_bool(const char *string)
706 {
707   int i, len;
708
709   /* Keep aligned args for readability. */
710   /* clang-format off */
711
712   /* Built-in Constants */
713   if      (STR_LITERAL_STARTSWITH(string, "unofficial",          len)) { i = len;
714   } else if (STR_LITERAL_STARTSWITH(string, "false",               len)) { i = len;
715   } else if (STR_LITERAL_STARTSWITH(string, "no",                  len)) { i = len;
716   } else if (STR_LITERAL_STARTSWITH(string, "off",                 len)) { i = len;
717   } else if (STR_LITERAL_STARTSWITH(string, "true",                len)) { i = len;
718   } else if (STR_LITERAL_STARTSWITH(string, "yes",                 len)) { i = len;
719   } else if (STR_LITERAL_STARTSWITH(string, "on",                  len)) { i = len;
720   } else if (STR_LITERAL_STARTSWITH(string, "pi",                  len)) { i = len;
721   } else if (STR_LITERAL_STARTSWITH(string, "tau",                 len)) { i = len;
722   /* Encodings */
723   } else if (STR_LITERAL_STARTSWITH(string, "sint16be",            len)) { i = len;
724   } else if (STR_LITERAL_STARTSWITH(string, "sint16le",            len)) { i = len;
725   } else if (STR_LITERAL_STARTSWITH(string, "sint32be",            len)) { i = len;
726   } else if (STR_LITERAL_STARTSWITH(string, "sint32le",            len)) { i = len;
727   } else if (STR_LITERAL_STARTSWITH(string, "uint16be",            len)) { i = len;
728   } else if (STR_LITERAL_STARTSWITH(string, "uint16le",            len)) { i = len;
729   } else if (STR_LITERAL_STARTSWITH(string, "bt2020",              len)) { i = len;
730   } else if (STR_LITERAL_STARTSWITH(string, "bt709",               len)) { i = len;
731   } else if (STR_LITERAL_STARTSWITH(string, "sint8",               len)) { i = len;
732   } else if (STR_LITERAL_STARTSWITH(string, "uint8",               len)) { i = len;
733   } else if (STR_LITERAL_STARTSWITH(string, "ascii",               len)) { i = len;
734   } else if (STR_LITERAL_STARTSWITH(string, "utf8",                len)) { i = len;
735   /* Filetypes */
736   } else if (STR_LITERAL_STARTSWITH(string, "tiff",                len)) { i = len;
737   } else if (STR_LITERAL_STARTSWITH(string, "df3",                 len)) { i = len;
738   } else if (STR_LITERAL_STARTSWITH(string, "exr",                 len)) { i = len;
739   } else if (STR_LITERAL_STARTSWITH(string, "gif",                 len)) { i = len;
740   } else if (STR_LITERAL_STARTSWITH(string, "hdr",                 len)) { i = len;
741   } else if (STR_LITERAL_STARTSWITH(string, "iff",                 len)) { i = len;
742   } else if (STR_LITERAL_STARTSWITH(string, "jpeg",                len)) { i = len;
743   } else if (STR_LITERAL_STARTSWITH(string, "pgm",                 len)) { i = len;
744   } else if (STR_LITERAL_STARTSWITH(string, "png",                 len)) { i = len;
745   } else if (STR_LITERAL_STARTSWITH(string, "ppm",                 len)) { i = len;
746   } else if (STR_LITERAL_STARTSWITH(string, "sys",                 len)) { i = len;
747   } else if (STR_LITERAL_STARTSWITH(string, "tga",                 len)) { i = len;
748   } else if (STR_LITERAL_STARTSWITH(string, "ttf",                 len)) { i = len;
749   } else {                                                                 i = 0;
750 }
751
752   /* clang-format on */
753
754   /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
755   return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
756 }
757
758 static char txtfmt_pov_format_identifier(const char *str)
759 {
760   char fmt;
761
762   /* Keep aligned args for readability. */
763   /* clang-format off */
764
765   if      ((txtfmt_pov_find_specialvar(str))        != -1) { fmt = FMT_TYPE_SPECIAL;
766   } else if ((txtfmt_pov_find_keyword(str))           != -1) { fmt = FMT_TYPE_KEYWORD;
767   } else if ((txtfmt_pov_find_reserved_keywords(str)) != -1) { fmt = FMT_TYPE_RESERVED;
768   } else if ((txtfmt_pov_find_reserved_builtins(str)) != -1) { fmt = FMT_TYPE_DIRECTIVE;
769   } else {                                                     fmt = FMT_TYPE_DEFAULT;
770 }
771
772   /* clang-format on */
773
774   return fmt;
775 }
776
777 static void txtfmt_pov_format_line(SpaceText *st, TextLine *line, const bool do_next)
778 {
779   FlattenString fs;
780   const char *str;
781   char *fmt;
782   char cont_orig, cont, find, prev = ' ';
783   int len, i;
784
785   /* Get continuation from previous line */
786   if (line->prev && line->prev->format != NULL) {
787     fmt = line->prev->format;
788     cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
789     BLI_assert((FMT_CONT_ALL & cont) == cont);
790   }
791   else {
792     cont = FMT_CONT_NOP;
793   }
794
795   /* Get original continuation from this line */
796   if (line->format != NULL) {
797     fmt = line->format;
798     cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
799     BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
800   }
801   else {
802     cont_orig = 0xFF;
803   }
804
805   len = flatten_string(st, &fs, line->line);
806   str = fs.buf;
807   if (!text_check_format_len(line, len)) {
808     flatten_string_free(&fs);
809     return;
810   }
811   fmt = line->format;
812
813   while (*str) {
814     /* Handle escape sequences by skipping both \ and next char */
815     if (*str == '\\') {
816       *fmt = prev;
817       fmt++;
818       str++;
819       if (*str == '\0') {
820         break;
821       }
822       *fmt = prev;
823       fmt++;
824       str += BLI_str_utf8_size_safe(str);
825       continue;
826     }
827     /* Handle continuations */
828     else if (cont) {
829       /* C-Style comments */
830       if (cont & FMT_CONT_COMMENT_C) {
831         if (*str == '*' && *(str + 1) == '/') {
832           *fmt = FMT_TYPE_COMMENT;
833           fmt++;
834           str++;
835           *fmt = FMT_TYPE_COMMENT;
836           cont = FMT_CONT_NOP;
837         }
838         else {
839           *fmt = FMT_TYPE_COMMENT;
840         }
841         /* Handle other comments */
842       }
843       else {
844         find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
845         if (*str == find) {
846           cont = 0;
847         }
848         *fmt = FMT_TYPE_STRING;
849       }
850
851       str += BLI_str_utf8_size_safe(str) - 1;
852     }
853     /* Not in a string... */
854     else {
855       /* C-Style (multi-line) comments */
856       if (*str == '/' && *(str + 1) == '*') {
857         cont = FMT_CONT_COMMENT_C;
858         *fmt = FMT_TYPE_COMMENT;
859         fmt++;
860         str++;
861         *fmt = FMT_TYPE_COMMENT;
862       }
863       /* Single line comment */
864       else if (*str == '/' && *(str + 1) == '/') {
865         text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
866       }
867       else if (*str == '"' || *str == '\'') {
868         /* Strings */
869         find = *str;
870         cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
871         *fmt = FMT_TYPE_STRING;
872       }
873       /* Whitespace (all ws. has been converted to spaces) */
874       else if (*str == ' ') {
875         *fmt = FMT_TYPE_WHITESPACE;
876       }
877       /* Numbers (digits not part of an identifier and periods followed by digits) */
878       else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
879                (*str == '.' && text_check_digit(*(str + 1)))) {
880         *fmt = FMT_TYPE_NUMERAL;
881       }
882       /* Booleans */
883       else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_pov_find_bool(str)) != -1) {
884         if (i > 0) {
885           text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
886         }
887         else {
888           str += BLI_str_utf8_size_safe(str) - 1;
889           *fmt = FMT_TYPE_DEFAULT;
890         }
891       }
892       /* Punctuation */
893       else if (text_check_delim(*str)) {
894         *fmt = FMT_TYPE_SYMBOL;
895       }
896       /* Identifiers and other text (no previous ws. or delims. so text continues) */
897       else if (prev == FMT_TYPE_DEFAULT) {
898         str += BLI_str_utf8_size_safe(str) - 1;
899         *fmt = FMT_TYPE_DEFAULT;
900       }
901       /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
902       else {
903         /* Keep aligned args for readability. */
904         /* clang-format off */
905
906         /* Special vars(v) or built-in keywords(b) */
907         /* keep in sync with 'txtfmt_pov_format_identifier()' */
908         if      ((i = txtfmt_pov_find_specialvar(str))        != -1) { prev = FMT_TYPE_SPECIAL;
909         } else if ((i = txtfmt_pov_find_keyword(str))           != -1) { prev = FMT_TYPE_KEYWORD;
910         } else if ((i = txtfmt_pov_find_reserved_keywords(str)) != -1) { prev = FMT_TYPE_RESERVED;
911         } else if ((i = txtfmt_pov_find_reserved_builtins(str)) != -1) { prev = FMT_TYPE_DIRECTIVE;
912 }
913
914         /* clang-format on */
915
916         if (i > 0) {
917           text_format_fill_ascii(&str, &fmt, prev, i);
918         }
919         else {
920           str += BLI_str_utf8_size_safe(str) - 1;
921           *fmt = FMT_TYPE_DEFAULT;
922         }
923       }
924     }
925     prev = *fmt;
926     fmt++;
927     str++;
928   }
929
930   /* Terminate and add continuation char */
931   *fmt = '\0';
932   fmt++;
933   *fmt = cont;
934
935   /* If continuation has changed and we're allowed, process the next line */
936   if (cont != cont_orig && do_next && line->next) {
937     txtfmt_pov_format_line(st, line->next, do_next);
938   }
939
940   flatten_string_free(&fs);
941 }
942
943 void ED_text_format_register_pov(void)
944 {
945   static TextFormatType tft = {NULL};
946   static const char *ext[] = {"pov", "inc", "mcr", "mac", NULL};
947
948   tft.format_identifier = txtfmt_pov_format_identifier;
949   tft.format_line = txtfmt_pov_format_line;
950   tft.ext = ext;
951
952   ED_text_format_register(&tft);
953 }