1 /****************************************************************************
2 * processrenderoptions.cpp
3 *
4 * This module contains the C++ interface for render option processing.
5 *
6 * from Persistence of Vision(tm) Ray Tracer version 3.6.
7 * Copyright 1991-2003 Persistence of Vision Team
8 * Copyright 2003-2004 Persistence of Vision Raytracer Pty. Ltd.
9 *---------------------------------------------------------------------------
10 * NOTICE: This source code file is provided so that users may experiment
11 * with enhancements to POV-Ray and to port the software to platforms other
12 * than those supported by the POV-Ray developers. There are strict rules
13 * regarding how you are permitted to use this file. These rules are contained
14 * in the distribution and derivative versions licenses which should have been
15 * provided with this file.
16 *
17 * These licences may be found online, linked from the end-user license
18 * agreement that is located at http://www.povray.org/povlegal.html
19 *---------------------------------------------------------------------------
20 * This program is based on the popular DKB raytracer version 2.12.
21 * DKBTrace was originally written by David K. Buck.
22 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
23 *---------------------------------------------------------------------------
24 *
25 *===========================================================================
26 * This file is part of MegaPOV, a modified and unofficial version of POV-Ray
27 * For more information on MegaPOV visit our website:
28 * http://megapov.inetart.net/
29 *===========================================================================
30 *
31 * $RCSfile: processrenderoptions.cpp,v $
32 * $Revision: 1.11 $
33 * $Author: chris $
34 *
35 *****************************************************************************/
36
37 #include "configfrontend.h"
38
39 #include "processrenderoptions.h"
40 #include "fileinputoutput.h"
41 #include "stringutilities.h"
42 #include "textstream.h"
43 #include "povms.h"
44 #include "povmsgid.h"
45 #include "pov_err.h"
46
47 BEGIN_POV_FRONTEND_NAMESPACE
48
49 USING_POV_BASE_NAMESPACE
50
51 /*****************************************************************************
52 * Local preprocessor defines
53 ******************************************************************************/
54
55 #define kUseSpecialHandler kPOVMSType_WildCard
56 #define kNoParameter kPOVMSType_Null
57
58 /*****************************************************************************
59 * Local variables
60 ******************************************************************************/
61
62 /* Supported output file types */
63 #ifdef HDR_PATCH /* Christoph Hormann March 2003 */
64 const char *Output_File_Types = "sStTcCpPnNdDrRhH";
65 #else
66 const char *Output_File_Types = "sStTcCpPnNdDrR";
67 #endif
68
69 /*
70 Keyword table for the INI-file parser.
71 The parser converts the INI-file options into a POVMS object using
72 the specifications provided in this table. The first element is the
73 INI-file keyword, the second element is the POVMS object attribute
74 key, the third is the attribute type.
75 */
76 struct ProcessOptions::INI_Parser_Table RenderOptions_INI_Table[] =
77 {
78 { "All_Console", kPOVAttrib_AllConsole, kPOVMSType_Bool },
79 { "All_File", kPOVAttrib_AllFile, kPOVObjectClass_File },
80 { "Antialias_Depth", kPOVAttrib_AntialiasDepth, kPOVMSType_Int },
81 { "Antialias", kPOVAttrib_Antialias, kPOVMSType_Bool },
82 { "Antialias_Threshold", kPOVAttrib_AntialiasThreshold, kPOVMSType_Float },
83
84 { "Bits_Per_Color", kPOVAttrib_BitsPerColor, kPOVMSType_Int },
85 { "Bits_Per_Colour", kPOVAttrib_BitsPerColor, kPOVMSType_Int },
86 { "Bounding", kPOVAttrib_Bounding, kPOVMSType_Bool },
87 { "Bounding_Threshold", kPOVAttrib_BoundingThreshold, kPOVMSType_Int },
88 { "Buffer_Output", '****', kPOVMSType_Bool },
89 { "Buffer_Size", '****', kPOVMSType_Int },
90
91 { "Clock", kPOVAttrib_Clock, kPOVMSType_Float },
92 // { "Compression", kPOVAttrib_Compression, kPOVMSType_Int },
93 { "Continue_Trace", kPOVAttrib_ContinueTrace, kPOVMSType_Bool },
94 { "Create_Histogram", kPOVAttrib_CreateHistogram, kPOVMSType_Bool },
95 { "Create_Ini", kPOVAttrib_CreateIni, kPOVObjectClass_File },
96 { "Cyclic_Animation", kPOVAttrib_CyclicAnimation, kPOVMSType_Bool },
97
98 { "Debug_Console", kPOVAttrib_DebugConsole, kPOVMSType_Bool },
99 { "Debug_File", kPOVAttrib_DebugFile, kPOVObjectClass_File },
100 { "Declare", kPOVAttrib_Declare, kUseSpecialHandler },
101 { "Display", kPOVAttrib_Display, kPOVMSType_Bool },
102 { "Display_Gamma", kPOVAttrib_DisplayGamma, kPOVMSType_Float },
103 { "Draw_Vistas", kPOVAttrib_DrawVistas, kPOVMSType_Bool },
104
105 { "End_Column", kPOVAttrib_Right, kPOVMSType_Float },
106 { "End_Row", kPOVAttrib_Bottom, kPOVMSType_Float },
107
108 { "Fatal_Console", kPOVAttrib_FatalConsole, kPOVMSType_Bool },
109 { "Fatal_Error_Command", kPOVAttrib_FatalErrorCommand, kUseSpecialHandler },
110 { "Fatal_Error_Return", kPOVAttrib_FatalErrorCommand, kUseSpecialHandler },
111 { "Fatal_File", kPOVAttrib_FatalFile, kPOVObjectClass_File },
112 { "Field_Render", kPOVAttrib_FieldRender, kPOVMSType_Bool },
113 { "Final_Clock", kPOVAttrib_FinalClock, kPOVMSType_Float },
114 { "Final_Frame", kPOVAttrib_FinalFrame, kPOVMSType_Int },
115 #ifdef FRAME_STEP_PATCH
116 { "Frame_Step", kPOVAttrib_FrameStep, kPOVMSType_Int },
117 #endif
118 { "Height", kPOVAttrib_Height, kPOVMSType_Int },
119 { "Histogram_Name", kPOVAttrib_HistogramFile, kPOVObjectClass_File },
120 { "Histogram_Grid_Size", kPOVAttrib_HistogramGridSizeX, kUseSpecialHandler },
121 { "Histogram_Type", kPOVAttrib_HistogramFileType, kUseSpecialHandler },
122
123 { "Initial_Clock", kPOVAttrib_InitialClock, kPOVMSType_Float },
124 { "Initial_Frame", kPOVAttrib_InitialFrame, kPOVMSType_Int },
125 { "Input_File_Name", kPOVAttrib_InputFile, kPOVObjectClass_File },
126 { "Include_Header", kPOVAttrib_IncludeHeader, kPOVObjectClass_File },
127 { "Include_Ini", kPOVAttrib_IncludeIni, kUseSpecialHandler },
128
129 { "Jitter_Amount", kPOVAttrib_JitterAmount, kPOVMSType_Float },
130 { "Jitter", kPOVAttrib_Jitter, kPOVMSType_Bool },
131
132 { "Library_Path", kPOVAttrib_LibraryPath, kUseSpecialHandler },
133 { "Light_Buffer", kPOVAttrib_LightBuffer, kPOVMSType_Bool },
134
135 { "Odd_Field", kPOVAttrib_OddField, kPOVMSType_Bool },
136 { "Output_Alpha", kPOVAttrib_OutputAlpha, kPOVMSType_Bool },
137 { "Output_File_Name", kPOVAttrib_OutputFile, kPOVObjectClass_File },
138 { "Output_File_Type", kPOVAttrib_OutputFileType, kUseSpecialHandler },
139 { "Output_To_File", kPOVAttrib_OutputToFile, kPOVMSType_Bool },
140
141 { "Palette", kPOVAttrib_Palette, kUseSpecialHandler },
142 { "Pause_When_Done", kPOVAttrib_PauseWhenDone, kPOVMSType_Bool },
143 { "Post_Frame_Command", kPOVAttrib_PostFrameCommand, kUseSpecialHandler },
144 { "Post_Frame_Return", kPOVAttrib_PostFrameCommand, kUseSpecialHandler },
145 { "Post_Scene_Command", kPOVAttrib_PostSceneCommand, kUseSpecialHandler },
146 { "Post_Scene_Return", kPOVAttrib_PostSceneCommand, kUseSpecialHandler },
147 { "Preview_End_Size", kPOVAttrib_PreviewEndSize, kPOVMSType_Int },
148 { "Preview_Start_Size", kPOVAttrib_PreviewStartSize, kPOVMSType_Int },
149 { "Pre_Frame_Command", kPOVAttrib_PreFrameCommand, kUseSpecialHandler },
150 { "Pre_Frame_Return", kPOVAttrib_PreFrameCommand, kUseSpecialHandler },
151 { "Pre_Scene_command", kPOVAttrib_PreSceneCommand, kUseSpecialHandler },
152 { "Pre_Scene_Return", kPOVAttrib_PreSceneCommand, kUseSpecialHandler },
153
154 { "Quality", kPOVAttrib_Quality, kPOVMSType_Int },
155
156 { "Radiosity", kPOVAttrib_Radiosity, kPOVMSType_Bool },
157 { "Remove_Bounds", kPOVAttrib_RemoveBounds, kPOVMSType_Bool },
158 { "Render_Console", kPOVAttrib_RenderConsole, kPOVMSType_Bool },
159 { "Render_File", kPOVAttrib_RenderFile, kPOVObjectClass_File },
160
161 { "Sampling_Method", kPOVAttrib_SamplingMethod, kPOVMSType_Int },
162 { "Split_Unions", kPOVAttrib_SplitUnions, kPOVMSType_Bool },
163 { "Start_Column", kPOVAttrib_Left, kPOVMSType_Float },
164 { "Start_Row", kPOVAttrib_Top, kPOVMSType_Float },
165 { "Statistic_Console", kPOVAttrib_StatisticsConsole, kPOVMSType_Bool },
166 { "Statistic_File", kPOVAttrib_StatisticsFile, kPOVObjectClass_File },
167 { "Subset_End_Frame", kPOVAttrib_SubsetEndFrame, kPOVMSType_Int },
168 { "Subset_Start_Frame", kPOVAttrib_SubsetStartFrame, kPOVMSType_Int },
169
170 { "Test_Abort_Count", kPOVAttrib_TestAbortCount, kPOVMSType_Int },
171 { "Test_Abort", kPOVAttrib_TestAbort, kPOVMSType_Bool },
172
173 { "User_Abort_Command", kPOVAttrib_UserAbortCommand, kUseSpecialHandler },
174 { "User_Abort_Return", kPOVAttrib_UserAbortCommand, kUseSpecialHandler },
175
176 { "Verbose", kPOVAttrib_Verbose, kPOVMSType_Bool },
177 { "Version", kPOVAttrib_Version, kPOVMSType_Float },
178 { "Video_Mode", kPOVAttrib_VideoMode, kUseSpecialHandler },
179 { "Vista_Buffer", kPOVAttrib_VistaBuffer, kPOVMSType_Bool },
180
181 { "Warning_Console", kPOVAttrib_WarningConsole, kPOVMSType_Bool },
182 { "Warning_File", kPOVAttrib_WarningFile, kPOVObjectClass_File },
183 { "Warning_Level", kPOVAttrib_WarningLevel, kPOVMSType_Int },
184 { "Width", kPOVAttrib_Width, kPOVMSType_Int },
185
186 { NULL, 0, 0 }
187 };
188
189 /*
190 Keyword table for the command line parser.
191 The parser converts the command line options into a POVMS object using
192 the specifications provided in this table. The first element is the
193 command keyword, the second element is the POVMS object attribute key
194 of the parameter, the third is the attribute type and the last specifies
195 is the +/- switch is used as boolean parameter if an attribute key is
196 provided.
197 */
198 struct ProcessOptions::Cmd_Parser_Table RenderOptions_Cmd_Table[] =
199 {
200 { "A0", kPOVAttrib_AntialiasThreshold, kPOVMSType_Float, kPOVAttrib_Antialias },
201 { "AM", kPOVAttrib_SamplingMethod, kPOVMSType_Int, kNoParameter },
202 { "A", kNoParameter, kNoParameter, kPOVAttrib_Antialias },
203
204 { "B", '****', kPOVMSType_Int, '****' },
205 { "B", kNoParameter, kNoParameter, '****' },
206
207 { "C", kNoParameter, kNoParameter, kPOVAttrib_ContinueTrace },
208
209 { "D", kPOVAttrib_Display, kUseSpecialHandler, kPOVAttrib_Display },
210 { "D", kNoParameter, kNoParameter, kPOVAttrib_Display },
211
212 { "EC", kPOVAttrib_Right, kPOVMSType_Float, kNoParameter },
213 { "EF0", kPOVAttrib_SubsetEndFrame, kPOVMSType_Float, kNoParameter },
214 { "EF", kPOVAttrib_SubsetEndFrame, kPOVMSType_Int, kNoParameter },
215 { "EP", kPOVAttrib_PreviewEndSize, kPOVMSType_Int, kNoParameter },
216 { "ER", kPOVAttrib_Bottom, kPOVMSType_Float, kNoParameter },
217
218 { "F", kPOVAttrib_OutputFileType, kUseSpecialHandler, kPOVAttrib_OutputToFile },
219 { "F", kNoParameter, kNoParameter, kPOVAttrib_OutputToFile },
220
221 { "GA", kPOVAttrib_AllFile, kPOVObjectClass_File, kPOVAttrib_AllConsole },
222 { "GA", kNoParameter, kNoParameter, kPOVAttrib_AllConsole },
223 { "GD", kPOVAttrib_DebugFile, kPOVObjectClass_File, kPOVAttrib_DebugConsole },
224 { "GD", kNoParameter, kNoParameter, kPOVAttrib_DebugConsole },
225 { "GF", kPOVAttrib_FatalFile, kPOVObjectClass_File, kPOVAttrib_FatalConsole },
226 { "GF", kNoParameter, kNoParameter, kPOVAttrib_FatalConsole },
227 { "GI", kPOVAttrib_CreateIni, kPOVObjectClass_File, kNoParameter },
228 { "GR", kPOVAttrib_RenderFile, kPOVObjectClass_File, kPOVAttrib_RenderConsole },
229 { "GR", kNoParameter, kNoParameter, kPOVAttrib_RenderConsole },
230 { "GS", kPOVAttrib_StatisticsFile, kPOVObjectClass_File, kPOVAttrib_StatisticsConsole },
231 { "GS", kNoParameter, kNoParameter, kPOVAttrib_StatisticsConsole },
232 { "GW", kPOVAttrib_WarningFile, kPOVObjectClass_File, kPOVAttrib_WarningConsole },
233 { "GW", kNoParameter, kNoParameter, kPOVAttrib_WarningConsole },
234
235 { "HI", kPOVAttrib_IncludeHeader, kPOVObjectClass_File, kNoParameter },
236 { "HN", kPOVAttrib_HistogramFile, kPOVObjectClass_File, kNoParameter },
237 { "HS", kPOVAttrib_HistogramGridSizeX, kUseSpecialHandler, kNoParameter },
238 { "HT", kPOVAttrib_HistogramFileType, kUseSpecialHandler, kPOVAttrib_CreateHistogram },
239 { "H", kPOVAttrib_Height, kPOVMSType_Int, kNoParameter },
240
241 { "I", kPOVAttrib_InputFile, kPOVObjectClass_File, kNoParameter },
242
243 { "J", kPOVAttrib_JitterAmount, kPOVMSType_Float, kPOVAttrib_Jitter },
244 { "J", kNoParameter, kNoParameter, kPOVAttrib_Jitter },
245
246 { "KC", kNoParameter, kNoParameter, kPOVAttrib_CyclicAnimation },
247 { "KI", kPOVAttrib_InitialClock, kPOVMSType_Float, kNoParameter },
248 { "KFF", kPOVAttrib_FinalFrame, kPOVMSType_Int, kNoParameter },
249 { "KFI", kPOVAttrib_InitialFrame, kPOVMSType_Int, kNoParameter },
250 { "KF", kPOVAttrib_FinalClock, kPOVMSType_Float, kNoParameter },
251 { "K", kPOVAttrib_Clock, kPOVMSType_Float, kNoParameter },
252
253 { "L", kPOVAttrib_LibraryPath, kUseSpecialHandler, kNoParameter },
254
255 { "MB", kPOVAttrib_BoundingThreshold, kPOVMSType_Int, kPOVAttrib_Bounding },
256 { "MB", kNoParameter, kNoParameter, kPOVAttrib_Bounding },
257 { "MV", kPOVAttrib_Version, kPOVMSType_Float, kNoParameter },
258
259 { "O", kPOVAttrib_OutputFile, kPOVObjectClass_File, kNoParameter },
260
261 { "P", kNoParameter, kNoParameter, kPOVAttrib_PauseWhenDone },
262
263 { "QR", kNoParameter, kNoParameter, kPOVAttrib_Radiosity },
264 { "Q", kPOVAttrib_Quality, kPOVMSType_Int, kNoParameter },
265
266 { "R", kPOVAttrib_AntialiasDepth, kPOVMSType_Int, kNoParameter },
267
268 { "SC", kPOVAttrib_Left, kPOVMSType_Float, kNoParameter },
269 { "SF0", kPOVAttrib_SubsetStartFrame, kPOVMSType_Float, kNoParameter },
270 { "SF", kPOVAttrib_SubsetStartFrame, kPOVMSType_Int, kNoParameter },
271 { "SP", kPOVAttrib_PreviewStartSize, kPOVMSType_Int, kNoParameter },
272 { "SR", kPOVAttrib_Top, kPOVMSType_Float, kNoParameter },
273 { "SU", kNoParameter, kNoParameter, kPOVAttrib_SplitUnions },
274 #ifdef FRAME_STEP_PATCH
275 { "STP", kPOVAttrib_FrameStep, kPOVMSType_Int, kNoParameter },
276 #endif
277 { "UA", kNoParameter, kNoParameter, kPOVAttrib_OutputAlpha },
278 { "UD", kNoParameter, kNoParameter, kPOVAttrib_DrawVistas },
279 { "UF", kNoParameter, kNoParameter, kPOVAttrib_FieldRender },
280 { "UL", kNoParameter, kNoParameter, kPOVAttrib_LightBuffer },
281 { "UO", kNoParameter, kNoParameter, kPOVAttrib_OddField },
282 { "UR", kNoParameter, kNoParameter, kPOVAttrib_RemoveBounds },
283 { "UV", kNoParameter, kNoParameter, kPOVAttrib_VistaBuffer },
284
285 { "V", kNoParameter, kNoParameter, kPOVAttrib_Verbose },
286
287 { "WL", kPOVAttrib_WarningLevel, kPOVMSType_Int, kNoParameter },
288 { "W", kPOVAttrib_Width, kPOVMSType_Int, kNoParameter },
289
290 { "X", kPOVAttrib_TestAbortCount, kUseSpecialHandler, kPOVAttrib_TestAbort },
291 { "X", kNoParameter, kNoParameter, kPOVAttrib_TestAbort },
292
293 { NULL, 0, 0, 0 }
294 };
295
ProcessRenderOptions()296 ProcessRenderOptions::ProcessRenderOptions() : ProcessOptions(RenderOptions_INI_Table, RenderOptions_Cmd_Table)
297 {
298 }
299
~ProcessRenderOptions()300 ProcessRenderOptions::~ProcessRenderOptions()
301 {
302 }
303
ReadSpecialOptionHandler(INI_Parser_Table * option,char * param,POVMSObjectPtr obj)304 int ProcessRenderOptions::ReadSpecialOptionHandler(INI_Parser_Table *option, char *param, POVMSObjectPtr obj)
305 {
306 POVMSAttributeList list;
307 double floatval = 0.0;
308 int intval = 0;
309 int intval2 = 0;
310 int err = kNoErr;
311
312 switch(option->key)
313 {
314 case kPOVAttrib_HistogramGridSizeX:
315 if(sscanf(param, "%d.%d", &intval, &intval2) == 2)
316 {
317 err = POVMSUtil_SetInt(obj, kPOVAttrib_HistogramGridSizeX, intval);
318 if(err == kNoErr)
319 err = POVMSUtil_SetInt(obj, kPOVAttrib_HistogramGridSizeY, intval2);
320 }
321 else
322 {
323 ParseError("Invalid histogram grid size '%s'.", param);
324 err = kParseErr;
325 }
326 break;
327 case kPOVAttrib_Palette:
328 case kPOVAttrib_VideoMode:
329 while(isspace(*param))
330 param++;
331 err = POVMSUtil_SetInt(obj, option->key, tolower(*param));
332 break;
333 case kPOVAttrib_HistogramFileType:
334 case kPOVAttrib_OutputFileType:
335 while(isspace(*param))
336 param++;
337 if(strchr(Output_File_Types, *param) == NULL)
338 ParseError("Unrecognized output file format %c.", *param);
339 err = POVMSUtil_SetInt(obj, option->key, tolower(*param));
340 break;
341 case kPOVAttrib_IncludeIni:
342 case kPOVAttrib_LibraryPath:
343 POVMSAttribute attr;
344
345 if(err == kNoErr)
346 {
347 // parse INI file (recursive)
348 if(option->key == kPOVAttrib_IncludeIni)
349 err = ParseFile(param, obj);
350
351 // create list if it isn't there
352 if(err == kNoErr)
353 {
354 if(POVMSObject_Exist(obj, option->key) == kFalseErr)
355 err = POVMSAttrList_New(&list);
356 else if(POVMSObject_Exist(obj, option->key) != kNoErr)
357 err = kObjectAccessErr;
358 else
359 err = POVMSObject_Get(obj, &list, option->key);
360 }
361 }
362 else
363 {
364 ParseError("File name or path parameter expected for option '%s', found '%s'.", option->keyword, param);
365 err = kParseErr;
366 }
367
368 // add path or file to list
369 if(err == kNoErr)
370 err = POVMSAttr_New(&attr);
371 if(err == kNoErr)
372 {
373 err = POVMSAttr_Set(&attr, kPOVMSType_CString, (void *)param, strlen(param) + 1);
374 if(err == kNoErr)
375 err = POVMSAttrList_Append(&list, &attr);
376 else
377 err = POVMSAttr_Delete(&attr);
378 }
379 if(err == kNoErr)
380 err = POVMSObject_Set(obj, &list, option->key);
381 break;
382 case kPOVAttrib_Declare:
383 POVMSObject decobj;
384
385 // create list if it isn't there
386 if(POVMSObject_Exist(obj, option->key) == kFalseErr)
387 err = POVMSAttrList_New(&list);
388 else if(POVMSObject_Exist(obj, option->key) != kNoErr)
389 err = kObjectAccessErr;
390 else
391 err = POVMSObject_Get(obj, &list, option->key);
392
393 // add value to list
394 if(err == kNoErr)
395 err = POVMSObject_New(&decobj, kPOVMSType_WildCard);
396 if(err == kNoErr)
397 {
398 char *ptr = NULL;
399
400 err = POVMSUtil_SetString(&decobj, kPOVAttrib_Identifier, strtok(param, "="));
401 if(err == kNoErr)
402 {
403 ptr = strtok(NULL, "");
404 if(ptr == NULL)
405 err = kParseErr;
406 }
407 if(err == kNoErr)
408 {
409 if(strchr(ptr, '"') != NULL)
410 {
411 ptr = strchr(ptr, '"') + 1;
412 strtok(ptr, "\"");
413 err = POVMSUtil_SetString(&decobj, kPOVAttrib_Value, ptr);
414 }
415 else
416 err = POVMSUtil_SetFloat(&decobj, kPOVAttrib_Value, atof(ptr));
417 }
418 if(err == kNoErr)
419 err = POVMSAttrList_Append(&list, &decobj);
420 else
421 err = POVMSObject_Delete(&decobj);
422 }
423 if(err == kNoErr)
424 err = POVMSObject_Set(obj, &list, option->key);
425 break;
426 case kPOVAttrib_FatalErrorCommand:
427 case kPOVAttrib_PostFrameCommand:
428 case kPOVAttrib_PostSceneCommand:
429 case kPOVAttrib_PreFrameCommand:
430 case kPOVAttrib_PreSceneCommand:
431 case kPOVAttrib_UserAbortCommand:
432 POVMSObject cmdobj;
433
434 if(POVMSObject_Exist(obj, option->key) == kNoErr)
435 err = POVMSObject_Get(obj, &cmdobj, option->key);
436 else
437 err = POVMSObject_New(&cmdobj, kPOVMSType_WildCard);
438 if(toupper(*(option->keyword + strlen(option->keyword) - 1)) == 'D')
439 {
440 if(err == kNoErr)
441 err = POVMSUtil_SetString(&cmdobj, kPOVAttrib_CommandString, param);
442 }
443 else
444 {
445 if(err == kNoErr)
446 {
447 int i = 0;
448
449 if((*param == '-') || (*param == '!'))
450 i = tolower(*(param + 1));
451 else
452 i = tolower(*param);
453 err = POVMSUtil_SetInt(&cmdobj, kPOVAttrib_ReturnAction, i);
454 }
455 }
456 if(err == kNoErr)
457 err = POVMSObject_Set(obj, &cmdobj, option->key);
458 break;
459 }
460
461 return err;
462 }
463
ReadSpecialSwitchHandler(Cmd_Parser_Table * option,char * param,POVMSObjectPtr obj,bool)464 int ProcessRenderOptions::ReadSpecialSwitchHandler(Cmd_Parser_Table *option, char *param, POVMSObjectPtr obj, bool)
465 {
466 int intval = 0;
467 int intval2 = 0;
468 int err = 0;
469 char chr = 0;
470
471 switch(option->key)
472 {
473 case kPOVAttrib_Display:
474 if(param[0] != '\0')
475 {
476 err = POVMSUtil_SetInt(obj, kPOVAttrib_VideoMode, (int)toupper(param[0]));
477 if((param[1] != '\0') && (err == 0))
478 err = POVMSUtil_SetInt(obj, kPOVAttrib_Palette, (int)toupper(param[1]));
479 }
480 break;
481 case kPOVAttrib_HistogramGridSizeX:
482 if(sscanf(param, "%d.%d", &intval, &intval2) == 2)
483 {
484 err = POVMSUtil_SetInt(obj, kPOVAttrib_HistogramGridSizeX, intval);
485 if(err == kNoErr)
486 err = POVMSUtil_SetInt(obj, kPOVAttrib_HistogramGridSizeY, intval2);
487 }
488 else
489 {
490 ParseError("Invalid histogram grid size '%s'.", param);
491 err = kParseErr;
492 }
493 break;
494 case kPOVAttrib_OutputFileType:
495 if(strchr(Output_File_Types, *param) == NULL)
496 ParseError("Unrecognized output file format %c.", *param);
497 err = POVMSUtil_SetInt(obj, option->key, tolower(*param));
498 param++;
499 if((err == kNoErr) && (*param > ' '))
500 {
501 if(isdigit(*param) != 0)
502 {
503 if(sscanf(param, "%d", &intval) == 1)
504 err = POVMSUtil_SetInt(obj, kPOVAttrib_BitsPerColor, intval);
505 else
506 {
507 ParseError("Invalid bits per color '%s'.", param);
508 err = kParseErr;
509 }
510 }
511 else
512 {
513 ParseError("Missing bits per color, '%s' found instead.", param);
514 err = kParseErr;
515 }
516 }
517 break;
518 case kPOVAttrib_HistogramFileType:
519 if(strchr(Output_File_Types, *param) == NULL)
520 {
521 ParseError("Unrecognized output file format %c.", *param);
522 err = kParseErr;
523 }
524 else
525 {
526 chr = tolower(*param);
527 err = POVMSUtil_SetInt(obj, option->key, chr);
528 }
529 break;
530 case kPOVAttrib_LibraryPath:
531 POVMSAttributeList list;
532 POVMSAttribute attr;
533
534 if(err == kNoErr)
535 {
536 // create list if it isn't there
537 if(POVMSObject_Exist(obj, option->key) == kFalseErr)
538 err = POVMSAttrList_New(&list);
539 else if(POVMSObject_Exist(obj, option->key) != kNoErr)
540 err = kObjectAccessErr;
541 else
542 err = POVMSObject_Get(obj, &list, option->key);
543 }
544 else
545 {
546 ParseError("File name or path parameter expected for switch '%s', found '%s'.", option->command, param);
547 err = kParseErr;
548 }
549
550 // add path or file to list
551 if(err == kNoErr)
552 err = POVMSAttr_New(&attr);
553 if(err == kNoErr)
554 {
555 err = POVMSAttr_Set(&attr, kPOVMSType_CString, (void *)param, strlen(param) + 1);
556 if(err == kNoErr)
557 err = POVMSAttrList_Append(&list, &attr);
558 else
559 err = POVMSAttr_Delete(&attr);
560 }
561 if(err == kNoErr)
562 err = POVMSObject_Set(obj, &list, option->key);
563 break;
564 case kPOVAttrib_TestAbortCount:
565 if((*param) == 0)
566 break;
567 if(sscanf(param, "%d", &intval) == 1)
568 err = POVMSUtil_SetInt(obj, option->key, intval);
569 else
570 {
571 ParseError("No or integer parameter expected for switch '%s', found '%s'.", option->command, param);
572 err = kParseErr;
573 }
574 break;
575 }
576
577 return err;
578 }
579
WriteSpecialOptionHandler(INI_Parser_Table * option,POVMSObjectPtr obj,OTextStream * file)580 int ProcessRenderOptions::WriteSpecialOptionHandler(INI_Parser_Table *option, POVMSObjectPtr obj, OTextStream *file)
581 {
582 POVMSAttributeList list;
583 POVMSFloat floatval;
584 POVMSInt intval,intval2;
585 int err = 0;
586 int l;
587 int i,imax;
588 POVMSAttribute item;
589 char *bufptr;
590 char chr;
591
592 switch(option->key)
593 {
594 case kPOVAttrib_HistogramGridSizeX:
595 if(POVMSUtil_GetInt(obj, kPOVAttrib_HistogramGridSizeX, &intval) == 0)
596 {
597 if(POVMSUtil_GetInt(obj, kPOVAttrib_HistogramGridSizeY, &intval2) == 0)
598 file->printf("%s=%d.%d\n", option->keyword, intval, intval2);
599 }
600 break;
601 case kPOVAttrib_Palette:
602 case kPOVAttrib_VideoMode:
603 case kPOVAttrib_OutputFileType:
604 case kPOVAttrib_HistogramFileType:
605 if(POVMSUtil_GetInt(obj, option->key, &intval) == 0)
606 {
607 chr = intval;
608 if(chr > 32)
609 file->printf("%s=%c\n", option->keyword, chr);
610 }
611 break;
612 case kPOVAttrib_IncludeIni:
613 break;
614 case kPOVAttrib_Declare:
615 POVMSObject decobj;
616
617 err = POVMSObject_Get(obj, &list, option->key);
618 if(err != 0)
619 break;
620
621 l = 0;
622 err = POVMSAttrList_Count(&list, &l);
623 if(err != 0)
624 break;
625 if(l == 0)
626 break;
627
628 imax = l;
629 for(i = 1; i <= imax; i++)
630 {
631 err = POVMSAttrList_GetNth(&list, i, &decobj);
632 if(err == 0)
633 err = POVMSObject_Get(&decobj, &item, kPOVAttrib_Identifier);
634 if(err == 0)
635 {
636 l = 0;
637 err = POVMSAttr_Size(&item, &l);
638 if(l > 0)
639 {
640 bufptr = new char[l];
641 bufptr[0] = 0;
642 if((POVMSUtil_GetFloat(&decobj, kPOVAttrib_Value, &floatval) == 0) &&
643 (POVMSAttr_Get(&item, kPOVMSType_CString, bufptr, &l) == 0))
644 file->printf("%s=%s=%g\n", option->keyword, bufptr, (float)floatval);
645 delete[] bufptr;
646 }
647 (void)POVMSAttr_Delete(&item);
648 }
649 }
650 break;
651 case kPOVAttrib_LibraryPath:
652 err = POVMSObject_Get(obj, &list, option->key);
653 if(err != 0)
654 break;
655
656 l = 0;
657 err = POVMSAttrList_Count(&list, &l);
658 if(err != 0)
659 break;
660 if(l == 0)
661 break;
662
663 imax = l;
664 for(i = 1; i <= imax; i++)
665 {
666 err = POVMSAttrList_GetNth(&list, i, &item);
667 if(err == 0)
668 {
669 l = 0;
670 err = POVMSAttr_Size(&item, &l);
671 if(l > 0)
672 {
673 bufptr = new char[l];
674 bufptr[0] = 0;
675 if(POVMSAttr_Get(&item, kPOVMSType_CString, bufptr, &l) == 0)
676 file->printf("%s=\"%s\"\n", option->keyword, bufptr);
677 delete[] bufptr;
678 }
679 (void)POVMSAttr_Delete(&item);
680 }
681 }
682 break;
683 case kPOVAttrib_FatalErrorCommand:
684 case kPOVAttrib_PostFrameCommand:
685 case kPOVAttrib_PostSceneCommand:
686 case kPOVAttrib_PreFrameCommand:
687 case kPOVAttrib_PreSceneCommand:
688 case kPOVAttrib_UserAbortCommand:
689 POVMSObject cmdobj;
690
691 err = POVMSObject_Get(obj, &cmdobj, option->key);
692 if(err != 0)
693 break;
694
695 err = POVMSObject_Get(&cmdobj, &item, kPOVAttrib_CommandString);
696 if(err == 0)
697 {
698 if(toupper(*(option->keyword + strlen(option->keyword) - 1)) == 'D')
699 {
700 l = 0;
701 err = POVMSAttr_Size(&item, &l);
702 if(l > 0)
703 {
704 bufptr = new char[l];
705 bufptr[0] = 0;
706 if(POVMSAttr_Get(&item, kPOVMSType_CString, bufptr, &l) == 0)
707 file->printf("%s=%s\n", option->keyword, bufptr);
708 delete[] bufptr;
709 }
710 }
711 else
712 {
713 if(POVMSUtil_GetInt(&cmdobj, kPOVAttrib_ReturnAction, &intval) == 0)
714 {
715 if(intval < 0)
716 {
717 chr = -intval;
718 file->printf("%s=!%c\n", option->keyword, chr);
719 }
720 else
721 {
722 chr = intval;
723 file->printf("%s=%c\n", option->keyword, chr);
724 }
725 }
726 }
727 }
728 if(err == 0)
729 err = POVMSObject_Delete(&cmdobj);
730 break;
731 }
732
733 return err;
734 }
735
WriteOptionFilter(INI_Parser_Table * table)736 bool ProcessRenderOptions::WriteOptionFilter(INI_Parser_Table *table)
737 {
738 // So that we don't get both Bits_Per_Color and Bits_Per_Colour in the INI file.
739 return (strcmp(table->keyword, "Bits_Per_Colour") != 0);
740 }
741
ProcessUnknownString(char * str,POVMSObjectPtr obj)742 int ProcessRenderOptions::ProcessUnknownString(char *str, POVMSObjectPtr obj)
743 {
744 POVMSAttributeList list;
745 POVMSAttribute attr;
746 int state = 0; // INI file
747 int err = kNoErr;
748
749 if(str == NULL)
750 {
751 ParseError("Expected filename, nothing was found.");
752 return kParseErr;
753 }
754
755 // add filename or path
756
757 // see if it is a POV file
758 if(state == 0)
759 {
760 char *ptr = strrchr(str, '.');
761 if(ptr != NULL)
762 {
763 if(pov_stricmp(ptr, ".pov") == 0)
764 state = 1; // POV file
765 }
766 }
767
768 // see if it is a path
769 if(state == 0)
770 {
771 if(strlen(str) > 0)
772 {
773 if(str[strlen(str) - 1] == FILENAME_SEPARATOR)
774 state = 2; // library path
775 }
776 }
777
778 switch(state)
779 {
780 // INI file
781 case 0:
782 // parse INI file (recursive)
783 err = ParseFile(str, obj);
784 if(err == kNoErr)
785 {
786 // create list if it isn't there
787 if(POVMSObject_Exist(obj, kPOVAttrib_IncludeIni) == kFalseErr)
788 err = POVMSAttrList_New(&list);
789 else if(POVMSObject_Exist(obj, kPOVAttrib_IncludeIni) != kNoErr)
790 err = kObjectAccessErr;
791 else
792 err = POVMSObject_Get(obj, &list, kPOVAttrib_IncludeIni);
793 }
794
795 // add INI file to list
796 if(err == kNoErr)
797 err = POVMSAttr_New(&attr);
798 if(err == kNoErr)
799 {
800 err = POVMSAttr_Set(&attr, kPOVMSType_CString, str, strlen(str) + 1);
801 if(err == kNoErr)
802 err = POVMSAttrList_Append(&list, &attr);
803 else
804 err = POVMSAttr_Delete(&attr);
805 }
806 if(err == kNoErr)
807 err = POVMSObject_Set(obj, &list, kPOVAttrib_IncludeIni);
808 break;
809 // POV file
810 case 1:
811 // set POV file
812 err = POVMSUtil_SetString(obj, kPOVAttrib_InputFile, str);
813 break;
814 // library path
815 case 2:
816 // create list if it isn't there
817 if(POVMSObject_Exist(obj, kPOVAttrib_LibraryPath) == kFalseErr)
818 err = POVMSAttrList_New(&list);
819 else if(POVMSObject_Exist(obj, kPOVAttrib_LibraryPath) != kNoErr)
820 err = kObjectAccessErr;
821 else
822 err = POVMSObject_Get(obj, &list, kPOVAttrib_LibraryPath);
823
824 // add librarypath to list
825 if(err == kNoErr)
826 err = POVMSAttr_New(&attr);
827 if(err == kNoErr)
828 {
829 err = POVMSAttr_Set(&attr, kPOVMSType_CString, str, strlen(str) + 1);
830 if(err == kNoErr)
831 err = POVMSAttrList_Append(&list, &attr);
832 else
833 err = POVMSAttr_Delete(&attr);
834 }
835 if(err == kNoErr)
836 err = POVMSObject_Set(obj, &list, kPOVAttrib_LibraryPath);
837 break;
838 }
839
840 return err;
841 }
842
OpenFileForRead(const char * filename,POVMSObjectPtr obj)843 ITextStream *ProcessRenderOptions::OpenFileForRead(const char *filename, POVMSObjectPtr obj)
844 {
845 char buffer[FILE_NAME_LENGTH];
846
847 return OpenINIFileStream(filename, POV_BASE_NAMESPACE::POV_File_Text_INI, buffer, obj);
848 }
849
OpenFileForWrite(const char * filename,POVMSObjectPtr)850 OTextStream *ProcessRenderOptions::OpenFileForWrite(const char *filename, POVMSObjectPtr)
851 {
852 return new OTextStream(filename, POV_BASE_NAMESPACE::POV_File_Text_INI);
853 }
854
OpenINIFileStream(const char * filename,unsigned int stype,char * buffer,POVMSObjectPtr obj)855 ITextStream *ProcessRenderOptions::OpenINIFileStream(const char *filename, unsigned int stype, char *buffer, POVMSObjectPtr obj)
856 {
857 int i,ii,l[4];
858 char pathname[FILE_NAME_LENGTH];
859 char file[FILE_NAME_LENGTH];
860 char file_x[4][FILE_NAME_LENGTH];
861 int cnt = 0;
862 int ll;
863 POVMSAttribute attr, item;
864
865 if(Has_Extension(filename))
866 {
867 for(i = 0; i < 4; i++)
868 l[i]=0;
869 }
870 else
871 {
872 for(i = 0; i < 4; i++)
873 {
874 if((l[i] = strlen(gPOV_File_Extensions[stype].ext[i])) > 0)
875 {
876 strcpy(file_x[i], filename);
877 strcat(file_x[i], gPOV_File_Extensions[stype].ext[i]);
878 }
879 }
880 }
881
882 // Check the current directory first
883 for(i = 0; i < 4; i++)
884 {
885 if(l[i])
886 {
887 if(EXIST_FILE(file_x[i]) == true)
888 {
889 strcpy(buffer,file_x[i]);
890 return new ITextStream(file_x[i], stype);
891 }
892 }
893 }
894 if(EXIST_FILE(filename) == true)
895 {
896 strcpy(buffer,filename);
897 return new ITextStream(filename, stype);
898 }
899
900 if(POVMSObject_Get(obj, &attr, kPOVAttrib_LibraryPath) != 0)
901 return NULL;
902
903 if(POVMSAttrList_Count(&attr, &cnt) != 0)
904 {
905 (void)POVMSAttrList_Delete(&attr);
906 return NULL;
907 }
908
909 for (i = 1; i <= cnt; i++)
910 {
911 (void)POVMSAttr_New(&item);
912 if(POVMSAttrList_GetNth(&attr, i, &item) != 0)
913 continue;
914 ll = 0;
915 if(POVMSAttr_Size(&item, &ll) != 0)
916 {
917 (void)POVMSAttr_Delete(&item);
918 continue;
919 }
920 if(ll <= 0)
921 {
922 (void)POVMSAttr_Delete(&item);
923 continue;
924 }
925 if(POVMSAttr_Get(&item, kPOVMSType_CString, file, &ll) != 0)
926 {
927 (void)POVMSAttr_Delete(&item);
928 continue;
929 }
930 (void)POVMSAttr_Delete(&item);
931
932 file[strlen(file)+1] = '\0';
933 if(file[strlen(file) - 1] != DRIVE_SEPARATOR)
934 file[strlen(file)] = FILENAME_SEPARATOR;
935
936 for(ii = 0; ii < 4; ii++)
937 {
938 if(l[ii])
939 {
940 strcpy(pathname, file);
941 strcat(pathname, file_x[ii]);
942 if(EXIST_FILE(pathname) == true)
943 {
944 strcpy(buffer,pathname);
945 (void)POVMSAttrList_Delete(&attr);
946 return new ITextStream(pathname, stype);
947 }
948 }
949 }
950 strcpy(pathname, file);
951 strcat(pathname, filename);
952 if(EXIST_FILE(pathname) == true)
953 {
954 strcpy(buffer,pathname);
955 (void)POVMSAttrList_Delete(&attr);
956 return new ITextStream(pathname, stype);
957 }
958 }
959
960 (void)POVMSAttrList_Delete(&attr);
961
962 if(l[0])
963 ParseError("Could not find file '%s%s'", filename, gPOV_File_Extensions[stype].ext[0]);
964 else
965 ParseError("Could not find file '%s'", filename);
966
967 return NULL;
968 }
969
970 END_POV_FRONTEND_NAMESPACE
971