-
Notifications
You must be signed in to change notification settings - Fork 9
/
cmdfiles.cpp
4011 lines (3749 loc) · 109 KB
/
cmdfiles.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
Command-line / Command-File Parser Routines
*/
#include <cassert>
#include <string>
#include <system_error>
#include <vector>
#include <ctype.h>
#include <float.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include "port.h"
#include "prototyp.h"
#include "fractype.h"
#include "drivers.h"
#include "helpcom.h"
#ifdef XFRACT
#define DEFAULT_PRINTER 5 // Assume a Postscript printer
#define PRT_RESOLUTION 100 // Assume medium resolution
#else
#define DEFAULT_PRINTER 2 // Assume an IBM/Epson printer
#define PRT_RESOLUTION 60 // Assume low resolution
#endif
static int cmdfile(FILE *handle, cmd_file mode);
static int next_command(
char *cmdbuf,
int maxlen,
FILE *handle,
char *linebuf,
int *lineoffset,
cmd_file mode);
static bool next_line(FILE *handle, char *linebuf, cmd_file mode);
int cmdarg(char *argument, cmd_file mode);
static void argerror(char const *);
static void initvars_run();
static void initvars_restart();
static void initvars_fractal();
static void initvars_3d();
static void reset_ifs_defn();
static void parse_textcolors(char const *value);
static int parse_colors(char const *value);
static int get_bf(bf_t bf, char const *curarg);
static bool isabigfloat(char const *str);
// variables defined by the command line/files processor
int g_stop_pass = 0; // stop at this guessing pass early
int g_distance_estimator_x_dots = 0; // xdots to use for video independence
int g_distance_estimator_y_dots = 0; // ydots to use for video independence
int g_bf_digits = 0; // digits to use (force) for bf_math
int g_show_dot = -1; // color to show crawling graphics cursor
int g_size_dot = 0; // size of dot crawling cursor
record_colors_mode g_record_colors = record_colors_mode::none; // default PAR color-writing method
char g_auto_show_dot = 0; // dark, medium, bright
bool g_start_show_orbit = false; // show orbits on at start of fractal
std::string g_read_filename; // name of fractal input file
std::string g_temp_dir; // name of temporary directory
std::string g_working_dir; // name of directory for misc files
std::string g_organize_formulas_dir; // name of directory for orgfrm files
std::string g_gif_filename_mask;
char PrintName[FILE_MAX_PATH] = {"fract001.prn"}; // Name for print-to-file
// cppcheck-suppress constStatement
std::string g_save_filename{"fract001"}; // save files using this name
// cppcheck-suppress constStatement
std::string g_auto_name{"auto.key"}; // record auto keystrokes here
bool g_potential_flag = false; // continuous potential enabled?
bool g_potential_16bit = false; // store 16 bit continuous potential values
bool g_gif87a_flag = false; // true if GIF87a format, false otherwise
bool g_dither_flag = false; // true if want to dither GIFs
bool g_ask_video = false; // flag for video prompting
bool g_float_flag = false;
int g_biomorph = 0; // flag for biomorph
int g_user_biomorph_value = 0;
symmetry_type g_force_symmetry = symmetry_type::NONE; // force symmetry
int g_show_file = 0; // zero if file display pending
bool g_random_seed_flag = false;
int g_random_seed = 0; // Random number seeding flag and value
int g_decomp[2] = { 0 }; // Decomposition coloring
long g_distance_estimator = 0;
int g_distance_estimator_width_factor = 0;
bool g_overwrite_file = false;// true if file overwrite allowed
int g_sound_flag = 0; // sound control bitfield... see sound.c for useage
int g_base_hertz = 0; // sound=x/y/x hertz value
int g_debug_flag = debug_flags::none; // internal use only - you didn't see this
bool g_timer_flag = false; // you didn't see this, either
int g_cycle_limit = 0; // color-rotator upper limit
int g_inside_color = 0; // inside color: 1=blue
int g_fill_color = 0; // fillcolor: -1=normal
int g_outside_color = COLOR_BLACK; // outside color
bool g_finite_attractor = false; // finite attractor logic
display_3d_modes g_display_3d = display_3d_modes::NONE; // 3D display flag: 0 = OFF
bool g_overlay_3d = false; // 3D overlay flag
int g_init_3d[20] = { 0 }; // '3d=nn/nn/nn/...' values
bool g_check_cur_dir = false; // flag to check current dir for files
batch_modes g_init_batch = batch_modes::NONE; // 1 if batch run (no kbd)
int g_init_save_time = 0; // autosave minutes
DComplex g_init_orbit = { 0.0 }; // initial orbitvalue
init_orbit_mode g_use_init_orbit = init_orbit_mode::normal; // flag for initorbit
int g_init_mode = 0; // initial video mode
int g_init_cycle_limit = 0; // initial cycle limit
bool g_use_center_mag = false; // use center-mag corners
long g_bail_out = 0; // user input bailout value
bailouts g_bail_out_test; // test used for determining bailout
double g_inversion[3] = { 0.0 }; // radius, xcenter, ycenter
int g_color_cycle_range_lo = 0;
int g_color_cycle_range_hi = 0; // cycling color range
std::vector<int> g_iteration_ranges; // iter->color ranges mapping
int g_iteration_ranges_len = 0; // size of ranges array
BYTE g_map_clut[256][3]; // map= (default colors)
bool g_map_specified = false; // map= specified
BYTE *mapdacbox = nullptr; // map= (default colors)
int g_color_state = 0; // 0, g_dac_box matches default (bios or map=)
// 1, g_dac_box matches no known defined map
// 2, g_dac_box matches the colorfile map
bool g_colors_preloaded = false; // if g_dac_box preloaded for next mode select
int g_save_release = 0; // release creating PAR file
bool g_read_color = true; // flag for reading color from GIF
double g_math_tol[2] = {.05, .05}; // For math transition
bool g_targa_out = false; // 3D fullcolor flag
bool g_truecolor = false; // escape time truecolor flag
true_color_mode g_true_mode = true_color_mode::default_color; // truecolor coloring scheme
std::string g_color_file; // from last <l> <s> or colors=@filename
bool g_new_bifurcation_functions_loaded = false; // if function loaded for new bifs
float g_screen_aspect = DEFAULTASPECT; // aspect ratio of the screen
float g_aspect_drift = DEFAULTASPECTDRIFT; // how much drift is allowed and
// still forced to screenaspect
bool g_fast_restore = false; /* true - reset viewwindows prior to a restore
and do not display warnings when video
mode changes during restore */
bool g_organize_formulas_search = false; /* 1 - user has specified a directory for
Orgform formula compilation files */
int g_orbit_save_flags = 0; // for IFS and LORENZ to output acrospin file
int g_orbit_delay = 0; // clock ticks delating orbit release
int g_transparent_color_3d[2] = { 0 }; // transparency min/max values
long g_log_map_flag = 0; // Logarithmic palette flag: 0 = no
BYTE g_exit_video_mode = 3; // video mode on exit
int g_log_map_fly_calculate = 0; // calculate logmap on-the-fly
bool g_log_map_auto_calculate = false; // auto calculate logmap
bool g_bof_match_book_images = true; // Flag to make inside=bof options not duplicate bof images
bool g_escape_exit = false; // set to true to avoid the "are you sure?" screen
bool g_first_init = true; // first time into cmdfiles?
static int init_rseed = 0;
static bool initcorners = false;
static bool initparams = false;
fractalspecificstuff *curfractalspecific = nullptr;
std::string g_formula_filename; // file to find (type=)formulas in
std::string g_formula_name; // Name of the Formula (if not null)
std::string g_l_system_filename; // file to find (type=)L-System's in
std::string g_l_system_name; // Name of L-System
std::string g_command_file; // file to find command sets in
std::string g_command_name; // Name of Command set
std::string g_command_comment[4]; // comments for command set
std::string g_ifs_filename; // file to find (type=)IFS in
std::string g_ifs_name; // Name of the IFS def'n (if not null)
id::SearchPath g_search_for = { 0 };
std::vector<float> g_ifs_definition; // ifs parameters
bool g_ifs_type = false; // false=2d, true=3d
slides_mode g_slides = slides_mode::OFF; // PLAY autokey=play, RECORD autokey=record
BYTE txtcolor[] =
{
BLUE*16+L_WHITE, // C_TITLE title background
BLUE*16+L_GREEN, // C_TITLE_DEV development vsn foreground
GREEN*16+YELLOW, // C_HELP_HDG help page title line
WHITE*16+BLACK, // C_HELP_BODY help page body
GREEN*16+GRAY, // C_HELP_INSTR help page instr at bottom
WHITE*16+BLUE, // C_HELP_LINK help page links
CYAN*16+BLUE, // C_HELP_CURLINK help page current link
WHITE*16+GRAY, // C_PROMPT_BKGRD prompt/choice background
WHITE*16+BLACK, // C_PROMPT_TEXT prompt/choice extra info
BLUE*16+WHITE, // C_PROMPT_LO prompt/choice text
BLUE*16+L_WHITE, // C_PROMPT_MED prompt/choice hdg2/...
BLUE*16+YELLOW, // C_PROMPT_HI prompt/choice hdg/cur/...
GREEN*16+L_WHITE, // C_PROMPT_INPUT fullscreen_prompt input
CYAN*16+L_WHITE, // C_PROMPT_CHOOSE fullscreen_prompt choice
MAGENTA*16+L_WHITE, // C_CHOICE_CURRENT fullscreen_choice input
BLACK*16+WHITE, // C_CHOICE_SP_INSTR speed key bar & instr
BLACK*16+L_MAGENTA, // C_CHOICE_SP_KEYIN speed key value
WHITE*16+BLUE, // C_GENERAL_HI tab, thinking, IFS
WHITE*16+BLACK, // C_GENERAL_MED
WHITE*16+GRAY, // C_GENERAL_LO
BLACK*16+L_WHITE, // C_GENERAL_INPUT
WHITE*16+BLACK, // C_DVID_BKGRD disk video
BLACK*16+YELLOW, // C_DVID_HI
BLACK*16+L_WHITE, // C_DVID_LO
RED*16+L_WHITE, // C_STOP_ERR stop message, error
GREEN*16+BLACK, // C_STOP_INFO stop message, info
BLUE*16+WHITE, // C_TITLE_LOW bottom lines of title screen
GREEN*16+BLACK, // C_AUTHDIV1 title screen dividers
GREEN*16+GRAY, // C_AUTHDIV2 title screen dividers
BLACK*16+L_WHITE, // C_PRIMARY primary authors
BLACK*16+WHITE // C_CONTRIB contributing authors
};
/*
cmdfiles(argc,argv) process the command-line arguments
it also processes the 'sstools.ini' file and any
indirect files ('fractint @myfile')
*/
// This probably ought to go somewhere else, but it's used here.
// getpower10(x) returns the magnitude of x. This rounds
// a little so 9.95 rounds to 10, but we're using a binary base anyway,
// so there's nothing magic about changing to the next power of 10.
int getpower10(LDBL x)
{
char string[11]; // space for "+x.xe-xxxx"
int p;
sprintf(string, "%+.1Le", x);
p = atoi(string+5);
return p;
}
namespace
{
std::string findpath(char const *filename)
{
char buffer[FILE_MAX_PATH] = { 0 };
::findpath(filename, buffer);
return buffer;
}
void process_sstools_ini()
{
std::string const sstools_ini = findpath("sstools.ini"); // look for SSTOOLS.INI
if (!sstools_ini.empty()) // found it!
{
FILE *initfile = fopen(sstools_ini.c_str(), "r");
if (initfile != nullptr)
{
cmdfile(initfile, cmd_file::SSTOOLS_INI); // process it
}
}
}
void process_simple_command(char *curarg)
{
bool processed = false;
if (strchr(curarg, '=') == nullptr)
{
// not xxx=yyy, so check for gif
std::string filename = curarg;
if (has_ext(curarg) == nullptr)
{
filename += ".gif";
}
if (FILE *initfile = fopen(filename.c_str(), "rb"))
{
char tempstring[101];
if (fread(tempstring, 6, 1, initfile) != 6)
{
throw std::system_error(errno, std::system_category(), "process_simple_command failed fread");
}
if (tempstring[0] == 'G'
&& tempstring[1] == 'I'
&& tempstring[2] == 'F'
&& tempstring[3] >= '8' && tempstring[3] <= '9'
&& tempstring[4] >= '0' && tempstring[4] <= '9')
{
g_read_filename = curarg;
g_browse_name = extract_filename(g_read_filename.c_str());
g_show_file = 0;
processed = true;
}
fclose(initfile);
}
}
if (!processed)
{
cmdarg(curarg, cmd_file::AT_CMD_LINE); // process simple command
}
}
void process_file_setname(char *curarg, char *sptr)
{
*sptr = 0;
if (merge_pathnames(g_command_file, &curarg[1], cmd_file::AT_CMD_LINE) < 0)
{
init_msg("", g_command_file.c_str(), cmd_file::AT_CMD_LINE);
}
g_command_name = &sptr[1];
FILE *initfile = nullptr;
if (find_file_item(g_command_file, g_command_name.c_str(), &initfile, 0) || initfile == nullptr)
{
argerror(curarg);
}
cmdfile(initfile, cmd_file::AT_CMD_LINE_SET_NAME);
}
void process_file(char *curarg)
{
FILE *initfile = fopen(&curarg[1], "r");
if (initfile == nullptr)
{
argerror(curarg);
}
cmdfile(initfile, cmd_file::AT_CMD_LINE);
}
}
int cmdfiles(int argc, char const *const *argv)
{
if (g_first_init)
{
initvars_run(); // once per run initialization
}
initvars_restart(); // <ins> key initialization
initvars_fractal(); // image initialization
process_sstools_ini();
// cycle through args
for (int i = 1; i < argc; i++)
{
char curarg[141];
strcpy(curarg, argv[i]);
if (curarg[0] == ';') // start of comments?
{
break;
}
if (curarg[0] != '@')
{
process_simple_command(curarg);
}
// @filename/setname?
else if (char *sptr = strchr(curarg, '/'))
{
process_file_setname(curarg, sptr);
}
// @filename
else
{
process_file(curarg);
}
}
if (!g_first_init)
{
g_init_mode = -1; // don't set video when <ins> key used
g_show_file = 1; // nor startup image file
}
init_msg("", nullptr, cmd_file::AT_CMD_LINE); // this causes driver_get_key if init_msg called on runup
if (g_debug_flag != debug_flags::allow_init_commands_anytime)
{
g_first_init = false;
}
// PAR reads a file and sets color, don't read colors from GIF
g_read_color = !(g_colors_preloaded && g_show_file == 0);
//set structure of search directories
strcpy(g_search_for.par, g_command_file.c_str());
strcpy(g_search_for.frm, g_formula_filename.c_str());
strcpy(g_search_for.lsys, g_l_system_filename.c_str());
strcpy(g_search_for.ifs, g_ifs_filename.c_str());
return 0;
}
int load_commands(FILE *infile)
{
// when called, file is open in binary mode, positioned at the
// '(' or '{' following the desired parameter set's name
int ret;
initcorners = false;
initparams = false; // reset flags for type=
ret = cmdfile(infile, cmd_file::AT_AFTER_STARTUP);
// PAR reads a file and sets color, don't read colors from GIF
g_read_color = !(g_colors_preloaded && g_show_file == 0);
return ret;
}
static void initvars_run() // once per run init
{
init_rseed = (int)time(nullptr);
init_comments();
char const *p = getenv("TMP");
if (p == nullptr)
{
p = getenv("TEMP");
}
if (p != nullptr)
{
if (isadirectory(p))
{
g_temp_dir = p;
fix_dirname(g_temp_dir);
}
}
else
{
g_temp_dir.clear();
}
}
static void initvars_restart() // <ins> key init
{
g_record_colors = record_colors_mode::automatic; // use mapfiles in PARs
g_save_release = g_release; // this release number
g_gif87a_flag = false; // turn on GIF89a processing
g_dither_flag = false; // no dithering
g_ask_video = true; // turn on video-prompt flag
g_overwrite_file = false; // don't overwrite
g_sound_flag = SOUNDFLAG_SPEAKER | SOUNDFLAG_BEEP; // sound is on to PC speaker
g_init_batch = batch_modes::NONE; // not in batch mode
g_check_cur_dir = false; // flag to check current dire for files
g_init_save_time = 0; // no auto-save
g_init_mode = -1; // no initial video mode
g_view_window = false; // no view window
g_view_reduction = 4.2F;
g_view_crop = true;
g_virtual_screens = true; // virtual screen modes on
g_final_aspect_ratio = g_screen_aspect;
g_view_y_dots = 0;
g_view_x_dots = g_view_y_dots;
g_keep_aspect_ratio = true; // keep virtual aspect
g_z_scroll = true; // relaxed screen scrolling
g_orbit_delay = 0; // full speed orbits
g_orbit_interval = 1; // plot all orbits
g_debug_flag = debug_flags::none; // debugging flag(s) are off
g_timer_flag = false; // timer flags are off
g_formula_filename = "fractint.frm"; // default formula file
g_formula_name = "";
g_l_system_filename = "fractint.l";
g_l_system_name = "";
g_command_file = "fractint.par";
g_command_name = "";
for (auto &elem : g_command_comment)
{
elem.clear();
}
g_ifs_filename = "fractint.ifs";
g_ifs_name = "";
reset_ifs_defn();
g_random_seed_flag = false; // not a fixed srand() seed
g_random_seed = init_rseed;
g_read_filename = DOTSLASH; // initially current directory
g_show_file = 1;
// next should perhaps be fractal re-init, not just <ins> ?
g_init_cycle_limit = 55; // spin-DAC default speed limit
g_map_set = false; // no map= name active
g_map_specified = false;
g_major_method = Major::breadth_first; // default inverse julia methods
g_inverse_julia_minor_method = Minor::left_first; // default inverse julia methods
g_truecolor = false; // truecolor output flag
g_true_mode = true_color_mode::default_color;
}
static void initvars_fractal() // init vars affecting calculation
{
g_escape_exit = false; // don't disable the "are you sure?" screen
g_user_periodicity_value = 1; // turn on periodicity
g_inside_color = 1; // inside color = blue
g_fill_color = -1; // no special fill color
g_user_biomorph_value = -1; // turn off biomorph flag
g_outside_color = ITER; // outside color = -1 (not used)
g_max_iterations = 150; // initial maxiter
g_user_std_calc_mode = 'g'; // initial solid-guessing
g_stop_pass = 0; // initial guessing stoppass
g_quick_calc = false;
g_close_proximity = 0.01;
g_is_mandelbrot = true; // default formula mand/jul toggle
#ifndef XFRACT
g_user_float_flag = false; // turn off the float flag
#else
g_user_float_flag = true; // turn on the float flag
#endif
g_finite_attractor = false; // disable finite attractor logic
fractype = fractal_type::MANDEL; // initial type Set flag
curfractalspecific = &fractalspecific[0];
initcorners = false;
initparams = false;
g_bail_out = 0; // no user-entered bailout
g_bof_match_book_images = true; // use normal bof initialization to make bof images
g_use_init_orbit = init_orbit_mode::normal;
for (int i = 0; i < MAXPARAMS; i++)
{
g_params[i] = 0.0; // initial parameter values
}
for (int i = 0; i < 3; i++)
{
g_potential_params[i] = 0.0; // initial potential values
}
for (auto &elem : g_inversion)
{
elem = 0.0; // initial invert values
}
g_init_orbit.y = 0.0;
g_init_orbit.x = g_init_orbit.y; // initial orbit values
g_invert = 0;
g_decomp[1] = 0;
g_decomp[0] = g_decomp[1];
g_user_distance_estimator_value = 0;
g_distance_estimator_x_dots = 0;
g_distance_estimator_y_dots = 0;
g_distance_estimator_width_factor = 71;
g_force_symmetry = symmetry_type::NOT_FORCED;
g_x_min = -2.5;
g_x_3rd = g_x_min;
g_x_max = 1.5; // initial corner values
g_y_min = -1.5;
g_y_3rd = g_y_min;
g_y_max = 1.5; // initial corner values
bf_math = bf_math_type::NONE;
g_potential_16bit = false;
g_potential_flag = false;
g_log_map_flag = 0; // no logarithmic palette
set_trig_array(0, "sin"); // trigfn defaults
set_trig_array(1, "sqr");
set_trig_array(2, "sinh");
set_trig_array(3, "cosh");
if (g_iteration_ranges_len)
{
g_iteration_ranges.clear();
g_iteration_ranges_len = 0;
}
g_use_center_mag = true; // use center-mag, not corners
g_color_state = 0;
g_colors_preloaded = false;
g_color_cycle_range_lo = 1;
g_color_cycle_range_hi = 255; // color cycling default range
g_orbit_delay = 0; // full speed orbits
g_orbit_interval = 1; // plot all orbits
g_keep_screen_coords = false;
g_draw_mode = 'r'; // passes=orbits draw mode
g_set_orbit_corners = false;
g_orbit_corner_min_x = curfractalspecific->xmin;
g_orbit_corner_max_x = curfractalspecific->xmax;
g_orbit_corner_3_x = curfractalspecific->xmin;
g_orbit_corner_min_y = curfractalspecific->ymin;
g_orbit_corner_max_y = curfractalspecific->ymax;
g_orbit_corner_3_y = curfractalspecific->ymin;
g_math_tol[0] = 0.05;
g_math_tol[1] = 0.05;
g_display_3d = display_3d_modes::NONE; // 3D display is off
g_overlay_3d = false; // 3D overlay is off
g_old_demm_colors = false;
g_bail_out_test = bailouts::Mod;
floatbailout = fpMODbailout;
longbailout = asmlMODbailout;
bignumbailout = bnMODbailout;
bigfltbailout = bfMODbailout;
g_new_bifurcation_functions_loaded = false; // for old bifs
g_julibrot_x_min = -.83;
g_julibrot_y_min = -.25;
g_julibrot_x_max = -.83;
g_julibrot_y_max = .25;
g_julibrot_origin_fp = 8;
g_julibrot_height_fp = 7;
g_julibrot_width_fp = 10;
g_julibrot_dist_fp = 24;
g_eyes_fp = 2.5F;
g_julibrot_depth_fp = 8;
g_new_orbit_type = fractal_type::JULIA;
g_julibrot_z_dots = 128;
initvars_3d();
g_base_hertz = 440; // basic hertz rate
#ifndef XFRACT
g_fm_volume = 63; // full volume on soundcard o/p
g_hi_attenuation = 0; // no attenuation of hi notes
g_fm_attack = 5; // fast attack
g_fm_decay = 10; // long decay
g_fm_sustain = 13; // fairly high sustain level
g_fm_release = 5; // short release
g_fm_wavetype = 0; // sin wave
g_polyphony = 0; // no polyphony
for (int i = 0; i <= 11; i++)
{
g_scale_map[i] = i+1; // straight mapping of notes in octave
}
#endif
}
static void initvars_3d() // init vars affecting 3d
{
g_raytrace_format = raytrace_formats::none;
g_brief = false;
SPHERE = FALSE;
g_preview = false;
g_show_box = false;
g_converge_x_adjust = 0;
g_converge_y_adjust = 0;
g_eye_separation = 0;
g_glasses_type = 0;
g_preview_factor = 20;
g_red_crop_left = 4;
g_red_crop_right = 0;
g_blue_crop_left = 0;
g_blue_crop_right = 4;
g_red_bright = 80;
g_blue_bright = 100;
g_transparent_color_3d[1] = 0;
g_transparent_color_3d[0] = g_transparent_color_3d[1]; // no min/max transparency
set_3d_defaults();
}
static void reset_ifs_defn()
{
if (!g_ifs_definition.empty())
{
g_ifs_definition.clear();
}
}
// mode = 0 command line @filename
// 1 sstools.ini
// 2 <@> command after startup
// 3 command line @filename/setname
static int cmdfile(FILE *handle, cmd_file mode)
{
// note that cmdfile could be open as text OR as binary
// binary is used in @ command processing for reasonable speed note/point
int i;
int lineoffset = 0;
int changeflag = 0; // &1 fractal stuff chgd, &2 3d stuff chgd
char linebuf[513];
char cmdbuf[10000] = { 0 };
if (mode == cmd_file::AT_AFTER_STARTUP || mode == cmd_file::AT_CMD_LINE_SET_NAME)
{
while ((i = getc(handle)) != '{' && i != EOF)
{
}
for (auto &elem : g_command_comment)
{
elem.clear();
}
}
linebuf[0] = 0;
while (next_command(cmdbuf, 10000, handle, linebuf, &lineoffset, mode) > 0)
{
if ((mode == cmd_file::AT_AFTER_STARTUP || mode == cmd_file::AT_CMD_LINE_SET_NAME) && strcmp(cmdbuf, "}") == 0)
{
break;
}
i = cmdarg(cmdbuf, mode);
if (i == CMDARG_ERROR)
{
break;
}
changeflag |= i;
}
fclose(handle);
if (changeflag & CMDARG_FRACTAL_PARAM)
{
backwards_v18();
backwards_v19();
backwards_v20();
}
return changeflag;
}
static int next_command(
char *cmdbuf,
int maxlen,
FILE *handle,
char *linebuf,
int *lineoffset,
cmd_file mode)
{
int cmdlen = 0;
char *lineptr;
lineptr = linebuf + *lineoffset;
while (1)
{
while (*lineptr <= ' ' || *lineptr == ';')
{
if (cmdlen) // space or ; marks end of command
{
cmdbuf[cmdlen] = 0;
*lineoffset = (int)(lineptr - linebuf);
return cmdlen;
}
while (*lineptr && *lineptr <= ' ')
{
++lineptr; // skip spaces and tabs
}
if (*lineptr == ';' || *lineptr == 0)
{
if (*lineptr == ';'
&& (mode == cmd_file::AT_AFTER_STARTUP || mode == cmd_file::AT_CMD_LINE_SET_NAME)
&& (g_command_comment[0].empty() || g_command_comment[1].empty() ||
g_command_comment[2].empty() || g_command_comment[3].empty()))
{
// save comment
while (*(++lineptr)
&& (*lineptr == ' ' || *lineptr == '\t'))
{
}
if (*lineptr)
{
if ((int)strlen(lineptr) >= MAXCMT)
{
*(lineptr+MAXCMT-1) = 0;
}
for (auto &elem : g_command_comment)
{
if (elem.empty())
{
elem = lineptr;
break;
}
}
}
}
if (next_line(handle, linebuf, mode))
{
return -1; // eof
}
lineptr = linebuf; // start new line
}
}
if (*lineptr == '\\' // continuation onto next line?
&& *(lineptr+1) == 0)
{
if (next_line(handle, linebuf, mode))
{
argerror(cmdbuf); // missing continuation
return -1;
}
lineptr = linebuf;
while (*lineptr && *lineptr <= ' ')
{
++lineptr; // skip white space @ start next line
}
continue; // loop to check end of line again
}
cmdbuf[cmdlen] = *(lineptr++); // copy character to command buffer
if (++cmdlen >= maxlen) // command too long?
{
argerror(cmdbuf);
return -1;
}
}
}
static bool next_line(FILE *handle, char *linebuf, cmd_file mode)
{
int toolssection;
char tmpbuf[11];
toolssection = 0;
while (file_gets(linebuf, 512, handle) >= 0)
{
if (mode == cmd_file::SSTOOLS_INI && linebuf[0] == '[') // check for [fractint]
{
#ifndef XFRACT
strncpy(tmpbuf, &linebuf[1], 9);
tmpbuf[9] = 0;
strlwr(tmpbuf);
toolssection = strncmp(tmpbuf, "fractint]", 9);
#else
strncpy(tmpbuf, &linebuf[1], 10);
tmpbuf[10] = 0;
strlwr(tmpbuf);
toolssection = strncmp(tmpbuf, "xfractint]", 10);
#endif
continue; // skip tools section heading
}
if (toolssection == 0)
{
return false;
}
}
return true;
}
/*
cmdarg(string,mode) processes a single command-line/command-file argument
return:
-1 error, >= 0 ok
if ok, return value:
| 1 means fractal parm has been set
| 2 means 3d parm has been set
| 4 means 3d=yes specified
| 8 means reset specified
*/
#define NONNUMERIC -32767
int cmdarg(char *curarg, cmd_file mode) // process a single argument
{
int valuelen = 0; // length of value
int numval = 0; // numeric value of arg
char charval[16] = { 0 }; // first character of arg
int yesnoval[16] = { 0 }; // 0 if 'n', 1 if 'y', -1 if not
double ftemp = 0.0;
char *argptr2 = nullptr;
int totparms = 0; // # of / delimited parms
int intparms = 0; // # of / delimited ints
int floatparms = 0; // # of / delimited floats
int intval[64] = { 0 }; // pre-parsed integer parms
double floatval[16] = { 0.0 }; // pre-parsed floating parms
char const *floatvalstr[16]; // pointers to float vals
char tmpc = 0;
int lastarg = 0;
double Xctr = 0.0;
double Yctr = 0.0;
double Xmagfactor = 0.0;
double Rotation = 0.0;
double Skew = 0.0;
LDBL Magnification = 0.0;
bf_t bXctr;
bf_t bYctr;
char *argptr = curarg;
while (*argptr)
{
// convert to lower case
if (*argptr >= 'A' && *argptr <= 'Z')
{
*argptr += 'a' - 'A';
}
else if (*argptr == '=')
{
// don't convert colors=value or comment=value
if ((strncmp(curarg, "colors=", 7) == 0) || (strncmp(curarg, "comment", 7) == 0))
{
break;
}
}
++argptr;
}
int j;
char *value = strchr(&curarg[1], '=');
if (value != nullptr)
{
j = (int)((value++) - curarg);
if (j > 1 && curarg[j-1] == ':')
{
--j; // treat := same as =
}
}
else
{
j = (int) strlen(curarg);
value = curarg + j;
}
if (j > 20)
{
argerror(curarg); // keyword too long
return CMDARG_ERROR;
}
std::string const variable(curarg, j);
valuelen = (int) strlen(value); // note value's length
charval[0] = value[0]; // first letter of value
yesnoval[0] = -1; // note yes|no value
if (charval[0] == 'n')
{
yesnoval[0] = 0;
}
if (charval[0] == 'y')
{
yesnoval[0] = 1;
}
argptr = value;
floatparms = 0;
intparms = floatparms;
totparms = intparms;
numval = totparms;
while (*argptr) // count and pre-parse parms
{
long ll;
lastarg = 0;
argptr2 = strchr(argptr, '/');
if (argptr2 == nullptr) // find next '/'
{
argptr2 = argptr + strlen(argptr);
*argptr2 = '/';
lastarg = 1;
}
if (totparms == 0)
{
numval = NONNUMERIC;
}
if (totparms < 16)
{
charval[totparms] = *argptr; // first letter of value
if (charval[totparms] == 'n')
{
yesnoval[totparms] = 0;
}
if (charval[totparms] == 'y')
{
yesnoval[totparms] = 1;
}
}
char next = 0;
if (sscanf(argptr, "%c%c", &next, &tmpc) > 0 // NULL entry
&& (next == '/' || next == '=') && tmpc == '/')
{
j = 0;
++floatparms;
++intparms;
if (totparms < 16)
{
floatval[totparms] = j;
floatvalstr[totparms] = "0";
}
if (totparms < 64)
{
intval[totparms] = j;
}
if (totparms == 0)
{
numval = j;
}
}
else if (sscanf(argptr, "%ld%c", &ll, &tmpc) > 0 // got an integer
&& tmpc == '/') // needs a long int, ll, here for lyapunov
{
++floatparms;
++intparms;
if (totparms < 16)
{
floatval[totparms] = ll;
floatvalstr[totparms] = argptr;
}
if (totparms < 64)
{
intval[totparms] = (int) ll;
}
if (totparms == 0)
{
numval = (int) ll;
}
}
#ifndef XFRACT
else if (sscanf(argptr, "%lg%c", &ftemp, &tmpc) > 0 // got a float
#else
else if (sscanf(argptr, "%lf%c", &ftemp, &tmpc) > 0 // got a float
#endif
&& tmpc == '/')
{
++floatparms;
if (totparms < 16)
{
floatval[totparms] = ftemp;
floatvalstr[totparms] = argptr;
}
}
// using arbitrary precision and above failed
else if (((int) strlen(argptr) > 513) // very long command
|| (totparms > 0 && floatval[totparms-1] == FLT_MAX
&& totparms < 6)
|| isabigfloat(argptr))
{
++floatparms;
floatval[totparms] = FLT_MAX;
floatvalstr[totparms] = argptr;
}
++totparms;
argptr = argptr2; // on to the next
if (lastarg)
{
*argptr = 0;
}
else
{
++argptr;
}
}
if (mode != cmd_file::AT_AFTER_STARTUP || g_debug_flag == debug_flags::allow_init_commands_anytime)
{
// these commands are allowed only at startup
if (variable == "batch") // batch=?
{
if (yesnoval[0] < 0)
{
goto badarg;
}
#ifdef XFRACT
g_init_mode = yesnoval[0] ? 0 : -1; // skip credits for batch mode
#endif