1 /*
2         Various routines that prompt for things.
3 */
4 
5 #include <string.h>
6 #include <ctype.h>
7 #ifdef   XFRACT
8 #ifndef  __386BSD__
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #endif
12 #endif
13 #ifdef __TURBOC__
14 #include <alloc.h>
15 #elif defined(__APPLE__)
16 #include <malloc/malloc.h>
17 #elif !defined(BIG_ANSI_C)
18 #include <malloc.h>
19 #endif
20 
21   /* see Fractint.c for a description of the "include"  hierarchy */
22 #include "port.h"
23 #include "prototyp.h"
24 #include "fractype.h"
25 #include "helpdefs.h"
26 
27 #ifdef __hpux
28 #include <sys/param.h>
29 #define getwd(a) getcwd(a,MAXPATHLEN)
30 #endif
31 
32 #ifdef __SVR4
33 #include <sys/param.h>
34 #define getwd(a) getcwd(a,MAXPATHLEN)
35 #endif
36 
37 /* Routines used in prompts2.c */
38 
39    int prompt_checkkey(int curkey);
40    int prompt_checkkey_scroll(int curkey);
41    long get_file_entry(int,char *,char *,char *,char *);
42 
43 /* Routines in this module      */
44 
45 int prompt_valuestring(char *buf,struct fullscreenvalues *val);
46 static  int input_field_list(int attr,char *fld,int vlen,char **list,int llen,
47                              int row,int col,int (*checkkey)(int));
48 static  int select_fracttype(int t);
49 static  int sel_fractype_help(int curkey, int choice);
50         int select_type_params(int newfractype,int oldfractype);
51         void set_default_parms(void);
52 static  long gfe_choose_entry(int,char *,char *,char *);
53 static  int check_gfe_key(int curkey,int choice);
54 static  void load_entry_text(FILE *entfile,char far *buf,int maxlines, int startrow, int startcol);
55 static  void format_parmfile_line(int,char *);
56 static  int get_light_params(void );
57 static  int check_mapfile(void );
58 static  int get_funny_glasses_params(void );
59 
60 /* fullscreen_choice options */
61 #define CHOICEHELP      4
62 
63 #define GETFORMULA 0
64 #define GETLSYS    1
65 #define GETIFS     2
66 #define GETPARM    3
67 
68 static char funnyglasses_map_name[MAX_NAME];
69 char ifsmask[MAX_NAME]     = {"*.ifs"};
70 char formmask[MAX_NAME]    = {"*.frm"};
71 char lsysmask[MAX_NAME]    = {"*.l"};
72 char Glasses1Map[MAX_NAME] = "glasses1.map";
73 char MAP_name[FILE_MAX_DIR] = "";
74 int  mapset = 0;
75 int julibrot;   /* flag for julibrot */
76 
77 /* --------------------------------------------------------------------- */
78 
79 int promptfkeys;
80 
81    /* These need to be global because F6 exits fullscreen_prompt() */
82 int scroll_row_status;    /* will be set to first line of extra info to
83                              be displayed ( 0 = top line) */
84 int scroll_column_status; /* will be set to first column of extra info to
85                              be displayed ( 0 = leftmost column )*/
86 
fullscreen_prompt(char far * hdg,int numprompts,char far ** prompts,struct fullscreenvalues * values,int fkeymask,char far * extrainfo)87 int fullscreen_prompt(  /* full-screen prompting routine */
88         char far *hdg,          /* heading, lines separated by \n */
89         int numprompts,         /* there are this many prompts (max) */
90         char far **prompts,     /* array of prompting pointers */
91         struct fullscreenvalues *values, /* array of values */
92         int fkeymask,           /* bit n on if Fn to cause return */
93         char far *extrainfo     /* extra info box to display, \n separated */
94         )
95 {
96    char far *hdgscan;
97    int titlelines,titlewidth,titlerow;
98    int maxpromptwidth,maxfldwidth,maxcomment;
99    int boxrow,boxlines;
100    int boxcol,boxwidth;
101    int extralines,extrawidth,extrarow;
102    int instrrow;
103    int promptrow,promptcol,valuecol;
104    int curchoice = 0;
105    int done, i, j;
106    int anyinput;
107    int savelookatmouse;
108    int curtype, curlen;
109    char buf[81];
110 
111       /* scrolling related variables */
112    FILE * scroll_file = NULL;     /* file with extrainfo entry to scroll   */
113    long scroll_file_start = 0;    /* where entry starts in scroll_file     */
114    int in_scrolling_mode = 0;     /* will be 1 if need to scroll extrainfo */
115    int lines_in_entry = 0;        /* total lines in entry to be scrolled   */
116    int vertical_scroll_limit = 0; /* don't scroll down if this is top line */
117    int widest_entry_line = 0;     /* length of longest line in entry       */
118    int rewrite_extrainfo = 0;     /* if 1: rewrite extrainfo to text box   */
119    char blanks[78];               /* used to clear text box                */
120 
121 static FCODE instr1[]  = {"Use " UPARR1 " and " DNARR1 " to select values to change"};
122 static FCODE instr2a[]  = {"Type in replacement value for selected field"};
123 static FCODE instr2b[]  = {"Use " LTARR1 " or " RTARR1 " to change value of selected field"};
124 static FCODE instr3a[] = {"Press ENTER when finished (or ESCAPE to back out)"};
125 static FCODE instr3b[] = {"Press ENTER when finished, ESCAPE to back out, or "FK_F1" for help"};
126 
127 static FCODE instr0[] = {"No changeable parameters;"};
128 static FCODE instr0a[] = {"Press ENTER to exit"};
129 static FCODE instr0b[] = {"Press ENTER to exit, ESC to back out, "FK_F1" for help"};
130 
131    savelookatmouse = lookatmouse;
132    lookatmouse = 0;
133    promptfkeys = fkeymask;
134    memset(blanks,' ',77);   /* initialize string of blanks */
135    blanks[77] = (char) 0;
136 
137       /* If applicable, open file for scrolling extrainfo. The function
138          find_file_item() opens the file and sets the file pointer to the
139          beginning of the entry.
140       */
141 
142    if((fractype == FORMULA || fractype == FFORMULA) && extrainfo && *extrainfo) {
143       find_file_item(FormFileName, FormName, &scroll_file, 1);
144       in_scrolling_mode = 1;
145       scroll_file_start = ftell(scroll_file);
146    }
147 
148    else if(fractype == LSYSTEM && extrainfo && *extrainfo) {
149       find_file_item(LFileName, LName, &scroll_file, 2);
150       in_scrolling_mode = 1;
151       scroll_file_start = ftell(scroll_file);
152    }
153 
154    else if((fractype == IFS || fractype == IFS3D) && extrainfo && *extrainfo) {
155       find_file_item(IFSFileName, IFSName, &scroll_file, 3);
156       in_scrolling_mode = 1;
157       scroll_file_start = ftell(scroll_file);
158    }
159 
160       /* initialize widest_entry_line and lines_in_entry */
161    if(in_scrolling_mode && scroll_file != NULL) {
162       int comment = 0;
163       int c = 0;
164       int widthct = 0;
165       while((c = fgetc(scroll_file)) != EOF && c != '\032') {
166          if(c == ';')
167             comment = 1;
168          else if(c == '\n') {
169             comment = 0;
170             lines_in_entry++;
171             widthct =  -1;
172          }
173          else if (c == '\t')
174             widthct += 7 - widthct % 8;
175          else if ( c == '\r')
176             continue;
177          if(++widthct > widest_entry_line)
178             widest_entry_line = widthct;
179          if (c == '}' && !comment) {
180             lines_in_entry++;
181             break;
182          }
183       }
184       if(c == EOF || c == '\032') { /* should never happen */
185          fclose(scroll_file);
186          in_scrolling_mode = 0;
187       }
188    }
189 
190 
191 
192    helptitle();                        /* clear screen, display title line  */
193    setattr(1,0,C_PROMPT_BKGRD,24*80);  /* init rest of screen to background */
194 
195 
196    hdgscan = hdg;                      /* count title lines, find widest */
197    i = titlewidth = 0;
198    titlelines = 1;
199    while (*hdgscan) {
200       if (*(hdgscan++) == '\n') {
201          ++titlelines;
202          i = -1;
203       }
204       if (++i > titlewidth)
205          titlewidth = i;
206    }
207    extralines = extrawidth = i = 0;
208    if ((hdgscan = extrainfo) != 0) {
209       if (*hdgscan == 0)
210          extrainfo = NULL;
211       else { /* count extra lines, find widest */
212          extralines = 3;
213          while (*hdgscan) {
214             if (*(hdgscan++) == '\n') {
215                if (extralines + numprompts + titlelines >= 20) {
216                    *hdgscan = 0; /* full screen, cut off here */
217                    break;
218                }
219                ++extralines;
220                i = -1;
221             }
222             if (++i > extrawidth)
223                extrawidth = i;
224          }
225       }
226    }
227 
228       /* if entry fits in available space, shut off scrolling */
229    if(in_scrolling_mode && scroll_row_status == 0
230              && lines_in_entry == extralines - 2
231              && scroll_column_status == 0
232              && far_strchr(extrainfo, '\021') == NULL) {
233       in_scrolling_mode = 0;
234       fclose(scroll_file);
235       scroll_file = NULL;
236    }
237 
238       /*initialize vertical scroll limit. When the top line of the text
239         box is the vertical scroll limit, the bottom line is the end of the
240         entry, and no further down scrolling is necessary.
241       */
242    if (in_scrolling_mode)
243       vertical_scroll_limit = lines_in_entry - (extralines - 2);
244 
245    /* work out vertical positioning */
246    i = numprompts + titlelines + extralines + 3; /* total rows required */
247    j = (25 - i) / 2;                   /* top row of it all when centered */
248    j -= j / 4;                         /* higher is better if lots extra */
249    boxlines = numprompts;
250    titlerow = 1 + j;
251    promptrow = boxrow = titlerow + titlelines;
252    if (titlerow > 2) {                 /* room for blank between title & box? */
253       --titlerow;
254       --boxrow;
255       ++boxlines;
256       }
257    instrrow = boxrow+boxlines;
258    if (instrrow + 3 + extralines < 25) {
259       ++boxlines;    /* blank at bottom of box */
260       ++instrrow;
261       if (instrrow + 3 + extralines < 25)
262          ++instrrow; /* blank before instructions */
263       }
264    extrarow = instrrow + 2;
265    if (numprompts > 1) /* 3 instructions lines */
266       ++extrarow;
267    if (extrarow + extralines < 25)
268       ++extrarow;
269 
270    if(in_scrolling_mode)  /* set box to max width if in scrolling mode */
271       extrawidth = 76;
272 
273    /* work out horizontal positioning */
274    maxfldwidth = maxpromptwidth = maxcomment = anyinput = 0;
275    for (i = 0; i < numprompts; i++) {
276       if (values[i].type == 'y') {
277          static char *noyes[2] = {s_no,s_yes};
278          values[i].type = 'l';
279          values[i].uval.ch.vlen = 3;
280          values[i].uval.ch.list = noyes;
281          values[i].uval.ch.llen = 2;
282          }
283       j = far_strlen(prompts[i]);
284       if (values[i].type == '*') {
285          if (j > maxcomment)     maxcomment = j;
286          }
287       else {
288          anyinput = 1;
289          if (j > maxpromptwidth) maxpromptwidth = j;
290          j = prompt_valuestring(buf,&values[i]);
291          if (j > maxfldwidth)    maxfldwidth = j;
292          }
293       }
294    boxwidth = maxpromptwidth + maxfldwidth + 2;
295    if (maxcomment > boxwidth) boxwidth = maxcomment;
296    if ((boxwidth += 4) > 80) boxwidth = 80;
297    boxcol = (80 - boxwidth) / 2;       /* center the box */
298    promptcol = boxcol + 2;
299    valuecol = boxcol + boxwidth - maxfldwidth - 2;
300    if (boxwidth <= 76) {               /* make margin a bit wider if we can */
301       boxwidth += 2;
302       --boxcol;
303       }
304    if ((j = titlewidth) < extrawidth)
305       j = extrawidth;
306    if ((i = j + 4 - boxwidth) > 0) {   /* expand box for title/extra */
307       if (boxwidth + i > 80)
308          i = 80 - boxwidth;
309       boxwidth += i;
310       boxcol -= i / 2;
311       }
312    i = (90 - boxwidth) / 20;
313    boxcol    -= i;
314    promptcol -= i;
315    valuecol  -= i;
316 
317    /* display box heading */
318    for (i = titlerow; i < boxrow; ++i)
319       setattr(i,boxcol,C_PROMPT_HI,boxwidth);
320    {
321       char far *hdgline = hdg;
322       /* center each line of heading independently */
323       int i;
324       for(i=0;i<titlelines-1;i++)
325       {
326          char far *next;
327          if((next = far_strchr(hdgline,'\n')) == NULL)
328             break; /* shouldn't happen */
329          *next = '\0';
330          titlewidth = far_strlen(hdgline);
331          textcbase = boxcol + (boxwidth - titlewidth) / 2;
332          putstring(titlerow+i,0,C_PROMPT_HI,hdgline);
333          *next = '\n';
334          hdgline = next+1;
335       }
336         /* add scrolling key message, if applicable */
337       if(in_scrolling_mode) {
338          *(hdgline + 31) = (char) 0;   /* replace the ')' */
339          far_strcat(hdgline, ". CTRL+(direction key) to scroll text.)");
340       }
341 
342       titlewidth = far_strlen(hdgline);
343       textcbase = boxcol + (boxwidth - titlewidth) / 2;
344       putstring(titlerow+i,0,C_PROMPT_HI,hdgline);
345    }
346 
347    /* display extra info */
348    if (extrainfo) {
349 #ifndef XFRACT
350 #define S1 '\xC4'
351 #define S2 "\xC0"
352 #define S3 "\xD9"
353 #define S4 "\xB3"
354 #define S5 "\xDA"
355 #define S6 "\xBF"
356 #else
357 #define S1 '-'
358 #define S2 "+" /* ll corner */
359 #define S3 "+" /* lr corner */
360 #define S4 "|"
361 #define S5 "+" /* ul corner */
362 #define S6 "+" /* ur corner */
363 #endif
364       memset(buf,S1,80); buf[boxwidth-2] = 0;
365       textcbase = boxcol + 1;
366       putstring(extrarow,0,C_PROMPT_BKGRD,buf);
367       putstring(extrarow+extralines-1,0,C_PROMPT_BKGRD,buf);
368       --textcbase;
369       putstring(extrarow,0,C_PROMPT_BKGRD,S5);
370       putstring(extrarow+extralines-1,0,C_PROMPT_BKGRD,S2);
371       textcbase += boxwidth - 1;
372       putstring(extrarow,0,C_PROMPT_BKGRD,S6);
373       putstring(extrarow+extralines-1,0,C_PROMPT_BKGRD,S3);
374 
375       textcbase = boxcol;
376 
377       for (i = 1; i < extralines-1; ++i) {
378          putstring(extrarow+i,0,C_PROMPT_BKGRD,S4);
379          putstring(extrarow+i,boxwidth-1,C_PROMPT_BKGRD,S4);
380       }
381       textcbase += (boxwidth - extrawidth) / 2;
382       putstring(extrarow+1,0,C_PROMPT_TEXT,extrainfo);
383    }
384 
385    textcbase = 0;
386 
387    /* display empty box */
388    for (i = 0; i < boxlines; ++i)
389       setattr(boxrow+i,boxcol,C_PROMPT_LO,boxwidth);
390 
391    /* display initial values */
392    for (i = 0; i < numprompts; i++) {
393       putstring(promptrow+i, promptcol, C_PROMPT_LO, prompts[i]);
394       prompt_valuestring(buf,&values[i]);
395       putstring(promptrow+i, valuecol, C_PROMPT_LO, buf);
396    }
397 
398 
399    if (!anyinput) {
400       putstringcenter(instrrow++,0,80,C_PROMPT_BKGRD,
401         instr0);
402       putstringcenter(instrrow,0,80,C_PROMPT_BKGRD,
403         (helpmode > 0) ? instr0b : instr0a);
404       movecursor(25,80);
405       textcbase = 2;
406       for(;;) {
407          if(rewrite_extrainfo) {
408             rewrite_extrainfo = 0;
409             fseek(scroll_file, scroll_file_start, SEEK_SET);
410             load_entry_text(scroll_file, extrainfo, extralines - 2,
411                         scroll_row_status, scroll_column_status);
412             for(i=1; i <= extralines - 2; i++)
413                putstring(extrarow+i,0,C_PROMPT_TEXT,blanks);
414             putstring(extrarow+1,0,C_PROMPT_TEXT,extrainfo);
415          }
416         while (!keypressed()) { }
417         done = getakey();
418         switch(done) {
419             case ESC:
420                done = -1;
421             case ENTER:
422             case ENTER_2:
423                goto fullscreen_exit;
424             case DOWN_ARROW_2:    /* scrolling key - down one row */
425                if(in_scrolling_mode && scroll_row_status < vertical_scroll_limit) {
426                   scroll_row_status++;
427                   rewrite_extrainfo = 1;
428                }
429                break;
430             case UP_ARROW_2:      /* scrolling key - up one row */
431                if(in_scrolling_mode && scroll_row_status > 0) {
432                   scroll_row_status--;
433                   rewrite_extrainfo = 1;
434               }
435               break;
436             case LEFT_ARROW_2:    /* scrolling key - left one column */
437                if(in_scrolling_mode && scroll_column_status > 0) {
438                   scroll_column_status--;
439                   rewrite_extrainfo = 1;
440                }
441                break;
442             case RIGHT_ARROW_2:   /* scrolling key - right one column */
443                if(in_scrolling_mode && far_strchr(extrainfo, '\021') != NULL) {
444                   scroll_column_status++;
445                   rewrite_extrainfo = 1;
446                }
447                break;
448             case CTL_PAGE_DOWN:   /* scrolling key - down one screen */
449                if(in_scrolling_mode && scroll_row_status < vertical_scroll_limit) {
450                   scroll_row_status += extralines - 2;
451                   if(scroll_row_status > vertical_scroll_limit)
452                      scroll_row_status = vertical_scroll_limit;
453                   rewrite_extrainfo = 1;
454                }
455                break;
456             case CTL_PAGE_UP:     /* scrolling key - up one screen */
457                if(in_scrolling_mode && scroll_row_status > 0) {
458                   scroll_row_status -= extralines - 2;
459                   if(scroll_row_status < 0)
460                      scroll_row_status = 0;
461                   rewrite_extrainfo = 1;
462                }
463                break;
464             case CTL_END:         /* scrolling key - to end of entry */
465                if(in_scrolling_mode) {
466                   scroll_row_status = vertical_scroll_limit;
467                   scroll_column_status = 0;
468                   rewrite_extrainfo = 1;
469                }
470                break;
471             case CTL_HOME:        /* scrolling key - to beginning of entry */
472                if(in_scrolling_mode) {
473                   scroll_row_status = scroll_column_status = 0;
474                   rewrite_extrainfo = 1;
475                }
476                break;
477             case F2:
478             case F3:
479             case F4:
480             case F5:
481             case F6:
482             case F7:
483             case F8:
484             case F9:
485             case F10:
486                if (promptfkeys & (1<<(done+1-F1)) )
487                   goto fullscreen_exit;
488          }
489       }
490    }
491 
492 
493    /* display footing */
494    if (numprompts > 1)
495       putstringcenter(instrrow++,0,80,C_PROMPT_BKGRD,instr1);
496    putstringcenter(instrrow+1,0,80,C_PROMPT_BKGRD,
497          (helpmode > 0) ? instr3b : instr3a);
498 
499    done = 0;
500    while (values[curchoice].type == '*') ++curchoice;
501 
502    while (!done) {
503       if(rewrite_extrainfo) {
504          j = textcbase;
505          textcbase = 2;
506          fseek(scroll_file, scroll_file_start, SEEK_SET);
507          load_entry_text(scroll_file, extrainfo, extralines - 2,
508                              scroll_row_status, scroll_column_status);
509          for(i=1; i <= extralines - 2; i++)
510             putstring(extrarow+i,0,C_PROMPT_TEXT,blanks);
511          putstring(extrarow+1,0,C_PROMPT_TEXT,extrainfo);
512          textcbase = j;
513       }
514 
515       curtype = values[curchoice].type;
516       curlen = prompt_valuestring(buf,&values[curchoice]);
517       if(!rewrite_extrainfo)
518          putstringcenter(instrrow,0,80,C_PROMPT_BKGRD,
519                    (curtype == 'l') ? instr2b : instr2a);
520       else
521          rewrite_extrainfo = 0;
522       putstring(promptrow+curchoice,promptcol,C_PROMPT_HI,prompts[curchoice]);
523 
524       if (curtype == 'l') {
525          i = input_field_list(
526                 C_PROMPT_CHOOSE, buf, curlen,
527                 values[curchoice].uval.ch.list, values[curchoice].uval.ch.llen,
528                 promptrow+curchoice,valuecol, in_scrolling_mode ? prompt_checkkey_scroll : prompt_checkkey);
529          for (j = 0; j < values[curchoice].uval.ch.llen; ++j)
530             if (strcmp(buf,values[curchoice].uval.ch.list[j]) == 0) break;
531          values[curchoice].uval.ch.val = j;
532          }
533       else {
534          j = 0;
535          if (curtype == 'i') j = 3;
536          if (curtype == 'L') j = 3;
537          if (curtype == 'd') j = 5;
538          if (curtype == 'D') j = 7;
539          if (curtype == 'f') j = 1;
540          i = input_field(j, C_PROMPT_INPUT, buf, curlen,
541                 promptrow+curchoice,valuecol, in_scrolling_mode ? prompt_checkkey_scroll : prompt_checkkey);
542          switch (values[curchoice].type) {
543             case 'd':
544             case 'D':
545                values[curchoice].uval.dval = atof(buf);
546                break;
547             case 'f':
548                values[curchoice].uval.dval = atof(buf);
549                roundfloatd(&values[curchoice].uval.dval);
550                break;
551             case 'i':
552                values[curchoice].uval.ival = atoi(buf);
553                break;
554             case 'L':
555                values[curchoice].uval.Lval = atol(buf);
556                break;
557             case 's':
558                strncpy(values[curchoice].uval.sval,buf,16);
559                break;
560             default: /* assume 0x100+n */
561                far_strcpy(values[curchoice].uval.sbuf,buf);
562             }
563          }
564 
565       putstring(promptrow+curchoice,promptcol,C_PROMPT_LO,prompts[curchoice]);
566       j = strlen(buf);
567       memset(&buf[j],' ',80-j); buf[curlen] = 0;
568       putstring(promptrow+curchoice, valuecol, C_PROMPT_LO,  buf);
569 
570       switch(i) {
571          case 0:  /* enter  */
572             done = 13;
573             break;
574          case -1: /* escape */
575          case F2:
576          case F3:
577          case F4:
578          case F5:
579          case F6:
580          case F7:
581          case F8:
582          case F9:
583          case F10:
584             done = i;
585             break;
586          case PAGE_UP:
587             curchoice = -1;
588          case DOWN_ARROW:
589             do {
590                if (++curchoice >= numprompts) curchoice = 0;
591                } while (values[curchoice].type == '*');
592             break;
593          case PAGE_DOWN:
594             curchoice = numprompts;
595          case UP_ARROW:
596             do {
597                if (--curchoice < 0) curchoice = numprompts - 1;
598                } while (values[curchoice].type == '*');
599             break;
600          case DOWN_ARROW_2:     /* scrolling key - down one row */
601             if(in_scrolling_mode && scroll_row_status < vertical_scroll_limit) {
602                scroll_row_status++;
603                rewrite_extrainfo = 1;
604             }
605             break;
606          case UP_ARROW_2:       /* scrolling key - up one row */
607             if(in_scrolling_mode && scroll_row_status > 0) {
608                scroll_row_status--;
609                rewrite_extrainfo = 1;
610             }
611             break;
612          case LEFT_ARROW_2:     /*scrolling key - left one column */
613             if(in_scrolling_mode && scroll_column_status > 0) {
614                scroll_column_status--;
615                rewrite_extrainfo = 1;
616             }
617             break;
618          case RIGHT_ARROW_2:    /* scrolling key - right one column */
619             if(in_scrolling_mode && far_strchr(extrainfo, '\021') != NULL) {
620                scroll_column_status++;
621                rewrite_extrainfo = 1;
622             }
623             break;
624          case CTL_PAGE_DOWN:    /* scrolling key - down on screen */
625             if(in_scrolling_mode && scroll_row_status < vertical_scroll_limit) {
626                scroll_row_status += extralines - 2;
627                if(scroll_row_status > vertical_scroll_limit)
628                   scroll_row_status = vertical_scroll_limit;
629                rewrite_extrainfo = 1;
630             }
631             break;
632          case CTL_PAGE_UP:      /* scrolling key - up one screen */
633             if(in_scrolling_mode && scroll_row_status > 0) {
634                  scroll_row_status -= extralines - 2;
635                if(scroll_row_status < 0)
636                   scroll_row_status = 0;
637                rewrite_extrainfo = 1;
638             }
639             break;
640          case CTL_END:          /* scrolling key - go to end of entry */
641             if(in_scrolling_mode) {
642                scroll_row_status = vertical_scroll_limit;
643                scroll_column_status = 0;
644                rewrite_extrainfo = 1;
645             }
646             break;
647          case CTL_HOME:         /* scrolling key - go to beginning of entry */
648             if(in_scrolling_mode) {
649                scroll_row_status = scroll_column_status = 0;
650                rewrite_extrainfo = 1;
651             }
652             break;
653       }
654    }
655 
656 fullscreen_exit:
657    movecursor(25,80);
658    lookatmouse = savelookatmouse;
659    if(scroll_file) {
660       fclose(scroll_file);
661       scroll_file = NULL;
662    }
663    return(done);
664 }
665 
prompt_valuestring(char * buf,struct fullscreenvalues * val)666 int prompt_valuestring(char *buf,struct fullscreenvalues *val)
667 {  /* format value into buf, return field width */
668    int i,ret;
669    switch (val->type) {
670       case 'd':
671          ret = 20;
672          i = 16;    /* cellular needs 16 (was 15)*/
673          for(;;) {
674             sprintf(buf,"%.*g",i,val->uval.dval);
675             if ((int)strlen(buf) <= ret) break;
676             --i;
677             }
678          break;
679       case 'D':
680          if (val->uval.dval<0) { /* We have to round the right way */
681              sprintf(buf,"%ld",(long)(val->uval.dval-.5));
682          }
683          else {
684              sprintf(buf,"%ld",(long)(val->uval.dval+.5));
685          }
686          ret = 20;
687          break;
688       case 'f':
689          sprintf(buf,"%.7g",val->uval.dval);
690          ret = 14;
691          break;
692       case 'i':
693          sprintf(buf,"%d",val->uval.ival);
694          ret = 6;
695          break;
696       case 'L':
697          sprintf(buf,"%ld",val->uval.Lval);
698          ret = 10;
699          break;
700       case '*':
701          *buf = (char)(ret = 0);
702          break;
703       case 's':
704          strncpy(buf,val->uval.sval,16);
705          buf[15] = 0;
706          ret = 15;
707          break;
708       case 'l':
709          strcpy(buf,val->uval.ch.list[val->uval.ch.val]);
710          ret = val->uval.ch.vlen;
711          break;
712       default: /* assume 0x100+n */
713          far_strcpy(buf,val->uval.sbuf);
714          ret = val->type & 0xff;
715       }
716    return ret;
717 }
718 
prompt_checkkey(int curkey)719 int prompt_checkkey(int curkey)
720 {
721    switch(curkey) {
722       case PAGE_UP:
723       case DOWN_ARROW:
724       case PAGE_DOWN:
725       case UP_ARROW:
726          return(curkey);
727       case F2:
728       case F3:
729       case F4:
730       case F5:
731       case F6:
732       case F7:
733       case F8:
734       case F9:
735       case F10:
736          if (promptfkeys & (1<<(curkey+1-F1)) )
737             return(curkey);
738       }
739    return(0);
740 }
741 
prompt_checkkey_scroll(int curkey)742 int prompt_checkkey_scroll(int curkey)
743 {
744    switch(curkey) {
745       case PAGE_UP:
746       case DOWN_ARROW:
747       case DOWN_ARROW_2:
748       case PAGE_DOWN:
749       case UP_ARROW:
750       case UP_ARROW_2:
751       case LEFT_ARROW_2:
752       case RIGHT_ARROW_2:
753       case CTL_PAGE_DOWN:
754       case CTL_PAGE_UP:
755       case CTL_END:
756       case CTL_HOME:
757          return(curkey);
758       case F2:
759       case F3:
760       case F4:
761       case F5:
762       case F6:
763       case F7:
764       case F8:
765       case F9:
766       case F10:
767          if (promptfkeys & (1<<(curkey+1-F1)) )
768             return(curkey);
769       }
770    return(0);
771 }
772 
input_field_list(int attr,char * fld,int vlen,char ** list,int llen,int row,int col,int (* checkkey)(int))773 static int input_field_list(
774         int attr,             /* display attribute */
775         char *fld,            /* display form field value */
776         int vlen,             /* field length */
777         char **list,          /* list of values */
778         int llen,             /* number of entries in list */
779         int row,              /* display row */
780         int col,              /* display column */
781         int (*checkkey)(int)  /* routine to check non data keys, or NULL */
782         )
783 {
784    int initval,curval;
785    char buf[81];
786    int curkey;
787    int i, j;
788    int ret,savelookatmouse;
789    savelookatmouse = lookatmouse;
790    lookatmouse = 0;
791    for (initval = 0; initval < llen; ++initval)
792       if (strcmp(fld,list[initval]) == 0) break;
793    if (initval >= llen) initval = 0;
794    curval = initval;
795    ret = -1;
796    for(;;) {
797       strcpy(buf,list[curval]);
798       i = strlen(buf);
799       while (i < vlen)
800          buf[i++] = ' ';
801       buf[vlen] = 0;
802       putstring(row,col,attr,buf);
803       curkey = keycursor(row,col); /* get a keystroke */
804       switch (curkey) {
805          case ENTER:
806          case ENTER_2:
807             ret = 0;
808             goto inpfldl_end;
809          case ESC:
810             goto inpfldl_end;
811          case RIGHT_ARROW:
812             if (++curval >= llen)
813                curval = 0;
814             break;
815          case LEFT_ARROW:
816             if (--curval < 0)
817                curval = llen - 1;
818             break;
819          case F5:
820             curval = initval;
821             break;
822          default:
823             if (nonalpha(curkey)) {
824                if (checkkey && (ret = (*checkkey)(curkey)) != 0)
825                   goto inpfldl_end;
826                break;                                /* non alphanum char */
827                }
828             j = curval;
829             for (i = 0; i < llen; ++i) {
830                if (++j >= llen)
831                   j = 0;
832                if ( (*list[j] & 0xdf) == (curkey & 0xdf)) {
833                   curval = j;
834                   break;
835                   }
836                }
837          }
838       }
839 inpfldl_end:
840    strcpy(fld,list[curval]);
841    lookatmouse = savelookatmouse;
842    return(ret);
843 }
844 
845 
846 /* --------------------------------------------------------------------- */
847 
848 /* MCP 7-7-91, This is static code, but not called anywhere */
849 #ifdef DELETE_UNUSED_CODE
850 
851 /* compare for sort of type table */
compare(const VOIDPTR i,const VOIDPTR j)852 static int compare(const VOIDPTR i, const VOIDPTR j)
853 {
854    return(strcmp(fractalspecific[(int)*((BYTE*)i)].name,
855                fractalspecific[(int)*((BYTE*)j)].name));
856 }
857 
858 /* --------------------------------------------------------------------- */
859 
clear_line(int row,int start,int stop,int color)860 static void clear_line(int row, int start, int stop, int color) /* clear part of a line */
861 {
862    int col;
863    for(col=start;col<= stop;col++)
864       putstring(row,col,color," ");
865 }
866 
867 #endif
868 
869 /* --------------------------------------------------------------------- */
870 
get_fracttype()871 int get_fracttype()             /* prompt for and select fractal type */
872 {
873    int done,i,oldfractype,t;
874    done = -1;
875    oldfractype = fractype;
876    for(;;) {
877       if ((t = select_fracttype(fractype)) < 0)
878          break;
879       if ((i = select_type_params(t, fractype)) == 0) { /* ok, all done */
880          done = 0;
881          break;
882          }
883       if (i > 0) /* can't return to prior image anymore */
884          done = 1;
885       }
886    if (done < 0)
887       fractype = oldfractype;
888    curfractalspecific = &fractalspecific[fractype];
889    return(done);
890 }
891 
892 struct FT_CHOICE {
893       char name[15];
894       int  num;
895       };
896 static struct FT_CHOICE far **ft_choices; /* for sel_fractype_help subrtn */
897 
select_fracttype(int t)898 static int select_fracttype(int t) /* subrtn of get_fracttype, separated */
899                                    /* so that storage gets freed up      */
900 {
901    static FCODE head1[] = {"Select a Fractal Type"};
902    static FCODE head2[] = {"Select Orbit Algorithm for Julibrot"};
903    static FCODE o_instr[] = {"Press "FK_F2" for a description of the highlighted type"};
904    char instr[sizeof(o_instr)];
905    char head[40];
906    int oldhelpmode;
907    int numtypes, done;
908    int i, j;
909 #define MAXFTYPES 200
910    char tname[40];
911    struct FT_CHOICE far *choices[MAXFTYPES];
912    int attributes[MAXFTYPES];
913 
914    /* steal existing array for "choices" */
915    choices[0] = (struct FT_CHOICE far *)boxy;
916    attributes[0] = 1;
917    for (i = 1; i < MAXFTYPES; ++i) {
918       choices[i] = choices[i-1] + 1;
919       attributes[i] = 1;
920       }
921    ft_choices = &choices[0];
922 
923    /* setup context sensitive help */
924    oldhelpmode = helpmode;
925    helpmode = HELPFRACTALS;
926    far_strcpy(instr,o_instr);
927    if(julibrot)
928       far_strcpy(head,head2);
929    else
930       far_strcpy(head,head1);
931    if (t == IFS3D) t = IFS;
932    i = j = -1;
933    while(fractalspecific[++i].name) {
934       if(julibrot)
935         if (!((fractalspecific[i].flags & OKJB) && *fractalspecific[i].name != '*'))
936            continue;
937       if (fractalspecific[i].name[0] == '*')
938          continue;
939       far_strcpy(choices[++j]->name,fractalspecific[i].name);
940       choices[j]->name[14] = 0; /* safety */
941       choices[j]->num = i;      /* remember where the real item is */
942       }
943    numtypes = j + 1;
944    shell_sort(choices,numtypes,sizeof(char far *),lccompare); /* sort list */
945    j = 0;
946    for (i = 0; i < numtypes; ++i) /* find starting choice in sorted list */
947       if (choices[i]->num == t || choices[i]->num == fractalspecific[t].tofloat)
948          j = i;
949 
950    tname[0] = 0;
951    done = fullscreen_choice(CHOICEHELP+8,head,NULL,instr,numtypes,
952          (char far *far*)choices,attributes,0,0,0,j,NULL,tname,NULL,sel_fractype_help);
953    if (done >= 0) {
954       done = choices[done]->num;
955       if((done == FORMULA || done == FFORMULA) && !strcmp(FormFileName, CommandFile))
956          strcpy(FormFileName, searchfor.frm);
957       if(done == LSYSTEM && !strcmp(LFileName, CommandFile))
958          strcpy(LFileName, searchfor.lsys);
959       if((done == IFS || done == IFS3D) && !strcmp(IFSFileName, CommandFile))
960          strcpy(IFSFileName, searchfor.ifs);
961    }
962 
963 
964    helpmode = oldhelpmode;
965    return(done);
966 }
967 
sel_fractype_help(int curkey,int choice)968 static int sel_fractype_help(int curkey,int choice)
969 {
970    int oldhelpmode;
971    if (curkey == F2) {
972       oldhelpmode = helpmode;
973       helpmode = fractalspecific[(*(ft_choices+choice))->num].helptext;
974       help(0);
975       helpmode = oldhelpmode;
976       }
977    return(0);
978 }
979 
select_type_params(int newfractype,int oldfractype)980 int select_type_params( /* prompt for new fractal type parameters */
981         int newfractype,        /* new fractal type */
982         int oldfractype         /* previous fractal type */
983         )
984 {
985    int ret,oldhelpmode;
986 
987    oldhelpmode = helpmode;
988 sel_type_restart:
989    ret = 0;
990    fractype = newfractype;
991    curfractalspecific = &fractalspecific[fractype];
992 
993    if (fractype == LSYSTEM) {
994       helpmode = HT_LSYS;
995       if (get_file_entry(GETLSYS,"L-System",lsysmask,LFileName,LName) < 0) {
996          ret = 1;
997          goto sel_type_exit;
998          }
999       }
1000    if (fractype == FORMULA || fractype == FFORMULA) {
1001       helpmode = HT_FORMULA;
1002       if (get_file_entry(GETFORMULA,"Formula",formmask,FormFileName,FormName) < 0) {
1003          ret = 1;
1004          goto sel_type_exit;
1005          }
1006       }
1007    if (fractype == IFS || fractype == IFS3D) {
1008       helpmode = HT_IFS;
1009       if (get_file_entry(GETIFS,"IFS",ifsmask,IFSFileName,IFSName) < 0) {
1010         ret = 1;
1011         goto sel_type_exit;
1012         }
1013       }
1014 
1015 /* Added the following to accommodate fn bifurcations.  JCO 7/2/92 */
1016    if(((fractype == BIFURCATION) || (fractype == LBIFURCATION)) &&
1017      !((oldfractype == BIFURCATION) || (oldfractype == LBIFURCATION)))
1018         set_trig_array(0,s_ident);
1019    if(((fractype == BIFSTEWART) || (fractype == LBIFSTEWART)) &&
1020      !((oldfractype == BIFSTEWART) || (oldfractype == LBIFSTEWART)))
1021         set_trig_array(0,s_ident);
1022    if(((fractype == BIFLAMBDA) || (fractype == LBIFLAMBDA)) &&
1023      !((oldfractype == BIFLAMBDA) || (oldfractype == LBIFLAMBDA)))
1024         set_trig_array(0,s_ident);
1025    if(((fractype == BIFEQSINPI) || (fractype == LBIFEQSINPI)) &&
1026      !((oldfractype == BIFEQSINPI) || (oldfractype == LBIFEQSINPI)))
1027         set_trig_array(0,s_sin);
1028    if(((fractype == BIFADSINPI) || (fractype == LBIFADSINPI)) &&
1029      !((oldfractype == BIFADSINPI) || (oldfractype == LBIFADSINPI)))
1030         set_trig_array(0,s_sin);
1031 
1032    /*
1033     * Next assumes that user going between popcorn and popcornjul
1034     * might not want to change function variables
1035     */
1036    if(((fractype    == FPPOPCORN   ) || (fractype    == LPOPCORN   ) ||
1037        (fractype    == FPPOPCORNJUL) || (fractype    == LPOPCORNJUL)) &&
1038      !((oldfractype == FPPOPCORN   ) || (oldfractype == LPOPCORN   ) ||
1039        (oldfractype == FPPOPCORNJUL) || (oldfractype == LPOPCORNJUL)))
1040       set_function_parm_defaults();
1041 
1042    /* set LATOO function defaults */
1043    if(fractype == LATOO && oldfractype != LATOO)
1044    {
1045       set_function_parm_defaults();
1046    }
1047    set_default_parms();
1048 
1049    if (get_fract_params(0) < 0)
1050       if (fractype == FORMULA || fractype == FFORMULA ||
1051           fractype == IFS || fractype == IFS3D ||
1052           fractype == LSYSTEM)
1053          goto sel_type_restart;
1054       else
1055          ret = 1;
1056    else {
1057       if (newfractype != oldfractype) {
1058          invert = 0;
1059          inversion[0] = inversion[1] = inversion[2] = 0;
1060          }
1061       }
1062 
1063 sel_type_exit:
1064    helpmode = oldhelpmode;
1065    return(ret);
1066 
1067 }
1068 
set_default_parms()1069 void set_default_parms()
1070 {
1071    int i,extra;
1072    xxmin = curfractalspecific->xmin;
1073    xxmax = curfractalspecific->xmax;
1074    yymin = curfractalspecific->ymin;
1075    yymax = curfractalspecific->ymax;
1076    xx3rd = xxmin;
1077    yy3rd = yymin;
1078 
1079    if (viewcrop && finalaspectratio != screenaspect)
1080       aspectratio_crop(screenaspect,finalaspectratio);
1081    for (i = 0; i < 4; i++) {
1082       param[i] = curfractalspecific->paramvalue[i];
1083       if (fractype != CELLULAR && fractype != FROTH && fractype != FROTHFP &&
1084           fractype != ANT)
1085          roundfloatd(&param[i]); /* don't round cellular, frothybasin or ant */
1086    }
1087    if((extra=find_extra_param(fractype)) > -1)
1088       for(i=0;i<MAXPARAMS-4;i++)
1089          param[i+4] = moreparams[extra].paramvalue[i];
1090    if(debugflag != 3200)
1091       bf_math = 0;
1092    else if(bf_math)
1093       fractal_floattobf();
1094 }
1095 
1096 #define MAXFRACTALS 25
1097 
build_fractal_list(int fractals[],int * last_val,char * nameptr[])1098 int build_fractal_list(int fractals[], int *last_val, char *nameptr[])
1099 {
1100     int numfractals,i;
1101 
1102     numfractals = 0;
1103     for (i = 0; i < num_fractal_types; i++)
1104     {
1105         if ((fractalspecific[i].flags & OKJB) && *fractalspecific[i].name != '*')
1106         {
1107             fractals[numfractals] = i;
1108             if (i == neworbittype || i == fractalspecific[neworbittype].tofloat)
1109                 *last_val = numfractals;
1110             nameptr[numfractals] = fractalspecific[i].name;
1111             numfractals++;
1112             if (numfractals >= MAXFRACTALS)
1113                 break;
1114         }
1115     }
1116     return (numfractals);
1117 }
1118 
1119 static FCODE v0a[] = {"From cx (real part)"};
1120 static FCODE v1a[] = {"From cy (imaginary part)"};
1121 static FCODE v2a[] = {"To   cx (real part)"};
1122 static FCODE v3a[] = {"To   cy (imaginary part)"};
1123 
1124 /* 4D Mandelbrot */
1125 static FCODE v0b[] = {"From cj (3rd dim)"};
1126 static FCODE v1b[] = {"From ck (4th dim)"};
1127 static FCODE v2b[] = {"To   cj (3rd dim)"};
1128 static FCODE v3b[] = {"To   ck (4th dim)"};
1129 
1130 /* 4D Julia */
1131 static FCODE v0c[] = {"From zj (3rd dim)"};
1132 static FCODE v1c[] = {"From zk (4th dim)"};
1133 static FCODE v2c[] = {"To   zj (3rd dim)"};
1134 static FCODE v3c[] = {"To   zk (4th dim)"};
1135 
1136 static FCODE v4[] = {"Number of z pixels"};
1137 static FCODE v5[] = {"Location of z origin"};
1138 static FCODE v6[] = {"Depth of z"};
1139 static FCODE v7[] = {"Screen height"};
1140 static FCODE v8[] = {"Screen width"};
1141 static FCODE v9[] = {"Distance to Screen"};
1142 static FCODE v10[] = {"Distance between eyes"};
1143 static FCODE v11[] = {"3D Mode"};
1144 char *juli3Doptions[] = {"monocular","lefteye","righteye","red-blue"};
1145 
1146 /* JIIM */
1147 #ifdef RANDOM_RUN
1148 static FCODE JIIMstr1[] = "Breadth first, Depth first, Random Walk, Random Run?";
1149 char *JIIMmethod[] = {"breadth", "depth", "walk", "run"};
1150 #else
1151 static FCODE JIIMstr1[] = "Breadth first, Depth first, Random Walk";
1152 char *JIIMmethod[] = {"breadth", "depth", "walk"};
1153 #endif
1154 static FCODE JIIMstr2[] = "Left first or Right first?";
1155 char *JIIMleftright[] = {"left", "right"};
1156 
1157 /* moved from miscres.c so sizeof structure can be accessed here */
1158 struct trig_funct_lst trigfn[] =
1159 /* changing the order of these alters meaning of *.fra file */
1160 /* maximum 6 characters in function names or recheck all related code */
1161 {
1162 #ifndef XFRACT
1163    {s_sin,   lStkSin,   dStkSin,   mStkSin   },
1164    {s_cosxx, lStkCosXX, dStkCosXX, mStkCosXX },
1165    {s_sinh,  lStkSinh,  dStkSinh,  mStkSinh  },
1166    {s_cosh,  lStkCosh,  dStkCosh,  mStkCosh  },
1167    {s_exp,   lStkExp,   dStkExp,   mStkExp   },
1168    {s_log,   lStkLog,   dStkLog,   mStkLog   },
1169    {s_sqr,   lStkSqr,   dStkSqr,   mStkSqr   },
1170    {s_recip, lStkRecip, dStkRecip, mStkRecip }, /* from recip on new in v16 */
1171    {s_ident, StkIdent,  StkIdent,  StkIdent  },
1172    {s_cos,   lStkCos,   dStkCos,   mStkCos   },
1173    {s_tan,   lStkTan,   dStkTan,   mStkTan   },
1174    {s_tanh,  lStkTanh,  dStkTanh,  mStkTanh  },
1175    {s_cotan, lStkCoTan, dStkCoTan, mStkCoTan },
1176    {s_cotanh,lStkCoTanh,dStkCoTanh,mStkCoTanh},
1177    {s_flip,  lStkFlip,  dStkFlip,  mStkFlip  },
1178    {s_conj,  lStkConj,  dStkConj,  mStkConj  },
1179    {s_zero,  lStkZero,  dStkZero,  mStkZero  },
1180    {s_asin,  lStkASin,  dStkASin,  mStkASin  },
1181    {s_asinh, lStkASinh, dStkASinh, mStkASinh },
1182    {s_acos,  lStkACos,  dStkACos,  mStkACos  },
1183    {s_acosh, lStkACosh, dStkACosh, mStkACosh },
1184    {s_atan,  lStkATan,  dStkATan,  mStkATan  },
1185    {s_atanh, lStkATanh, dStkATanh, mStkATanh },
1186    {s_cabs,  lStkCAbs,  dStkCAbs,  mStkCAbs  },
1187    {s_abs,   lStkAbs,   dStkAbs,   mStkAbs   },
1188    {s_sqrt,  lStkSqrt,  dStkSqrt,  mStkSqrt  },
1189    {s_floor, lStkFloor, dStkFloor, mStkFloor },
1190    {s_ceil,  lStkCeil,  dStkCeil,  mStkCeil  },
1191    {s_trunc, lStkTrunc, dStkTrunc, mStkTrunc },
1192    {s_round, lStkRound, dStkRound, mStkRound },
1193    {s_one,   lStkOne,   dStkOne,   mStkOne   },
1194 #else
1195    {s_sin,   dStkSin,   dStkSin,   dStkSin   },
1196    {s_cosxx, dStkCosXX, dStkCosXX, dStkCosXX },
1197    {s_sinh,  dStkSinh,  dStkSinh,  dStkSinh  },
1198    {s_cosh,  dStkCosh,  dStkCosh,  dStkCosh  },
1199    {s_exp,   dStkExp,   dStkExp,   dStkExp   },
1200    {s_log,   dStkLog,   dStkLog,   dStkLog   },
1201    {s_sqr,   dStkSqr,   dStkSqr,   dStkSqr   },
1202    {s_recip, dStkRecip, dStkRecip, dStkRecip }, /* from recip on new in v16 */
1203    {s_ident, StkIdent,  StkIdent,  StkIdent  },
1204    {s_cos,   dStkCos,   dStkCos,   dStkCos   },
1205    {s_tan,   dStkTan,   dStkTan,   dStkTan   },
1206    {s_tanh,  dStkTanh,  dStkTanh,  dStkTanh  },
1207    {s_cotan, dStkCoTan, dStkCoTan, dStkCoTan },
1208    {s_cotanh,dStkCoTanh,dStkCoTanh,dStkCoTanh},
1209    {s_flip,  dStkFlip,  dStkFlip,  dStkFlip  },
1210    {s_conj,  dStkConj,  dStkConj,  dStkConj  },
1211    {s_zero,  dStkZero,  dStkZero,  dStkZero  },
1212    {s_asin,  dStkASin,  dStkASin,  dStkASin  },
1213    {s_asinh, dStkASinh, dStkASinh, dStkASinh },
1214    {s_acos,  dStkACos,  dStkACos,  dStkACos  },
1215    {s_acosh, dStkACosh, dStkACosh, dStkACosh },
1216    {s_atan,  dStkATan,  dStkATan,  dStkATan  },
1217    {s_atanh, dStkATanh, dStkATanh, dStkATanh },
1218    {s_cabs,  dStkCAbs,  dStkCAbs,  dStkCAbs  },
1219    {s_abs,   dStkAbs,   dStkAbs,   dStkAbs   },
1220    {s_sqrt,  dStkSqrt,  dStkSqrt,  dStkSqrt  },
1221    {s_floor, dStkFloor, dStkFloor, dStkFloor },
1222    {s_ceil,  dStkCeil,  dStkCeil,  dStkCeil  },
1223    {s_trunc, dStkTrunc, dStkTrunc, dStkTrunc },
1224    {s_round, dStkRound, dStkRound, dStkRound },
1225    {s_one,   dStkOne,   dStkOne,   dStkOne   },
1226 #endif
1227 };
1228 
1229 #define NUMTRIGFN  sizeof(trigfn)/sizeof(struct trig_funct_lst)
1230 
1231 const int numtrigfn = NUMTRIGFN;
1232 
1233 /* --------------------------------------------------------------------- */
get_fract_params(int caller)1234 int get_fract_params(int caller)        /* prompt for type-specific parms */
1235 {
1236    char far *v0 = v0a;
1237    char far *v1 = v1a;
1238    char far *v2 = v2a;
1239    char far *v3 = v3a;
1240    char *juliorbitname = NULL;
1241    int i,j,k;
1242    int curtype,numparams,numtrig;
1243    struct fullscreenvalues paramvalues[30];
1244    char far *choices[30];
1245    long oldbailout = 0L, long_i;
1246    int promptnum;
1247    char msg[120];
1248    char *typename, *tmpptr;
1249    char bailoutmsg[50];
1250    int ret = 0;
1251    int oldhelpmode;
1252    char parmprompt[MAXPARAMS][55];
1253    static FCODE t1[] = {"First Function"};
1254    static FCODE t2[] = {"Second Function"};
1255    static FCODE t3[] = {"Third Function"};
1256    static FCODE t4[] = {"Fourth Function"};
1257    static FCODE *trg[] = {t1, t2, t3, t4};
1258    char *filename,*entryname;
1259    FILE *entryfile;
1260    char *trignameptr[NUMTRIGFN];
1261 #ifdef XFRACT
1262    static /* Can't initialize aggregates on the stack */
1263 #endif
1264    char *bailnameptr[] = {s_mod,s_real,s_imag,s_or,s_and,s_manh,s_manr};
1265    struct fractalspecificstuff far *jborbit = NULL;
1266    struct fractalspecificstuff far *savespecific;
1267    int firstparm = 0;
1268    int lastparm  = MAXPARAMS;
1269    double oldparam[MAXPARAMS];
1270    int fkeymask = 0x40;
1271    oldbailout = bailout;
1272    if(fractype==JULIBROT || fractype==JULIBROTFP)
1273       julibrot = 1;
1274    else
1275       julibrot = 0;
1276    curtype = fractype;
1277    if (curfractalspecific->name[0] == '*'
1278      && (i = curfractalspecific->tofloat) != NOFRACTAL  /* FIXED BUG HERE!! */
1279      && fractalspecific[i].name[0] != '*')
1280       curtype = i;
1281    curfractalspecific = &fractalspecific[curtype];
1282    tstack[0] = 0;
1283    if ((i = curfractalspecific->helpformula) < -1) {
1284       if (i == -2) { /* special for formula */
1285          filename = FormFileName;
1286          entryname = FormName;
1287          }
1288       else if (i == -3)  {       /* special for lsystem */
1289          filename = LFileName;
1290          entryname = LName;
1291          }
1292       else if (i == -4)  {       /* special for ifs */
1293          filename = IFSFileName;
1294          entryname = IFSName;
1295          }
1296       else { /* this shouldn't happen */
1297          filename = NULL;
1298          entryname = NULL;
1299       }
1300       if (find_file_item(filename,entryname,&entryfile, -1-i) == 0) {
1301          load_entry_text(entryfile,tstack,17, 0, 0);
1302          fclose(entryfile);
1303          if(fractype == FORMULA || fractype == FFORMULA)
1304            frm_get_param_stuff(entryname); /* no error check, should be okay, from above */
1305          }
1306       }
1307    else if (i >= 0) {
1308       int c,lines;
1309       read_help_topic(i,0,2000,tstack); /* need error handling here ?? */
1310       tstack[2000-i] = 0;
1311       i = j = lines = 0; k = 1;
1312       while ((c = tstack[i++]) != 0) {
1313          /* stop at ctl, blank, or line with col 1 nonblank, max 16 lines */
1314          if (k && c == ' ' && ++k <= 5) { } /* skip 4 blanks at start of line */
1315          else {
1316             if (c == '\n') {
1317                if (k) break; /* blank line */
1318                if (++lines >= 16) break;
1319                k = 1;
1320                }
1321             else if (c < 16) /* a special help format control char */
1322                break;
1323             else {
1324                if (k == 1) /* line starts in column 1 */
1325                   break;
1326                k = 0;
1327                }
1328             tstack[j++] = (char)c;
1329             }
1330          }
1331       while (--j >= 0 && tstack[j] == '\n') { }
1332       tstack[j+1] = 0;
1333       }
1334 gfp_top:
1335    promptnum = 0;
1336    if (julibrot)
1337    {
1338       i = select_fracttype(neworbittype);
1339       if (i < 0)
1340       {
1341          if (ret == 0)
1342             ret = -1;
1343          julibrot = 0;
1344          goto gfp_exit;
1345       }
1346       else
1347          neworbittype = i;
1348       jborbit = &fractalspecific[neworbittype];
1349       juliorbitname = jborbit->name;
1350    }
1351 
1352    if(fractype == FORMULA || fractype == FFORMULA) {
1353       if(uses_p1)  /* set first parameter */
1354          firstparm = 0;
1355       else if(uses_p2)
1356          firstparm = 2;
1357       else if(uses_p3)
1358          firstparm = 4;
1359       else if(uses_p4)
1360          firstparm = 6;
1361       else
1362          firstparm = 8; /* uses_p5 or no parameter */
1363 
1364       if(uses_p5)  /* set last parameter */
1365          lastparm = 10;
1366       else if(uses_p4)
1367          lastparm = 8;
1368       else if(uses_p3)
1369          lastparm = 6;
1370       else if(uses_p2)
1371          lastparm = 4;
1372       else
1373          lastparm = 2; /* uses_p1 or no parameter */
1374    }
1375 
1376    savespecific = curfractalspecific;
1377    if(julibrot)
1378    {
1379       curfractalspecific = jborbit;
1380       firstparm = 2; /* in most case Julibrot does not need first two parms */
1381       if(neworbittype == QUATJULFP     ||   /* all parameters needed */
1382          neworbittype == HYPERCMPLXJFP)
1383       {
1384          firstparm = 0;
1385          lastparm = 4;
1386       }
1387       if(neworbittype == QUATFP        ||   /* no parameters needed */
1388          neworbittype == HYPERCMPLXFP)
1389          firstparm = 4;
1390    }
1391    numparams = 0;
1392    j = 0;
1393    for (i = firstparm; i < lastparm; i++)
1394    {
1395       char tmpbuf[30];
1396       if (!typehasparm(julibrot?neworbittype:fractype,i,parmprompt[j])) {
1397          if(curtype == FORMULA || curtype == FFORMULA)
1398            if(paramnotused(i))
1399               continue;
1400          break;
1401       }
1402       numparams++;
1403       choices[promptnum] = parmprompt[j++];
1404       paramvalues[promptnum].type = 'd';
1405 
1406       if (choices[promptnum][0] == '+')
1407       {
1408          choices[promptnum]++;
1409          paramvalues[promptnum].type = 'D';
1410       }
1411       else if (choices[promptnum][0] == '#')
1412          choices[promptnum]++;
1413       sprintf(tmpbuf,"%.17g",param[i]);
1414       paramvalues[promptnum].uval.dval = atof(tmpbuf);
1415       oldparam[i] = paramvalues[promptnum++].uval.dval;
1416    }
1417 
1418 /* The following is a goofy kludge to make reading in the formula
1419  * parameters work.
1420  */
1421    if(curtype == FORMULA || curtype == FFORMULA)
1422       numparams = lastparm - firstparm;
1423 
1424    numtrig = (curfractalspecific->flags >> 6) & 7;
1425    if(curtype==FORMULA || curtype==FFORMULA ) {
1426       numtrig = maxfn;
1427       }
1428 
1429    i = NUMTRIGFN;
1430    while (--i >= 0)
1431       trignameptr[i] = trigfn[i].name;
1432    for (i = 0; i < numtrig; i++) {
1433       paramvalues[promptnum].type = 'l';
1434       paramvalues[promptnum].uval.ch.val  = trigndx[i];
1435       paramvalues[promptnum].uval.ch.llen = NUMTRIGFN;
1436       paramvalues[promptnum].uval.ch.vlen = 6;
1437       paramvalues[promptnum].uval.ch.list = trignameptr;
1438       choices[promptnum++] = (char far *)trg[i];
1439       }
1440    if (*(typename = curfractalspecific->name) == '*')
1441         ++typename;
1442 
1443    long_i = curfractalspecific->orbit_bailout;
1444 
1445    if( long_i != 0 && curfractalspecific->calctype == StandardFractal &&
1446        (curfractalspecific->flags & BAILTEST) ) {
1447         static FCODE bailteststr[] = {"Bailout Test (mod, real, imag, or, and, manh, manr)"};
1448       paramvalues[promptnum].type = 'l';
1449       paramvalues[promptnum].uval.ch.val  = (int)bailoutest;
1450       paramvalues[promptnum].uval.ch.llen = 7;
1451       paramvalues[promptnum].uval.ch.vlen = 6;
1452       paramvalues[promptnum].uval.ch.list = bailnameptr;
1453       choices[promptnum++] = bailteststr;
1454    }
1455 
1456    if (long_i) {
1457       if (potparam[0] != 0.0 && potparam[2] != 0.0)
1458       {
1459         static FCODE bailpotstr[] = {"Bailout: continuous potential (Y screen) value in use"};
1460          paramvalues[promptnum].type = '*';
1461          choices[promptnum++] = bailpotstr;
1462       }
1463       else
1464       {
1465          static FCODE bailoutstr[] = {"Bailout value (0 means use default)"};
1466          choices[promptnum] = bailoutstr;
1467          paramvalues[promptnum].type = 'L';
1468          paramvalues[promptnum++].uval.Lval = (oldbailout = bailout);
1469          paramvalues[promptnum].type = '*';
1470          tmpptr = typename;
1471          if (usr_biomorph != -1)
1472          {
1473             i = 100;
1474             tmpptr = "biomorph";
1475          }
1476          sprintf(bailoutmsg,"    (%s default is %ld)",tmpptr,long_i);
1477          choices[promptnum++] = bailoutmsg;
1478       }
1479    }
1480    if (julibrot)
1481    {
1482       switch(neworbittype)
1483       {
1484       case QUATFP:
1485       case HYPERCMPLXFP:
1486           v0 = v0b; v1 = v1b; v2 = v2b; v3 = v3b;
1487           break;
1488       case QUATJULFP:
1489       case HYPERCMPLXJFP:
1490           v0 = v0c; v1 = v1c; v2 = v2c; v3 = v3c;
1491           break;
1492       default:
1493           v0 = v0a; v1 = v1a; v2 = v2a; v3 = v3a;
1494          break;
1495       }
1496 
1497       curfractalspecific = savespecific;
1498       paramvalues[promptnum].uval.dval = mxmaxfp;
1499       paramvalues[promptnum].type = 'f';
1500       choices[promptnum++] = v0;
1501       paramvalues[promptnum].uval.dval = mymaxfp;
1502       paramvalues[promptnum].type = 'f';
1503       choices[promptnum++] = v1;
1504       paramvalues[promptnum].uval.dval = mxminfp;
1505       paramvalues[promptnum].type = 'f';
1506       choices[promptnum++] = v2;
1507       paramvalues[promptnum].uval.dval = myminfp;
1508       paramvalues[promptnum].type = 'f';
1509       choices[promptnum++] = v3;
1510       paramvalues[promptnum].uval.ival = zdots;
1511       paramvalues[promptnum].type = 'i';
1512       choices[promptnum++] = v4;
1513 
1514       paramvalues[promptnum].type = 'l';
1515       paramvalues[promptnum].uval.ch.val  = juli3Dmode;
1516       paramvalues[promptnum].uval.ch.llen = 4;
1517       paramvalues[promptnum].uval.ch.vlen = 9;
1518       paramvalues[promptnum].uval.ch.list = juli3Doptions;
1519       choices[promptnum++] = v11;
1520 
1521       paramvalues[promptnum].uval.dval = eyesfp;
1522       paramvalues[promptnum].type = 'f';
1523       choices[promptnum++] = v10;
1524       paramvalues[promptnum].uval.dval = originfp;
1525       paramvalues[promptnum].type = 'f';
1526       choices[promptnum++] = v5;
1527       paramvalues[promptnum].uval.dval = depthfp;
1528       paramvalues[promptnum].type = 'f';
1529       choices[promptnum++] = v6;
1530       paramvalues[promptnum].uval.dval = heightfp;
1531       paramvalues[promptnum].type = 'f';
1532       choices[promptnum++] = v7;
1533       paramvalues[promptnum].uval.dval = widthfp;
1534       paramvalues[promptnum].type = 'f';
1535       choices[promptnum++] = v8;
1536       paramvalues[promptnum].uval.dval = distfp;
1537       paramvalues[promptnum].type = 'f';
1538       choices[promptnum++] = v9;
1539    }
1540 
1541    if (curtype == INVERSEJULIA || curtype == INVERSEJULIAFP)
1542    {
1543       choices[promptnum] = JIIMstr1;
1544       paramvalues[promptnum].type = 'l';
1545       paramvalues[promptnum].uval.ch.list = JIIMmethod;
1546       paramvalues[promptnum].uval.ch.vlen = 7;
1547 #ifdef RANDOM_RUN
1548       paramvalues[promptnum].uval.ch.llen = 4;
1549 #else
1550       paramvalues[promptnum].uval.ch.llen = 3; /* disable random run */
1551 #endif
1552       paramvalues[promptnum++].uval.ch.val  = major_method;
1553 
1554       choices[promptnum] = JIIMstr2;
1555       paramvalues[promptnum].type = 'l';
1556       paramvalues[promptnum].uval.ch.list = JIIMleftright;
1557       paramvalues[promptnum].uval.ch.vlen = 5;
1558       paramvalues[promptnum].uval.ch.llen = 2;
1559       paramvalues[promptnum++].uval.ch.val  = minor_method;
1560    }
1561 
1562    if((curtype==FORMULA || curtype==FFORMULA) && uses_ismand) {
1563       choices[promptnum] = (char far *)s_ismand;
1564       paramvalues[promptnum].type = 'y';
1565       paramvalues[promptnum++].uval.ch.val = ismand?1:0;
1566    }
1567 
1568    if (caller                           /* <z> command ? */
1569 /*      && (display3d > 0 || promptnum == 0)) */
1570       && (display3d > 0))
1571       {
1572        static FCODE msg[]={"Current type has no type-specific parameters"};
1573        stopmsg(20,msg);
1574        goto gfp_exit;
1575        }
1576    if(julibrot)
1577       sprintf(msg,"Julibrot Parameters (orbit= %s)",juliorbitname);
1578    else
1579       sprintf(msg,"Parameters for fractal type %s",typename);
1580    if(bf_math == 0)
1581    {
1582       static FCODE pressf6[] = {"\n(Press "FK_F6" for corner parameters)"};
1583       far_strcat(msg,pressf6);
1584    }
1585    else
1586       fkeymask = 0;
1587    scroll_row_status = 0; /* make sure we start at beginning of entry */
1588    scroll_column_status = 0;
1589    for(;;)
1590    {
1591       oldhelpmode = helpmode;
1592       helpmode = curfractalspecific->helptext;
1593       i = fullscreen_prompt(msg,promptnum,choices,paramvalues,fkeymask,tstack);
1594       helpmode = oldhelpmode;
1595       if (i < 0)
1596       {
1597          if(julibrot)
1598            goto gfp_top;
1599          if (ret == 0)
1600             ret = -1;
1601          goto gfp_exit;
1602       }
1603       if (i != F6)
1604          break;
1605       if(bf_math == 0)
1606          if (get_corners() > 0)
1607             ret = 1;
1608      }
1609      promptnum = 0;
1610      for ( i = firstparm; i < numparams+firstparm; i++)
1611      {
1612         if(curtype == FORMULA || curtype == FFORMULA)
1613            if(paramnotused(i))
1614               continue;
1615         if (oldparam[i] != paramvalues[promptnum].uval.dval)
1616         {
1617            param[i] = paramvalues[promptnum].uval.dval;
1618            ret = 1;
1619         }
1620         ++promptnum;
1621     }
1622 
1623    for ( i = 0; i < numtrig; i++)
1624    {
1625       if (paramvalues[promptnum].uval.ch.val != (int)trigndx[i])
1626       {
1627          set_trig_array(i,trigfn[paramvalues[promptnum].uval.ch.val].name);
1628          ret = 1;
1629       }
1630       ++promptnum;
1631    }
1632 
1633    if(julibrot)
1634    {
1635       savespecific = curfractalspecific;
1636       curfractalspecific = jborbit;
1637    }
1638 
1639    long_i = curfractalspecific->orbit_bailout;
1640 
1641    if( long_i != 0 && curfractalspecific->calctype == StandardFractal &&
1642        (curfractalspecific->flags & BAILTEST) ) {
1643       if (paramvalues[promptnum].uval.ch.val != (int)bailoutest) {
1644         bailoutest = (enum bailouts)paramvalues[promptnum].uval.ch.val;
1645         ret = 1;
1646       }
1647       promptnum++;
1648    }
1649    else
1650       bailoutest = Mod;
1651    setbailoutformula(bailoutest);
1652 
1653    if (long_i) {
1654       if (potparam[0] != 0.0 && potparam[2] != 0.0)
1655          promptnum++;
1656       else
1657       {
1658          bailout = paramvalues[promptnum++].uval.Lval;
1659          if (bailout != 0 && (bailout < 1 || bailout > 2100000000L))
1660             bailout = oldbailout;
1661          if (bailout != oldbailout)
1662             ret = 1;
1663          promptnum++;
1664       }
1665    }
1666    if (julibrot)
1667      {
1668         mxmaxfp    = paramvalues[promptnum++].uval.dval;
1669         mymaxfp    = paramvalues[promptnum++].uval.dval;
1670         mxminfp    = paramvalues[promptnum++].uval.dval;
1671         myminfp    = paramvalues[promptnum++].uval.dval;
1672         zdots      = paramvalues[promptnum++].uval.ival;
1673         juli3Dmode = paramvalues[promptnum++].uval.ch.val;
1674         eyesfp     = (float)paramvalues[promptnum++].uval.dval;
1675         originfp   = (float)paramvalues[promptnum++].uval.dval;
1676         depthfp    = (float)paramvalues[promptnum++].uval.dval;
1677         heightfp   = (float)paramvalues[promptnum++].uval.dval;
1678         widthfp    = (float)paramvalues[promptnum++].uval.dval;
1679         distfp     = (float)paramvalues[promptnum++].uval.dval;
1680         ret = 1;  /* force new calc since not resumable anyway */
1681      }
1682       if (curtype == INVERSEJULIA || curtype == INVERSEJULIAFP)
1683       {
1684          if (paramvalues[promptnum].uval.ch.val != major_method ||
1685              paramvalues[promptnum+1].uval.ch.val != minor_method)
1686             ret = 1;
1687          major_method = (enum Major)paramvalues[promptnum++].uval.ch.val;
1688          minor_method = (enum Minor)paramvalues[promptnum++].uval.ch.val;
1689       }
1690      if((curtype==FORMULA || curtype==FFORMULA) && uses_ismand)
1691      {
1692         if (ismand != (short int)paramvalues[promptnum].uval.ch.val)
1693         {
1694            ismand = (short int)paramvalues[promptnum].uval.ch.val;
1695            ret = 1;
1696         }
1697         ++promptnum;
1698      }
1699 gfp_exit:
1700    curfractalspecific = &fractalspecific[fractype];
1701    return(ret);
1702 }
1703 
find_extra_param(int type)1704 int find_extra_param(int type)
1705 {
1706    int i,ret,curtyp;
1707    ret = -1;
1708    i= -1;
1709 
1710    if(fractalspecific[type].flags&MORE)
1711    {
1712       while((curtyp=moreparams[++i].type) != type && curtyp != -1);
1713       if(curtyp == type)
1714         ret = i;
1715    }
1716    return(ret);
1717 }
1718 
load_params(int fractype)1719 void load_params(int fractype)
1720 {
1721    int i, extra;
1722    for (i = 0; i < 4; ++i)
1723    {
1724       param[i] = fractalspecific[fractype].paramvalue[i];
1725       if(fractype != CELLULAR && fractype != ANT)
1726         roundfloatd(&param[i]); /* don't round cellular or ant */
1727    }
1728    if((extra=find_extra_param(fractype)) > -1)
1729       for(i=0;i<MAXPARAMS-4;i++)
1730          param[i+4] = moreparams[extra].paramvalue[i];
1731 }
1732 
check_orbit_name(char * orbitname)1733 int check_orbit_name(char *orbitname)
1734 {
1735    int i, numtypes, bad;
1736    char *nameptr[MAXFRACTALS];
1737    int fractals[MAXFRACTALS];
1738    int last_val;
1739 
1740    numtypes = build_fractal_list(fractals, &last_val, nameptr);
1741    bad = 1;
1742    for(i=0;i<numtypes;i++)
1743    {
1744       if(strcmp(orbitname,nameptr[i]) == 0)
1745       {
1746          neworbittype = fractals[i];
1747          bad = 0;
1748          break;
1749       }
1750    }
1751    return(bad);
1752 }
1753 
1754 /* --------------------------------------------------------------------- */
1755 
1756 static FILE *gfe_file;
1757 
get_file_entry(int type,char * title,char * fmask,char * filename,char * entryname)1758 long get_file_entry(int type,char *title,char *fmask,
1759                           char *filename,char *entryname)
1760 {
1761    /* Formula, LSystem, etc type structure, select from file */
1762    /* containing definitions in the form    name { ... }     */
1763    int newfile,firsttry;
1764    long entry_pointer;
1765    newfile = 0;
1766    for(;;) {
1767       firsttry = 0;
1768       /* pb: binary mode used here - it is more work, but much faster, */
1769       /*     especially when ftell or fgetpos is used                  */
1770       while (newfile || (gfe_file = fopen(filename, "rb")) == NULL) {
1771          char buf[60];
1772          newfile = 0;
1773          if (firsttry) {
1774             sprintf(temp1,s_cantfind, filename);
1775             stopmsg(0,temp1);
1776             }
1777          sprintf(buf,"Select %s File",title);
1778          if (getafilename(buf,fmask,filename) < 0)
1779             return -1;
1780 
1781          firsttry = 1; /* if around open loop again it is an error */
1782          }
1783       setvbuf(gfe_file,tstack,_IOFBF,4096); /* improves speed when file is big */
1784       newfile = 0;
1785       if ((entry_pointer = gfe_choose_entry(type,title,filename,entryname)) == -2) {
1786          newfile = 1; /* go to file list, */
1787          continue;    /* back to getafilename */
1788          }
1789       if (entry_pointer == -1)
1790          return -1;
1791       switch (type) {
1792          case GETFORMULA:
1793             if (RunForm(entryname, 1) == 0) return 0;
1794             break;
1795          case GETLSYS:
1796             if (LLoad() == 0) return 0;
1797             break;
1798          case GETIFS:
1799             if (ifsload() == 0) {
1800                fractype = (ifs_type == 0) ? IFS : IFS3D;
1801                curfractalspecific = &fractalspecific[fractype];
1802                set_default_parms(); /* to correct them if 3d */
1803                return 0;
1804                }
1805             break;
1806          case GETPARM:
1807             return entry_pointer;
1808          }
1809       }
1810 }
1811 
1812 struct entryinfo {
1813    char name[ITEMNAMELEN+2];
1814    long point; /* points to the ( or the { following the name */
1815    };
1816 static struct entryinfo far *far*gfe_choices; /* for format_getparm_line */
1817 static char *gfe_title;
1818 
1819 /* skip to next non-white space character and return it */
skip_white_space(FILE * infile,long * file_offset)1820 int skip_white_space(FILE *infile, long *file_offset)
1821 {
1822    int c;
1823    do
1824    {
1825       c = getc(infile);
1826       (*file_offset)++;
1827    }
1828    while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
1829    return(c);
1830 }
1831 
1832 /* skip to end of line */
skip_comment(FILE * infile,long * file_offset)1833 int skip_comment(FILE *infile, long *file_offset)
1834 {
1835    int c;
1836    do
1837    {
1838       c = getc(infile);
1839       (*file_offset)++;
1840    }
1841    while (c != '\n' && c != '\r' && c != EOF && c != '\032');
1842    return(c);
1843 }
1844 
1845 #define MAXENTRIES 2000L
1846 
scan_entries(FILE * infile,void far * ch,char * itemname)1847 int scan_entries(FILE * infile, void far * ch, char *itemname)
1848 {
1849       /*
1850       function returns the number of entries found; if a
1851       specific entry is being looked for, returns -1 if
1852       the entry is found, 0 otherwise.
1853       */
1854    struct entryinfo far *far * choices;
1855    char buf[101];
1856    int exclude_entry;
1857    long name_offset, temp_offset;   /*rev 5/23/96 to add temp_offset,
1858                                       used below to skip any '{' that
1859                                       does not have a corresponding
1860                                       '}' - GGM */
1861    long file_offset = -1;
1862    int numentries = 0;
1863 
1864    choices = (struct entryinfo far * far *) ch;
1865 
1866    for (;;)
1867    {                            /* scan the file for entry names */
1868       int c, len;
1869 top:
1870       if ((c = skip_white_space(infile, &file_offset)) == ';')
1871       {
1872          c = skip_comment(infile, &file_offset);
1873          if (c == EOF || c == '\032')
1874             break;
1875          continue;
1876       }
1877       name_offset = temp_offset = file_offset;
1878       /* next equiv roughly to fscanf(..,"%40[^* \n\r\t({\032]",buf) */
1879       len = 0;
1880       /* allow spaces in entry names in next JCO 9/2/2003 */
1881       while (c != ' ' && c != '\t' && c != '(' && c != ';' && c != '['
1882            && c != '{' && c != '\n' && c != '\r' && c != EOF && c != '\032')
1883       {
1884          if (len < 40)
1885             buf[len++] = (char) c;
1886          c = getc(infile);
1887          ++file_offset;
1888          if(c == '\n' || c == '\r')
1889             goto top;
1890       }
1891       buf[len] = 0;
1892       while (c != '{' &&  c != EOF && c != '\032')
1893       {
1894          if(c == ';')
1895             c = skip_comment(infile, &file_offset);
1896          else
1897          {
1898             c = getc(infile);
1899             ++file_offset;
1900             if(c == '\n' || c == '\r')
1901                goto top;
1902          }
1903       }
1904       if (c == '{')
1905       {
1906          while (c != '}' && c != EOF && c != '\032')
1907          {
1908             if(c == ';')
1909                c = skip_comment(infile, &file_offset);
1910             else
1911             {
1912                if(c == '\n' || c == '\r')     /* reset temp_offset to  */
1913                   temp_offset = file_offset;  /* beginning of new line */
1914                c = getc(infile);
1915                ++file_offset;
1916             }
1917             if(c == '{') /*second '{' found*/
1918             {
1919                if (temp_offset == name_offset) /*if on same line, skip line*/
1920                {
1921                   c = skip_comment(infile, &file_offset);
1922                   goto top;
1923                }
1924                else
1925                {
1926                   fseek(infile, temp_offset, SEEK_SET); /*else, go back to */
1927                   file_offset = temp_offset - 1;        /*beginning of line*/
1928                   goto top;
1929                }
1930             }
1931          }
1932          if (c != '}')   /* i.e. is EOF or '\032'*/
1933             break;
1934 
1935          if (strnicmp(buf, "frm:", 4) == 0 ||
1936                    strnicmp(buf, "ifs:", 4) == 0 ||
1937                    strnicmp(buf, "par:", 4) == 0)
1938             exclude_entry = 4;
1939          else if (strnicmp(buf, "lsys:", 5) == 0)
1940             exclude_entry = 5;
1941          else
1942             exclude_entry = 0;
1943 
1944          buf[ITEMNAMELEN + exclude_entry] = 0;
1945          if (itemname != NULL)  /* looking for one entry */
1946          {
1947             if (stricmp(buf, itemname) == 0)
1948             {
1949                fseek(infile, name_offset + (long) exclude_entry, SEEK_SET);
1950                return (-1);
1951             }
1952          }
1953          else /* make a whole list of entries */
1954          {
1955             if (buf[0] != 0 && stricmp(buf, "comment") != 0 && !exclude_entry)
1956             {
1957                far_strcpy(choices[numentries]->name, buf);
1958                choices[numentries]->point = name_offset;
1959                if (++numentries >= MAXENTRIES)
1960                {
1961                   sprintf(buf, "Too many entries in file, first %ld used", MAXENTRIES);
1962                   stopmsg(0, buf);
1963                   break;
1964                }
1965             }
1966          }
1967       }
1968       else if (c == EOF || c == '\032')
1969          break;
1970    }
1971    return (numentries);
1972 }
1973 
gfe_choose_entry(int type,char * title,char * filename,char * entryname)1974 static long gfe_choose_entry(int type,char *title,char *filename,char *entryname)
1975 /* subrtn of get_file_entry, separated so that storage gets freed up */
1976 {
1977 #ifdef XFRACT
1978    static FCODE o_instr[]={"Press "FK_F6" to select file, "FK_F2" for details, "FK_F4" to toggle sort "};
1979 /* keep the above line length < 80 characters */
1980 #else
1981    static FCODE o_instr[]={"Press "FK_F6" to select different file, "FK_F2" for details, "FK_F4" to toggle sort "};
1982 #endif
1983    int numentries, i;
1984    char buf[101];
1985    struct entryinfo far * far *choices;
1986    int far *attributes;
1987    void (*formatitem)(int, char *);
1988    int boxwidth,boxdepth,colwidth;
1989    static int dosort = 1;
1990    int options = 8;
1991    char far *instr;
1992    /* steal existing array for "choices" */
1993    choices = (struct entryinfo far *far*)MK_FP(extraseg,0);
1994    /* leave room for details F2 */
1995    choices = choices + (2048/sizeof(struct entryinfo far *far*));
1996    choices[0] = (struct entryinfo far *)(choices + MAXENTRIES+1);
1997    attributes = (int far *)(choices[0] + MAXENTRIES+1);
1998    instr = (char far *)(attributes + MAXENTRIES +1);
1999    gfe_choices = &choices[0];
2000    gfe_title = title;
2001 retry:
2002    attributes[0] = 1;
2003    for(i=1;i<MAXENTRIES+1;i++)
2004    {
2005       choices[i] = choices[i-1] + 1;
2006       attributes[i] = 1;
2007    }
2008 
2009    numentries = 0;
2010    helptitle(); /* to display a clue when file big and next is slow */
2011 
2012    numentries=scan_entries(gfe_file,choices,NULL);
2013    if (numentries == 0) {
2014       static FCODE msg[]={"File doesn't contain any valid entries"};
2015       stopmsg(0,msg);
2016       fclose(gfe_file);
2017       return -2; /* back to file list */
2018       }
2019    far_strcpy(instr,o_instr);
2020    if(dosort)
2021    {
2022       far_strcat(instr,"off");
2023       shell_sort((char far *)choices,numentries,sizeof(char far *),lccompare);
2024    }
2025    else
2026       far_strcat(instr,"on");
2027 
2028    strcpy(buf,entryname); /* preset to last choice made */
2029    sprintf(temp1,"%s Selection\nFile: %s",title,filename);
2030    formatitem = NULL;
2031    boxwidth = colwidth = boxdepth = 0;
2032    if (type == GETPARM) {
2033       formatitem = format_parmfile_line;
2034       boxwidth = 1;
2035       boxdepth = 16;
2036       colwidth = 76;
2037       }
2038    if(dosort)
2039       options = 8;
2040    else
2041       options = 8+32;
2042    i = fullscreen_choice(options,temp1,NULL,instr,numentries,(char far*far*)choices,
2043                            attributes,boxwidth,boxdepth,colwidth,0,
2044                            formatitem,buf,NULL,check_gfe_key);
2045    if (i == 0-F4)
2046    {
2047      rewind(gfe_file);
2048      dosort = 1-dosort;
2049      goto retry;
2050    }
2051    fclose(gfe_file);
2052    if (i < 0) {
2053       if (i == 0-F6)
2054          return -2; /* go back to file list */
2055       return -1;    /* cancel */
2056       }
2057    far_strcpy(entryname, choices[i]->name);
2058    return(choices[i]->point);
2059 }
2060 
2061 
check_gfe_key(int curkey,int choice)2062 static int check_gfe_key(int curkey,int choice)
2063 {
2064    char infhdg[60];
2065    char far *infbuf;
2066    int in_scrolling_mode = 0; /* 1 if entry doesn't fit available space */
2067    int top_line = 0;
2068    int left_column = 0;
2069    int i;
2070    int done = 0;
2071    int rewrite_infbuf = 0;  /* if 1: rewrite the entry portion of screen */
2072    char blanks[79];         /* used to clear the entry portion of screen */
2073    memset(blanks, ' ', 78);
2074    blanks[78] = (char) 0;
2075 
2076    if (curkey == F6)
2077       return 0-F6;
2078    if (curkey == F4)
2079       return 0-F4;
2080    if (curkey == F2) {
2081       int widest_entry_line = 0;
2082       int lines_in_entry = 0;
2083       int comment = 0;
2084       int c = 0;
2085       int widthct = 0;
2086       infbuf = MK_FP(extraseg,0);
2087       fseek(gfe_file,gfe_choices[choice]->point,SEEK_SET);
2088       while((c = fgetc(gfe_file)) != EOF && c != '\032') {
2089          if(c == ';')
2090             comment = 1;
2091          else if(c == '\n') {
2092             comment = 0;
2093             lines_in_entry++;
2094             widthct =  -1;
2095          }
2096          else if (c == '\t')
2097             widthct += 7 - widthct % 8;
2098          else if ( c == '\r')
2099             continue;
2100          if(++widthct > widest_entry_line)
2101             widest_entry_line = widthct;
2102          if (c == '}' && !comment) {
2103             lines_in_entry++;
2104             break;
2105          }
2106       }
2107       if(c == EOF || c == '\032') { /* should never happen */
2108          fseek(gfe_file,gfe_choices[choice]->point,SEEK_SET);
2109          in_scrolling_mode = 0;
2110       }
2111       fseek(gfe_file,gfe_choices[choice]->point,SEEK_SET);
2112       load_entry_text(gfe_file,infbuf, 17, 0, 0);
2113       if(lines_in_entry > 17 || widest_entry_line > 74)
2114          in_scrolling_mode = 1;
2115       strcpy(infhdg,gfe_title);
2116       strcat(infhdg," file entry:\n\n");
2117  /* ... instead, call help with buffer?  heading added */
2118       stackscreen();
2119       helptitle();
2120       setattr(1,0,C_GENERAL_MED,24*80);
2121 
2122       textcbase = 0;
2123       putstring(2,1,C_GENERAL_HI,infhdg);
2124       textcbase = 2; /* left margin is 2 */
2125       putstring(4,0,C_GENERAL_MED,infbuf);
2126 
2127       {
2128       static FCODE msg[]  = {"\n\n Use "UPARR1", "DNARR1", "RTARR1", "LTARR1", PgUp, PgDown, Home, and End to scroll text\nAny other key to return to selection list"};
2129       putstring(-1,0,C_GENERAL_LO,msg);
2130       }
2131 
2132       while(!done) {
2133          if(rewrite_infbuf) {
2134             rewrite_infbuf = 0;
2135             fseek(gfe_file,gfe_choices[choice]->point,SEEK_SET);
2136             load_entry_text(gfe_file, infbuf, 17, top_line, left_column);
2137             for(i = 4; i < (lines_in_entry < 17 ? lines_in_entry + 4 : 21); i++)
2138                putstring(i,0,C_GENERAL_MED,blanks);
2139             putstring(4,0,C_GENERAL_MED,infbuf);
2140          }
2141          if((i = getakeynohelp()) == DOWN_ARROW || i == DOWN_ARROW_2
2142                              || i == UP_ARROW || i == UP_ARROW_2
2143                              || i == LEFT_ARROW || i == LEFT_ARROW_2
2144                              || i == RIGHT_ARROW || i == RIGHT_ARROW_2
2145                              || i == HOME || i == CTL_HOME
2146                              || i == END || i == CTL_END
2147                              || i == PAGE_UP || i == CTL_PAGE_UP
2148                              || i == PAGE_DOWN || i == CTL_PAGE_DOWN) {
2149             switch(i) {
2150                case DOWN_ARROW: case DOWN_ARROW_2: /* down one line */
2151                   if(in_scrolling_mode && top_line < lines_in_entry - 17) {
2152                      top_line++;
2153                      rewrite_infbuf = 1;
2154                   }
2155                   break;
2156                case UP_ARROW: case UP_ARROW_2:  /* up one line */
2157                   if(in_scrolling_mode && top_line > 0) {
2158                      top_line--;
2159                      rewrite_infbuf = 1;
2160                   }
2161                   break;
2162                case LEFT_ARROW: case LEFT_ARROW_2:  /* left one column */
2163                   if(in_scrolling_mode && left_column > 0) {
2164                      left_column--;
2165                      rewrite_infbuf = 1;
2166                   }
2167                   break;
2168                case RIGHT_ARROW: case RIGHT_ARROW_2: /* right one column */
2169                   if(in_scrolling_mode && far_strchr(infbuf, '\021') != NULL) {
2170                      left_column++;
2171                      rewrite_infbuf = 1;
2172                   }
2173                   break;
2174                case PAGE_DOWN: case CTL_PAGE_DOWN: /* down 17 lines */
2175                   if(in_scrolling_mode && top_line < lines_in_entry - 17) {
2176                      top_line += 17;
2177                      if(top_line > lines_in_entry - 17)
2178                         top_line = lines_in_entry - 17;
2179                      rewrite_infbuf = 1;
2180                   }
2181                   break;
2182                case PAGE_UP: case CTL_PAGE_UP: /* up 17 lines */
2183                   if(in_scrolling_mode && top_line > 0) {
2184                      top_line -= 17;
2185                      if(top_line < 0)
2186                         top_line = 0;
2187                      rewrite_infbuf = 1;
2188                   }
2189                   break;
2190                case END: case CTL_END:       /* to end of entry */
2191                   if(in_scrolling_mode) {
2192                      top_line = lines_in_entry - 17;
2193                      left_column = 0;
2194                      rewrite_infbuf = 1;
2195                   }
2196                   break;
2197                case HOME: case CTL_HOME:     /* to beginning of entry */
2198                   if(in_scrolling_mode) {
2199                      top_line = left_column = 0;
2200                      rewrite_infbuf = 1;
2201                   }
2202                   break;
2203                default:
2204                   break;
2205             }
2206          }
2207          else
2208             done = 1;  /* a key other than scrolling key was pressed */
2209       }
2210       textcbase = 0;
2211       movecursor(25,80);
2212       unstackscreen();
2213    }
2214    return 0;
2215 }
2216 
load_entry_text(FILE * entfile,char far * buf,int maxlines,int startrow,int startcol)2217 static void load_entry_text(
2218       FILE *entfile,
2219       char far *buf,
2220       int maxlines,
2221       int startrow,
2222       int startcol)
2223 {
2224        /* Revised 12/14/96 by George Martin. Up to maxlines of an entry
2225           is copied to *buf starting from row "startrow", and skipping
2226           characters in each line up to "startcol". The terminating '\n'
2227           is deleted if maxlines is reached before the end of the entry.
2228        */
2229 
2230    int linelen, i;
2231    int comment=0;
2232    int c = 0;
2233    int tabpos = 7 - (startcol % 8);
2234 
2235    if(maxlines <= 0) { /* no lines to get! */
2236       *buf = (char) 0;
2237       return;
2238    }
2239 
2240       /*move down to starting row*/
2241    for(i = 0; i < startrow; i++) {
2242       while((c=fgetc(entfile)) != '\n' && c != EOF && c != '\032') {
2243          if(c == ';')
2244             comment = 1;
2245          if(c == '}' && !comment)  /* end of entry before start line */
2246             break;                 /* this should never happen       */
2247       }
2248       if(c == '\n')
2249          comment = 0;
2250       else {                       /* reached end of file or end of entry */
2251          *buf = (char) 0;
2252          return;
2253       }
2254    }
2255 
2256       /* write maxlines of entry */
2257    while(maxlines-- > 0) {
2258       comment = linelen = i = c = 0;
2259 
2260          /* skip line up to startcol */
2261       while (i++ < startcol && (c = fgetc(entfile)) != EOF && c != '\032') {
2262          if(c == ';')
2263             comment = 1;
2264          if(c == '}' && !comment) { /*reached end of entry*/
2265             *buf = (char) 0;
2266             return;
2267          }
2268          if ( c == '\r') {
2269             i--;
2270             continue;
2271          }
2272          if(c == '\t')
2273             i += 7 - (i % 8);
2274          if(c == '\n') {  /*need to insert '\n', even for short lines*/
2275             *(buf++) = (char)c;
2276             break;
2277          }
2278       }
2279       if(c == EOF || c == '\032') { /* unexpected end of file */
2280          *buf = (char) 0;
2281          return;
2282       }
2283       if(c == '\n')       /* line is already completed */
2284          continue;
2285 
2286       if(i > startcol) {  /* can happen because of <tab> character */
2287          while(i-- > startcol) {
2288             *(buf++) = ' ';
2289             linelen++;
2290          }
2291       }
2292 
2293          /*process rest of line into buf */
2294       while ((c = fgetc(entfile)) != EOF && c != '\032') {
2295          if (c == ';')
2296             comment = 1;
2297          else if (c == '\n' || c == '\r')
2298             comment = 0;
2299          if (c != '\r') {
2300             if (c == '\t') {
2301                while ((linelen % 8) != tabpos && linelen < 75) { /* 76 wide max */
2302                   *(buf++) = ' ';
2303                   ++linelen;
2304                }
2305                c = ' ';
2306             }
2307             if (c == '\n') {
2308                *(buf++) = '\n';
2309                break;
2310             }
2311             if (++linelen > 75) {
2312                if (linelen == 76)
2313                   *(buf++) = '\021';
2314             }
2315             else
2316                *(buf++) = (char)c;
2317             if (c == '}' && !comment) { /*reached end of entry*/
2318                *(buf) = (char) 0;
2319                return;
2320             }
2321          }
2322       }
2323       if(c == EOF || c == '\032') { /* unexpected end of file */
2324          *buf = (char) 0;
2325          return;
2326       }
2327    }
2328    if(*(buf-1) == '\n') /* specified that buf will not end with a '\n' */
2329       buf--;
2330    *buf = (char) 0;
2331 }
2332 
format_parmfile_line(int choice,char * buf)2333 static void format_parmfile_line(int choice,char *buf)
2334 {
2335    int c,i;
2336    char line[80];
2337    fseek(gfe_file,gfe_choices[choice]->point,SEEK_SET);
2338    while (getc(gfe_file) != '{') { }
2339    while ((c = getc(gfe_file)) == ' ' || c == '\t' || c == ';') { }
2340    i = 0;
2341    while (i < 56 && c != '\n' && c != '\r' && c != EOF && c != '\032') {
2342       line[i++] = (char)((c == '\t') ? ' ' : c);
2343       c = getc(gfe_file);
2344       }
2345    line[i] = 0;
2346 #ifndef XFRACT
2347    sprintf(buf,"%-20Fs%-56s",gfe_choices[choice]->name,line);
2348 #else
2349    sprintf(buf,"%-20s%-56s",gfe_choices[choice]->name,line);
2350 #endif
2351 }
2352 
2353 /* --------------------------------------------------------------------- */
2354 
get_fract3d_params()2355 int get_fract3d_params() /* prompt for 3D fractal parameters */
2356 {
2357    int i,k,ret,oldhelpmode;
2358    static FCODE hdg[] = {"3D Parameters"};
2359    static FCODE p1[] = {"X-axis rotation in degrees"};
2360    static FCODE p2[] = {"Y-axis rotation in degrees"};
2361    static FCODE p3[] = {"Z-axis rotation in degrees"};
2362    static FCODE p4[] = {"Perspective distance [1 - 999, 0 for no persp]"};
2363    static FCODE p5[] = {"X shift with perspective (positive = right)"};
2364    static FCODE p6[] = {"Y shift with perspective (positive = up   )"};
2365    static FCODE p7[] = {"Stereo (R/B 3D)? (0=no,1=alternate,2=superimpose,3=photo,4=stereo pair)"};
2366    struct fullscreenvalues uvalues[20];
2367    char far *ifs3d_prompts[8];
2368 
2369    stackscreen();
2370    ifs3d_prompts[0] = p1;
2371    ifs3d_prompts[1] = p2;
2372    ifs3d_prompts[2] = p3;
2373    ifs3d_prompts[3] = p4;
2374    ifs3d_prompts[4] = p5;
2375    ifs3d_prompts[5] = p6;
2376    ifs3d_prompts[6] = p7;
2377    k = 0;
2378    uvalues[k].type = 'i';
2379    uvalues[k++].uval.ival = XROT;
2380    uvalues[k].type = 'i';
2381    uvalues[k++].uval.ival = YROT;
2382    uvalues[k].type = 'i';
2383    uvalues[k++].uval.ival = ZROT;
2384    uvalues[k].type = 'i';
2385    uvalues[k++].uval.ival = ZVIEWER;
2386    uvalues[k].type = 'i';
2387    uvalues[k++].uval.ival = XSHIFT;
2388    uvalues[k].type = 'i';
2389    uvalues[k++].uval.ival = YSHIFT;
2390    uvalues[k].type = 'i';
2391    uvalues[k++].uval.ival = glassestype;
2392 
2393    oldhelpmode = helpmode;
2394    helpmode = HELP3DFRACT;
2395    i = fullscreen_prompt(hdg,k,ifs3d_prompts,uvalues,0,NULL);
2396    helpmode = oldhelpmode;
2397    if (i < 0) {
2398       ret = -1;
2399       goto get_f3d_exit;
2400       }
2401 
2402    ret = k = 0;
2403    XROT    =  uvalues[k++].uval.ival;
2404    YROT    =  uvalues[k++].uval.ival;
2405    ZROT    =  uvalues[k++].uval.ival;
2406    ZVIEWER =  uvalues[k++].uval.ival;
2407    XSHIFT  =  uvalues[k++].uval.ival;
2408    YSHIFT  =  uvalues[k++].uval.ival;
2409    glassestype = uvalues[k++].uval.ival;
2410    if (glassestype < 0 || glassestype > 4) glassestype = 0;
2411    if (glassestype)
2412       if (get_funny_glasses_params() || check_mapfile())
2413          ret = -1;
2414 
2415 get_f3d_exit:
2416    unstackscreen();
2417    return(ret);
2418 }
2419 
2420 /* --------------------------------------------------------------------- */
2421 /* These macros streamline the "save near space" campaign */
2422 
2423 #define LOADPROMPTS3D(X)     {\
2424    static FCODE tmp[] = { X };\
2425    prompts3d[++k]= tmp;\
2426    }
2427 
2428 #define LOADPROMPTSCHOICES(X)     {\
2429    static FCODE tmp[] = { X };\
2430    choices[k++]= tmp;\
2431    }
2432 
get_3d_params()2433 int get_3d_params()     /* prompt for 3D parameters */
2434 {
2435    static FCODE hdg[]={"3D Mode Selection"};
2436    static FCODE hdg1[]={"Select 3D Fill Type"};
2437    char far *choices[11];
2438    int attributes[21];
2439    int sphere;
2440    char far *s;
2441    static FCODE s1[] = {"Sphere 3D Parameters\n\
2442 Sphere is on its side; North pole to right\n\
2443 Long. 180 is top, 0 is bottom; Lat. -90 is left, 90 is right"};
2444    static FCODE s2[]={"Planar 3D Parameters\n\
2445 Pre-rotation X axis is screen top; Y axis is left side\n\
2446 Pre-rotation Z axis is coming at you out of the screen!"};
2447    char far *prompts3d[21];
2448    struct fullscreenvalues uvalues[21];
2449    int i, k;
2450    int oldhelpmode;
2451 
2452 #ifdef WINFRACT
2453      {
2454      extern int far wintext_textmode;
2455      if (wintext_textmode != 2)  /* are we in textmode? */
2456          return(0);              /* no - prompts are already handled */
2457      }
2458 #endif
2459 #ifdef XFRACT
2460 stackscreen();
2461 #endif
2462 restart_1:
2463         if (Targa_Out && overlay3d)
2464                 Targa_Overlay = 1;
2465 
2466    k= -1;
2467 
2468    LOADPROMPTS3D("Preview Mode?");
2469    uvalues[k].type = 'y';
2470    uvalues[k].uval.ch.val = preview;
2471 
2472    LOADPROMPTS3D("    Show Box?");
2473    uvalues[k].type = 'y';
2474    uvalues[k].uval.ch.val = showbox;
2475 
2476    LOADPROMPTS3D("Coarseness, preview/grid/ray (in y dir)");
2477    uvalues[k].type = 'i';
2478    uvalues[k].uval.ival = previewfactor;
2479 
2480    LOADPROMPTS3D("Spherical Projection?");
2481    uvalues[k].type = 'y';
2482    uvalues[k].uval.ch.val = sphere = SPHERE;
2483 
2484    LOADPROMPTS3D("Stereo (R/B 3D)? (0=no,1=alternate,2=superimpose,");
2485    uvalues[k].type = 'i';
2486    uvalues[k].uval.ival = glassestype;
2487 
2488    LOADPROMPTS3D("                  3=photo,4=stereo pair)");
2489    uvalues[k].type = '*';
2490 
2491    LOADPROMPTS3D("Ray trace out? (0=No, 1=DKB/POVRay, 2=VIVID, 3=RAW,");
2492    uvalues[k].type = 'i';
2493    uvalues[k].uval.ival = RAY;
2494 
2495    LOADPROMPTS3D("                4=MTV, 5=RAYSHADE, 6=ACROSPIN, 7=DXF)");
2496    uvalues[k].type = '*';
2497 
2498    LOADPROMPTS3D("    Brief output?");
2499    uvalues[k].type = 'y';
2500    uvalues[k].uval.ch.val = BRIEF;
2501 
2502    check_writefile(ray_name,".ray");
2503    LOADPROMPTS3D("    Output File Name");
2504    uvalues[k].type = 's';
2505    strcpy(uvalues[k].uval.sval,ray_name);
2506 
2507    LOADPROMPTS3D("Targa output?");
2508    uvalues[k].type = 'y';
2509    uvalues[k].uval.ch.val = Targa_Out;
2510 
2511    LOADPROMPTS3D("Use grayscale value for depth? (if \"no\" uses color number)");
2512    uvalues[k].type = 'y';
2513    uvalues[k].uval.ch.val = grayflag;
2514 
2515    oldhelpmode = helpmode;
2516    helpmode = HELP3DMODE;
2517 
2518    k = fullscreen_prompt(hdg,k+1,prompts3d,uvalues,0,NULL);
2519    helpmode = oldhelpmode;
2520    if (k < 0) {
2521 #ifdef XFRACT
2522       unstackscreen();
2523 #endif
2524       return(-1);
2525       }
2526 
2527    k=0;
2528 
2529    preview = (char)uvalues[k++].uval.ch.val;
2530 
2531    showbox = (char)uvalues[k++].uval.ch.val;
2532 
2533    previewfactor  = uvalues[k++].uval.ival;
2534 
2535    sphere = uvalues[k++].uval.ch.val;
2536 
2537    glassestype = uvalues[k++].uval.ival;
2538    k++;
2539 
2540    RAY = uvalues[k++].uval.ival;
2541    k++;
2542    {
2543       static FCODE msg[] = {
2544 "DKB/POV-Ray output is obsolete but still works. See \"Ray Tracing Output\" in\n\
2545 the online documentation."};
2546       if(RAY == 1)
2547          stopmsg(0,msg);
2548    }
2549    BRIEF = uvalues[k++].uval.ch.val;
2550 
2551    strcpy(ray_name,uvalues[k++].uval.sval);
2552 
2553    Targa_Out = uvalues[k++].uval.ch.val;
2554    grayflag  = (char)uvalues[k++].uval.ch.val;
2555 
2556    /* check ranges */
2557    if(previewfactor < 2)
2558       previewfactor = 2;
2559    if(previewfactor > 2000)
2560       previewfactor = 2000;
2561 
2562    if(sphere && !SPHERE)
2563    {
2564       SPHERE = TRUE;
2565       set_3d_defaults();
2566    }
2567    else if(!sphere && SPHERE)
2568    {
2569       SPHERE = FALSE;
2570       set_3d_defaults();
2571    }
2572 
2573    if(glassestype < 0)
2574       glassestype = 0;
2575    if(glassestype > 4)
2576       glassestype = 4;
2577    if(glassestype)
2578       whichimage = 1;
2579 
2580    if (RAY < 0)
2581       RAY = 0;
2582    if (RAY > 7)
2583       RAY = 7;
2584 
2585    if (!RAY)
2586    {
2587       k = 0;
2588       LOADPROMPTSCHOICES("make a surface grid");
2589       LOADPROMPTSCHOICES("just draw the points");
2590       LOADPROMPTSCHOICES("connect the dots (wire frame)");
2591       LOADPROMPTSCHOICES("surface fill (colors interpolated)");
2592       LOADPROMPTSCHOICES("surface fill (colors not interpolated)");
2593       LOADPROMPTSCHOICES("solid fill (bars up from \"ground\")");
2594       if(SPHERE)
2595       {
2596              LOADPROMPTSCHOICES("light source");
2597       }
2598       else
2599       {
2600              LOADPROMPTSCHOICES("light source before transformation");
2601              LOADPROMPTSCHOICES("light source after transformation");
2602       }
2603       for (i = 0; i < k; ++i)
2604          attributes[i] = 1;
2605       helpmode = HELP3DFILL;
2606       i = fullscreen_choice(CHOICEHELP,hdg1,NULL,NULL,k,(char far * far *)choices,attributes,
2607                               0,0,0,FILLTYPE+1,NULL,NULL,NULL,NULL);
2608       helpmode = oldhelpmode;
2609       if (i < 0)
2610          goto restart_1;
2611       FILLTYPE = i-1;
2612 
2613       if(glassestype)
2614       {
2615          if(get_funny_glasses_params())
2616             goto restart_1;
2617          }
2618          if (check_mapfile())
2619              goto restart_1;
2620       }
2621    restart_3:
2622 
2623    if(SPHERE)
2624    {
2625       k = -1;
2626       LOADPROMPTS3D("Longitude start (degrees)");
2627       LOADPROMPTS3D("Longitude stop  (degrees)");
2628       LOADPROMPTS3D("Latitude start  (degrees)");
2629       LOADPROMPTS3D("Latitude stop   (degrees)");
2630       LOADPROMPTS3D("Radius scaling factor in pct");
2631    }
2632    else
2633    {
2634       k = -1;
2635       if (!RAY)
2636       {
2637              LOADPROMPTS3D("X-axis rotation in degrees");
2638          LOADPROMPTS3D("Y-axis rotation in degrees");
2639              LOADPROMPTS3D("Z-axis rotation in degrees");
2640       }
2641       LOADPROMPTS3D("X-axis scaling factor in pct");
2642       LOADPROMPTS3D("Y-axis scaling factor in pct");
2643    }
2644    k = -1;
2645    if (!(RAY && !SPHERE))
2646    {
2647       uvalues[++k].uval.ival   = XROT    ;
2648       uvalues[k].type = 'i';
2649       uvalues[++k].uval.ival   = YROT    ;
2650       uvalues[k].type = 'i';
2651       uvalues[++k].uval.ival   = ZROT    ;
2652       uvalues[k].type = 'i';
2653    }
2654    uvalues[++k].uval.ival   = XSCALE    ;
2655    uvalues[k].type = 'i';
2656 
2657    uvalues[++k].uval.ival   = YSCALE    ;
2658    uvalues[k].type = 'i';
2659 
2660    LOADPROMPTS3D("Surface Roughness scaling factor in pct");
2661    uvalues[k].type = 'i';
2662    uvalues[k].uval.ival = ROUGH     ;
2663 
2664    LOADPROMPTS3D("'Water Level' (minimum color value)");
2665    uvalues[k].type = 'i';
2666    uvalues[k].uval.ival = WATERLINE ;
2667 
2668    if(!RAY)
2669    {
2670       LOADPROMPTS3D("Perspective distance [1 - 999, 0 for no persp])");
2671       uvalues[k].type = 'i';
2672       uvalues[k].uval.ival = ZVIEWER     ;
2673 
2674       LOADPROMPTS3D("X shift with perspective (positive = right)");
2675       uvalues[k].type = 'i';
2676       uvalues[k].uval.ival = XSHIFT    ;
2677 
2678       LOADPROMPTS3D("Y shift with perspective (positive = up   )");
2679       uvalues[k].type = 'i';
2680       uvalues[k].uval.ival = YSHIFT    ;
2681 
2682       LOADPROMPTS3D("Image non-perspective X adjust (positive = right)");
2683       uvalues[k].type = 'i';
2684       uvalues[k].uval.ival = xtrans    ;
2685 
2686       LOADPROMPTS3D("Image non-perspective Y adjust (positive = up)");
2687       uvalues[k].type = 'i';
2688       uvalues[k].uval.ival = ytrans    ;
2689 
2690       LOADPROMPTS3D("First transparent color");
2691       uvalues[k].type = 'i';
2692       uvalues[k].uval.ival = transparent[0];
2693 
2694       LOADPROMPTS3D("Last transparent color");
2695       uvalues[k].type = 'i';
2696       uvalues[k].uval.ival = transparent[1];
2697    }
2698 
2699    LOADPROMPTS3D("Randomize Colors      (0 - 7, '0' disables)");
2700    uvalues[k].type = 'i';
2701    uvalues[k++].uval.ival = RANDOMIZE;
2702 
2703    if (SPHERE)
2704       s = s1;
2705    else
2706       s = s2;
2707 
2708    helpmode = HELP3DPARMS;
2709    k = fullscreen_prompt(s,k,prompts3d,uvalues,0,NULL);
2710    helpmode = oldhelpmode;
2711    if (k < 0)
2712       goto restart_1;
2713 
2714    k = 0;
2715    if (!(RAY && !SPHERE))
2716    {
2717       XROT    = uvalues[k++].uval.ival;
2718       YROT    = uvalues[k++].uval.ival;
2719       ZROT    = uvalues[k++].uval.ival;
2720    }
2721    XSCALE     = uvalues[k++].uval.ival;
2722    YSCALE     = uvalues[k++].uval.ival;
2723    ROUGH      = uvalues[k++].uval.ival;
2724    WATERLINE  = uvalues[k++].uval.ival;
2725    if (!RAY)
2726    {
2727       ZVIEWER = uvalues[k++].uval.ival;
2728    XSHIFT     = uvalues[k++].uval.ival;
2729    YSHIFT     = uvalues[k++].uval.ival;
2730    xtrans     = uvalues[k++].uval.ival;
2731    ytrans     = uvalues[k++].uval.ival;
2732    transparent[0] = uvalues[k++].uval.ival;
2733    transparent[1] = uvalues[k++].uval.ival;
2734    }
2735    RANDOMIZE  = uvalues[k++].uval.ival;
2736    if (RANDOMIZE >= 7) RANDOMIZE = 7;
2737    if (RANDOMIZE <= 0) RANDOMIZE = 0;
2738 
2739    if ((Targa_Out || ILLUMINE || RAY))
2740         if(get_light_params())
2741             goto restart_3;
2742 #ifdef XFRACT
2743 unstackscreen();
2744 #endif
2745 return(0);
2746 }
2747 
2748 /* --------------------------------------------------------------------- */
get_light_params()2749 static int get_light_params()
2750 {
2751    static FCODE hdg[]={"Light Source Parameters"};
2752    char far *prompts3d[13];
2753    struct fullscreenvalues uvalues[13];
2754 
2755    int k;
2756    int oldhelpmode;
2757 
2758    /* defaults go here */
2759 
2760    k = -1;
2761 
2762    if (ILLUMINE || RAY)
2763    {
2764    LOADPROMPTS3D("X value light vector");
2765    uvalues[k].type = 'i';
2766    uvalues[k].uval.ival = XLIGHT    ;
2767 
2768    LOADPROMPTS3D("Y value light vector");
2769    uvalues[k].type = 'i';
2770    uvalues[k].uval.ival = YLIGHT    ;
2771 
2772    LOADPROMPTS3D("Z value light vector");
2773    uvalues[k].type = 'i';
2774    uvalues[k].uval.ival = ZLIGHT    ;
2775 
2776                 if (!RAY)
2777                 {
2778    LOADPROMPTS3D("Light Source Smoothing Factor");
2779    uvalues[k].type = 'i';
2780    uvalues[k].uval.ival = LIGHTAVG  ;
2781 
2782    LOADPROMPTS3D("Ambient");
2783    uvalues[k].type = 'i';
2784    uvalues[k].uval.ival = Ambient;
2785                 }
2786    }
2787 
2788    if (Targa_Out && !RAY)
2789    {
2790         LOADPROMPTS3D("Haze Factor        (0 - 100, '0' disables)");
2791         uvalues[k].type = 'i';
2792         uvalues[k].uval.ival= haze;
2793 
2794                 if (!Targa_Overlay)
2795         check_writefile(light_name,".tga");
2796       LOADPROMPTS3D("Targa File Name  (Assume .tga)");
2797         uvalues[k].type = 's';
2798         strcpy(uvalues[k].uval.sval,light_name);
2799 
2800       LOADPROMPTS3D("Back Ground Color (0 - 255)");
2801       uvalues[k].type = '*';
2802 
2803       LOADPROMPTS3D("   Red");
2804       uvalues[k].type = 'i';
2805       uvalues[k].uval.ival = (int)back_color[0];
2806 
2807       LOADPROMPTS3D("   Green");
2808       uvalues[k].type = 'i';
2809       uvalues[k].uval.ival = (int)back_color[1];
2810 
2811       LOADPROMPTS3D("   Blue");
2812       uvalues[k].type = 'i';
2813       uvalues[k].uval.ival = (int)back_color[2];
2814 
2815       LOADPROMPTS3D("Overlay Targa File? (Y/N)");
2816       uvalues[k].type = 'y';
2817       uvalues[k].uval.ch.val = Targa_Overlay;
2818 
2819    }
2820 
2821    LOADPROMPTS3D("");
2822 
2823    oldhelpmode = helpmode;
2824    helpmode = HELP3DLIGHT;
2825    k = fullscreen_prompt(hdg,k,prompts3d,uvalues,0,NULL);
2826    helpmode = oldhelpmode;
2827    if (k < 0)
2828       return(-1);
2829 
2830    k = 0;
2831    if (ILLUMINE)
2832    {
2833       XLIGHT   = uvalues[k++].uval.ival;
2834       YLIGHT   = uvalues[k++].uval.ival;
2835       ZLIGHT   = uvalues[k++].uval.ival;
2836       if (!RAY)
2837                 {
2838       LIGHTAVG = uvalues[k++].uval.ival;
2839       Ambient  = uvalues[k++].uval.ival;
2840       if (Ambient >= 100) Ambient = 100;
2841       if (Ambient <= 0) Ambient = 0;
2842                 }
2843    }
2844 
2845    if (Targa_Out && !RAY)
2846    {
2847         haze  =  uvalues[k++].uval.ival;
2848         if (haze >= 100) haze = 100;
2849         if (haze <= 0) haze = 0;
2850         strcpy(light_name,uvalues[k++].uval.sval);
2851                 /* In case light_name conflicts with an existing name it is checked
2852                         again in line3d */
2853                 k++;
2854         back_color[0] = (char)(uvalues[k++].uval.ival % 255);
2855         back_color[1] = (char)(uvalues[k++].uval.ival % 255);
2856         back_color[2] = (char)(uvalues[k++].uval.ival % 255);
2857         Targa_Overlay = uvalues[k].uval.ch.val;
2858    }
2859    return(0);
2860 }
2861 
2862 /* --------------------------------------------------------------------- */
2863 
2864 
check_mapfile()2865 static int check_mapfile()
2866 {
2867    int askflag = 0;
2868    int i,oldhelpmode;
2869    if(dontreadcolor)
2870       return(0);
2871    strcpy(temp1,"*");
2872    if (mapset)
2873       strcpy(temp1,MAP_name);
2874    if (!(glassestype == 1 || glassestype == 2))
2875       askflag = 1;
2876    else
2877       merge_pathnames(temp1,funnyglasses_map_name,0);
2878 
2879    for(;;) {
2880       if (askflag) {
2881          static FCODE msg[] = {"\
2882 Enter name of .MAP file to use,\n\
2883 or '*' to use palette from the image to be loaded."};
2884          oldhelpmode = helpmode;
2885          helpmode = -1;
2886          i = field_prompt(0,msg,NULL,temp1,60,NULL);
2887          helpmode = oldhelpmode;
2888          if (i < 0)
2889             return(-1);
2890          if (temp1[0] == '*') {
2891             mapset = 0;
2892             break;
2893          }
2894       }
2895       memcpy(olddacbox,dacbox,256*3); /* save the DAC */
2896       i = ValidateLuts(temp1);
2897       memcpy(dacbox,olddacbox,256*3); /* restore the DAC */
2898       if (i != 0) { /* Oops, somethings wrong */
2899          askflag = 1;
2900          continue;
2901          }
2902       mapset = 1;
2903       merge_pathnames(MAP_name,temp1,0);
2904       break;
2905       }
2906    return(0);
2907 }
2908 
get_funny_glasses_params()2909 static int get_funny_glasses_params()
2910 {
2911    static FCODE hdg[]={"Funny Glasses Parameters"};
2912    char far *prompts3d[10];
2913 
2914    struct fullscreenvalues uvalues[10];
2915 
2916    int k;
2917    int oldhelpmode;
2918 
2919    /* defaults */
2920    if(ZVIEWER == 0)
2921       ZVIEWER = 150;
2922    if(eyeseparation == 0)
2923    {
2924       if(fractype==IFS3D || fractype==LLORENZ3D || fractype==FPLORENZ3D)
2925       {
2926          eyeseparation =  2;
2927          xadjust       = -2;
2928       }
2929       else
2930       {
2931          eyeseparation =  3;
2932          xadjust       =  0;
2933       }
2934    }
2935 
2936    if(glassestype == 1)
2937       strcpy(funnyglasses_map_name,Glasses1Map);
2938    else if(glassestype == 2)
2939    {
2940       if(FILLTYPE == -1)
2941          strcpy(funnyglasses_map_name,"grid.map");
2942       else
2943       {
2944          strcpy(funnyglasses_map_name,Glasses1Map);
2945          funnyglasses_map_name[7] = '2';
2946       }
2947    }
2948 
2949    k = -1;
2950    LOADPROMPTS3D("Interocular distance (as % of screen)");
2951    uvalues[k].type = 'i';
2952    uvalues[k].uval.ival= eyeseparation;
2953 
2954    LOADPROMPTS3D("Convergence adjust (positive = spread greater)");
2955    uvalues[k].type = 'i';
2956    uvalues[k].uval.ival = xadjust;
2957 
2958    LOADPROMPTS3D("Left  red image crop (% of screen)");
2959    uvalues[k].type = 'i';
2960    uvalues[k].uval.ival = red_crop_left;
2961 
2962    LOADPROMPTS3D("Right red image crop (% of screen)");
2963    uvalues[k].type = 'i';
2964    uvalues[k].uval.ival = red_crop_right;
2965 
2966    LOADPROMPTS3D("Left  blue image crop (% of screen)");
2967    uvalues[k].type = 'i';
2968    uvalues[k].uval.ival = blue_crop_left;
2969 
2970    LOADPROMPTS3D("Right blue image crop (% of screen)");
2971    uvalues[k].type = 'i';
2972    uvalues[k].uval.ival = blue_crop_right;
2973 
2974    LOADPROMPTS3D("Red brightness factor (%)");
2975    uvalues[k].type = 'i';
2976    uvalues[k].uval.ival = red_bright;
2977 
2978    LOADPROMPTS3D("Blue brightness factor (%)");
2979    uvalues[k].type = 'i';
2980    uvalues[k].uval.ival = blue_bright;
2981 
2982    if(glassestype == 1 || glassestype == 2)
2983    {
2984       LOADPROMPTS3D("Map File name");
2985       uvalues[k].type = 's';
2986       strcpy(uvalues[k].uval.sval,funnyglasses_map_name);
2987    }
2988 
2989    oldhelpmode = helpmode;
2990    helpmode = HELP3DGLASSES;
2991    k = fullscreen_prompt(hdg,k+1,prompts3d,uvalues,0,NULL);
2992    helpmode = oldhelpmode;
2993    if (k < 0)
2994       return(-1);
2995 
2996    k = 0;
2997    eyeseparation   =  uvalues[k++].uval.ival;
2998    xadjust         =  uvalues[k++].uval.ival;
2999    red_crop_left   =  uvalues[k++].uval.ival;
3000    red_crop_right  =  uvalues[k++].uval.ival;
3001    blue_crop_left  =  uvalues[k++].uval.ival;
3002    blue_crop_right =  uvalues[k++].uval.ival;
3003    red_bright      =  uvalues[k++].uval.ival;
3004    blue_bright     =  uvalues[k++].uval.ival;
3005 
3006    if(glassestype == 1 || glassestype == 2)
3007       strcpy(funnyglasses_map_name,uvalues[k].uval.sval);
3008    return(0);
3009 }
3010 
setbailoutformula(enum bailouts test)3011 void setbailoutformula(enum bailouts test) {
3012 
3013    switch(test) {
3014      case Mod:
3015      default:{
3016          if (fpu >= 287 && debugflag != 72)     /* Fast 287 math */
3017            floatbailout = (int (near *)(void))asmfpMODbailout;
3018          else
3019            floatbailout = (int (near *)(void))fpMODbailout;
3020          if (cpu >=386 && debugflag != 8088)    /* Fast 386 math */
3021            longbailout = (int (near *)(void))asm386lMODbailout;
3022          else
3023            longbailout = (int (near *)(void))asmlMODbailout;
3024          bignumbailout = (int (near *)(void))bnMODbailout;
3025          bigfltbailout = (int (near *)(void))bfMODbailout;
3026          break;}
3027      case Real: {
3028          if (fpu >= 287 && debugflag != 72)     /* Fast 287 math */
3029            floatbailout = (int (near *)(void))asmfpREALbailout;
3030          else
3031            floatbailout = (int (near *)(void))fpREALbailout;
3032          if (cpu >=386 && debugflag != 8088)    /* Fast 386 math */
3033            longbailout = (int (near *)(void))asm386lREALbailout;
3034          else
3035            longbailout = (int (near *)(void))asmlREALbailout;
3036          bignumbailout = (int (near *)(void))bnREALbailout;
3037          bigfltbailout = (int (near *)(void))bfREALbailout;
3038          break;}
3039      case Imag:{
3040          if (fpu >= 287 && debugflag != 72)     /* Fast 287 math */
3041            floatbailout = (int (near *)(void))asmfpIMAGbailout;
3042          else
3043            floatbailout = (int (near *)(void))fpIMAGbailout;
3044          if (cpu >=386 && debugflag != 8088)    /* Fast 386 math */
3045            longbailout = (int (near *)(void))asm386lIMAGbailout;
3046          else
3047            longbailout = (int (near *)(void))asmlIMAGbailout;
3048          bignumbailout = (int (near *)(void))bnIMAGbailout;
3049          bigfltbailout = (int (near *)(void))bfIMAGbailout;
3050          break;}
3051      case Or:{
3052          if (fpu >= 287 && debugflag != 72)     /* Fast 287 math */
3053            floatbailout = (int (near *)(void))asmfpORbailout;
3054          else
3055            floatbailout = (int (near *)(void))fpORbailout;
3056          if (cpu >=386 && debugflag != 8088)    /* Fast 386 math */
3057            longbailout = (int (near *)(void))asm386lORbailout;
3058          else
3059            longbailout = (int (near *)(void))asmlORbailout;
3060          bignumbailout = (int (near *)(void))bnORbailout;
3061          bigfltbailout = (int (near *)(void))bfORbailout;
3062          break;}
3063      case And:{
3064          if (fpu >= 287 && debugflag != 72)     /* Fast 287 math */
3065            floatbailout = (int (near *)(void))asmfpANDbailout;
3066          else
3067            floatbailout = (int (near *)(void))fpANDbailout;
3068          if (cpu >=386 && debugflag != 8088)    /* Fast 386 math */
3069            longbailout = (int (near *)(void))asm386lANDbailout;
3070          else
3071            longbailout = (int (near *)(void))asmlANDbailout;
3072          bignumbailout = (int (near *)(void))bnANDbailout;
3073          bigfltbailout = (int (near *)(void))bfANDbailout;
3074          break;}
3075      case Manh:{
3076          if (fpu >= 287 && debugflag != 72)     /* Fast 287 math */
3077            floatbailout = (int (near *)(void))asmfpMANHbailout;
3078          else
3079            floatbailout = (int (near *)(void))fpMANHbailout;
3080          if (cpu >=386 && debugflag != 8088)    /* Fast 386 math */
3081            longbailout = (int (near *)(void))asm386lMANHbailout;
3082          else
3083            longbailout = (int (near *)(void))asmlMANHbailout;
3084          bignumbailout = (int (near *)(void))bnMANHbailout;
3085          bigfltbailout = (int (near *)(void))bfMANHbailout;
3086          break;}
3087      case Manr:{
3088          if (fpu >= 287 && debugflag != 72)     /* Fast 287 math */
3089            floatbailout = (int (near *)(void))asmfpMANRbailout;
3090          else
3091            floatbailout = (int (near *)(void))fpMANRbailout;
3092          if (cpu >=386 && debugflag != 8088)    /* Fast 386 math */
3093            longbailout = (int (near *)(void))asm386lMANRbailout;
3094          else
3095            longbailout = (int (near *)(void))asmlMANRbailout;
3096          bignumbailout = (int (near *)(void))bnMANRbailout;
3097          bigfltbailout = (int (near *)(void))bfMANRbailout;
3098          break;}
3099    }
3100 }
3101