File: common\miscres.c

    1 /*
    2         Resident odds and ends that don't fit anywhere else.
    3 */
    4 
    5 #include <string.h>
    6 #include <ctype.h>
    7 #include <time.h>
    8 #include <malloc.h>
    9 
   10 #ifndef XFRACT
   11 #include <io.h>
   12 #endif
   13 
   14 #ifndef USE_VARARGS
   15 #include <stdarg.h>
16 #else 17 #include <varargs.h>
18 #endif 19 20 /*#ifdef __TURBOC__ 21 #include <dir.h> 22 #endif */ 23 24 /* see Fractint.c for a description of the "include" hierarchy */ 25 #include "port.h" 26 #include "prototyp.h" 27 #include "fractype.h" 28 #include "helpdefs.h" 29 30 /* routines in this module */ 31 32 static void trigdetails(char *); 33 static void area(void); 34 35 /* TW's static string consolidation campaign to help brain-dead compilers */ 36 char s_cantwrite[] = {"Can't write %s"}; 37 char s_cantcreate[] = {"Can't create %s"}; 38 char s_cantunderstand[] = {"Can't understand %s"}; 39 char s_cantfind[] = {"Can't find %s"}; 40 41 #ifndef XFRACT 42 43 void findpath(char far *filename, char *fullpathname) /* return full pathnames */ 44 { 45 char fname[FILE_MAX_FNAME]; 46 char ext[FILE_MAX_EXT]; 47 char temp_path[FILE_MAX_PATH]; 48 49 splitpath(filename ,NULL,NULL,fname,ext); 50 makepath(temp_path,"" ,"" ,fname,ext); 51 52 if(checkcurdir != 0 && access(temp_path,0)==0) { /* file exists */ 53 strcpy(fullpathname,temp_path); 54 return; 55 } 56 57 far_strcpy(temp_path,filename); /* avoid side effect changes to filename */ 58 59 if (temp_path[0] == SLASHC || (temp_path[0] && temp_path[1] == ':')) { 60 if(access(temp_path,0)==0) { /* file exists */ 61 strcpy(fullpathname,temp_path); 62 return; 63 } 64 else { 65 splitpath(temp_path ,NULL,NULL,fname,ext); 66 makepath(temp_path,"" ,"" ,fname,ext); 67 } 68 } 69 fullpathname[0] = 0; /* indicate none found */ 70 /* #ifdef __TURBOC__ */ /* look for the file */ 71 /* strcpy(fullpathname,searchpath(temp_path)); */ 72 /* #else */ 73 _searchenv(temp_path,"PATH",fullpathname); 74 /* #endif */ 75 if (fullpathname[0] != 0) /* found it! */ 76 if (strncmp(&fullpathname[2],SLASHSLASH,2) == 0) /* stupid klooge! */ 77 strcpy(&fullpathname[3],temp_path); 78 } 79 #endif 80 81 82 void notdiskmsg() 83 { 84 static FCODE sorrymsg[]={ 85 "This type may be slow using a real-disk based 'video' mode, but may not \n\ 86 be too bad if you have enough expanded or extended memory. Press <Esc> to \n\ 87 abort if it appears that your disk drive is working too hard."}; 88 stopmsg(0,sorrymsg); 89 } 90 91 /* Wrapping version of putstring for long numbers */ 92 /* row -- pointer to row variable, internally incremented if needed */ 93 /* col1 -- starting column */ 94 /* col2 -- last column */ 95 /* color -- attribute (same as for putstring) */ 96 /* maxrow -- max number of rows to write */ 97 /* returns 0 if success, 1 if hit maxrow before done */ 98 int putstringwrap(int *row,int col1,int col2,int color,char far *str,int maxrow) 99 { 100 char save1, save2; 101 int length, decpt, padding, startrow, done; 102 done = 0; 103 startrow = *row; 104 length = far_strlen(str); 105 padding = 3; /* space between col1 and decimal. */ 106 /* find decimal point */ 107 for(decpt=0;decpt < length; decpt++) 108 if(str[decpt] == '.') 109 break; 110 if(decpt >= length) 111 decpt = 0; 112 if(decpt < padding) 113 padding -= decpt; 114 else 115 padding = 0; 116 col1 += padding; 117 decpt += col1+1; /* column just past where decimal is */ 118 while(length > 0) 119 { 120 if(col2-col1 < length) 121 { 122 if((*row - startrow + 1) >= maxrow) 123 done = 1; 124 else 125 done = 0; 126 save1 = str[col2-col1+1]; 127 save2 = str[col2-col1+2]; 128 if(done) 129 str[col2-col1+1] = '+'; 130 else 131 str[col2-col1+1] = '\\'; 132 str[col2-col1+2] = 0; 133 putstring(*row,col1,color,str); 134 if(done == 1) 135 break; 136 str[col2-col1+1] = save1; 137 str[col2-col1+2] = save2; 138 str += col2-col1; 139 (*row)++; 140 } else 141 putstring(*row,col1,color,str); 142 length -= col2-col1; 143 col1 = decpt; /* align with decimal */ 144 } 145 return(done); 146 } 147 148 #define rad_to_deg(x) ((x)*(180.0/PI)) /* most people "think" in degrees */ 149 #define deg_to_rad(x) ((x)*(PI/180.0)) 150 /* 151 convert corners to center/mag 152 Rotation angles indicate how much the IMAGE has been rotated, not the 153 zoom box. Same goes for the Skew angles 154 */ 155 156 #ifdef _MSC_VER 157 #pragma optimize( "", off ) 158 #endif 159 160 void cvtcentermag(double *Xctr, double *Yctr, LDBL *Magnification, double *Xmagfactor, double *Rotation, double *Skew) 161 { 162 double Width, Height; 163 double a, b; /* bottom, left, diagonal */ 164 double a2, b2, c2; /* squares of above */ 165 double tmpx1, tmpx2, tmpy1, tmpy2, tmpa; /* temporary x, y, angle */ 166 167 /* simple normal case first */ 168 if (xx3rd == xxmin && yy3rd == yymin) 169 { /* no rotation or skewing, but stretching is allowed */ 170 Width = xxmax - xxmin; 171 Height = yymax - yymin; 172 *Xctr = (xxmin + xxmax)/2.0; 173 *Yctr = (yymin + yymax)/2.0; 174 *Magnification = 2.0/Height; 175 *Xmagfactor = Height / (DEFAULTASPECT * Width); 176 *Rotation = 0.0; 177 *Skew = 0.0; 178 } 179 else 180 { 181 /* set up triangle ABC, having sides abc */ 182 /* side a = bottom, b = left, c = diagonal not containing (x3rd,y3rd) */ 183 tmpx1 = xxmax - xxmin; 184 tmpy1 = yymax - yymin; 185 c2 = tmpx1*tmpx1 + tmpy1*tmpy1; 186 187 tmpx1 = xxmax - xx3rd; 188 tmpy1 = yymin - yy3rd; 189 a2 = tmpx1*tmpx1 + tmpy1*tmpy1; 190 a = sqrt(a2); 191 *Rotation = -rad_to_deg(atan2( tmpy1, tmpx1 )); /* negative for image rotation */ 192 193 tmpx2 = xxmin - xx3rd; 194 tmpy2 = yymax - yy3rd; 195 b2 = tmpx2*tmpx2 + tmpy2*tmpy2; 196 b = sqrt(b2); 197 198 tmpa = acos((a2+b2-c2)/(2*a*b)); /* save tmpa for later use */ 199 *Skew = 90.0 - rad_to_deg(tmpa); 200 201 *Xctr = (xxmin + xxmax)*0.5; 202 *Yctr = (yymin + yymax)*0.5; 203 204 Height = b * sin(tmpa); 205 206 *Magnification = 2.0/Height; /* 1/(h/2) */ 207 *Xmagfactor = Height / (DEFAULTASPECT * a); 208 209 /* if vector_a cross vector_b is negative */ 210 /* then adjust for left-hand coordinate system */ 211 if ( tmpx1*tmpy2 - tmpx2*tmpy1 < 0 && debugflag != 4010) 212 { 213 *Skew = -*Skew; 214 *Xmagfactor = -*Xmagfactor; 215 *Magnification = -*Magnification; 216 } 217 } 218 /* just to make par file look nicer */ 219 if (*Magnification < 0) 220 { 221 *Magnification = -*Magnification; 222 *Rotation += 180; 223 } 224 #ifdef DEBUG
225 { 226 double txmin, txmax, tx3rd, tymin, tymax, ty3rd; 227 double error; 228 txmin = xxmin; 229 txmax = xxmax; 230 tx3rd = xx3rd; 231 tymin = yymin; 232 tymax = yymax; 233 ty3rd = yy3rd; 234 cvtcorners(*Xctr, *Yctr, *Magnification, *Xmagfactor, *Rotation, *Skew); 235 error = sqr(txmin - xxmin) + 236 sqr(txmax - xxmax) + 237 sqr(tx3rd - xx3rd) + 238 sqr(tymin - yymin) + 239 sqr(tymax - yymax) + 240 sqr(ty3rd - yy3rd); 241 if(error > .001) 242 showcornersdbl("cvtcentermag problem"); 243 xxmin = txmin; 244 xxmax = txmax; 245 xx3rd = tx3rd; 246 yymin = tymin; 247 yymax = tymax; 248 yy3rd = ty3rd; 249 }
250 #endif 251 return; 252 } 253 254 255 /* convert center/mag to corners */ 256 void cvtcorners(double Xctr, double Yctr, LDBL Magnification, double Xmagfactor, double Rotation, double Skew) 257 { 258 double x, y; 259 double h, w; /* half height, width */ 260 double tanskew, sinrot, cosrot; 261 262 if (Xmagfactor == 0.0) 263 Xmagfactor = 1.0; 264 265 h = (double)(1/Magnification); 266 w = h / (DEFAULTASPECT * Xmagfactor); 267 268 if (Rotation == 0.0 && Skew == 0.0) 269 { /* simple, faster case */ 270 xx3rd = xxmin = Xctr - w; 271 xxmax = Xctr + w; 272 yy3rd = yymin = Yctr - h; 273 yymax = Yctr + h; 274 return; 275 } 276 277 /* in unrotated, untranslated coordinate system */ 278 tanskew = tan(deg_to_rad(Skew)); 279 xxmin = -w + h*tanskew; 280 xxmax = w - h*tanskew; 281 xx3rd = -w - h*tanskew; 282 yymax = h; 283 yy3rd = yymin = -h; 284 285 /* rotate coord system and then translate it */ 286 Rotation = deg_to_rad(Rotation); 287 sinrot = sin(Rotation); 288 cosrot = cos(Rotation); 289 290 /* top left */ 291 x = xxmin * cosrot + yymax * sinrot; 292 y = -xxmin * sinrot + yymax * cosrot; 293 xxmin = x + Xctr; 294 yymax = y + Yctr; 295 296 /* bottom right */ 297 x = xxmax * cosrot + yymin * sinrot; 298 y = -xxmax * sinrot + yymin * cosrot; 299 xxmax = x + Xctr; 300 yymin = y + Yctr; 301 302 /* bottom left */ 303 x = xx3rd * cosrot + yy3rd * sinrot; 304 y = -xx3rd * sinrot + yy3rd * cosrot; 305 xx3rd = x + Xctr; 306 yy3rd = y + Yctr; 307 308 return; 309 } 310 311 /* convert corners to center/mag using bf */ 312 void cvtcentermagbf(bf_t Xctr, bf_t Yctr, LDBL *Magnification, double *Xmagfactor, double *Rotation, double *Skew) 313 { 314 /* needs to be LDBL or won't work past 307 (-DBL_MIN_10_EXP) or so digits */ 315 LDBL Width, Height; 316 LDBL a, b; /* bottom, left, diagonal */ 317 LDBL a2, b2, c2; /* squares of above */ 318 LDBL tmpx1, tmpx2, tmpy=0.0, tmpy1, tmpy2 ; 319 double tmpa; /* temporary x, y, angle */ 320 bf_t bfWidth, bfHeight; 321 bf_t bftmpx, bftmpy; 322 int saved; 323 int signx; 324 325 saved = save_stack(); 326 327 /* simple normal case first */ 328 /* if (xx3rd == xxmin && yy3rd == yymin) */ 329 if(!cmp_bf(bfx3rd, bfxmin) && !cmp_bf(bfy3rd, bfymin)) 330 { /* no rotation or skewing, but stretching is allowed */ 331 bfWidth = alloc_stack(bflength+2); 332 bfHeight = alloc_stack(bflength+2); 333 /* Width = xxmax - xxmin; */ 334 sub_bf(bfWidth, bfxmax, bfxmin); 335 Width = bftofloat(bfWidth); 336 /* Height = yymax - yymin; */ 337 sub_bf(bfHeight, bfymax, bfymin); 338 Height = bftofloat(bfHeight); 339 /* *Xctr = (xxmin + xxmax)/2; */ 340 add_bf(Xctr, bfxmin, bfxmax); 341 half_a_bf(Xctr); 342 /* *Yctr = (yymin + yymax)/2; */ 343 add_bf(Yctr, bfymin, bfymax); 344 half_a_bf(Yctr); 345 *Magnification = 2/Height; 346 *Xmagfactor = (double)(Height / (DEFAULTASPECT * Width)); 347 *Rotation = 0.0; 348 *Skew = 0.0; 349 } 350 else 351 { 352 bftmpx = alloc_stack(bflength+2); 353 bftmpy = alloc_stack(bflength+2); 354 355 /* set up triangle ABC, having sides abc */ 356 /* side a = bottom, b = left, c = diagonal not containing (x3rd,y3rd) */ 357 /* IMPORTANT: convert from bf AFTER subtracting */ 358 359 /* tmpx = xxmax - xxmin; */ 360 sub_bf(bftmpx, bfxmax, bfxmin); 361 tmpx1 = bftofloat(bftmpx); 362 /* tmpy = yymax - yymin; */ 363 sub_bf(bftmpy, bfymax, bfymin); 364 tmpy1 = bftofloat(bftmpy); 365 c2 = tmpx1*tmpx1 + tmpy1*tmpy1; 366 367 /* tmpx = xxmax - xx3rd; */ 368 sub_bf(bftmpx, bfxmax, bfx3rd); 369 tmpx1 = bftofloat(bftmpx); 370 371 /* tmpy = yymin - yy3rd; */ 372 sub_bf(bftmpy, bfymin, bfy3rd); 373 tmpy1 = bftofloat(bftmpy); 374 a2 = tmpx1*tmpx1 + tmpy1*tmpy1; 375 a = sqrtl(a2); 376 377 /* divide tmpx and tmpy by |tmpx| so that double version of atan2() can be used */ 378 /* atan2() only depends on the ratio, this puts it in double's range */ 379 signx = sign(tmpx1); 380 if(signx) 381 tmpy = tmpy1/tmpx1 * signx; /* tmpy = tmpy / |tmpx| */ 382 *Rotation = (double)(-rad_to_deg(atan2( (double)tmpy, signx ))); /* negative for image rotation */ 383 384 /* tmpx = xxmin - xx3rd; */ 385 sub_bf(bftmpx, bfxmin, bfx3rd); 386 tmpx2 = bftofloat(bftmpx); 387 /* tmpy = yymax - yy3rd; */ 388 sub_bf(bftmpy, bfymax, bfy3rd); 389 tmpy2 = bftofloat(bftmpy); 390 b2 = tmpx2*tmpx2 + tmpy2*tmpy2; 391 b = sqrtl(b2); 392 393 tmpa = acos((double)((a2+b2-c2)/(2*a*b))); /* save tmpa for later use */ 394 *Skew = 90 - rad_to_deg(tmpa); 395 396 /* these are the only two variables that must use big precision */ 397 /* *Xctr = (xxmin + xxmax)/2; */ 398 add_bf(Xctr, bfxmin, bfxmax); 399 half_a_bf(Xctr); 400 /* *Yctr = (yymin + yymax)/2; */ 401 add_bf(Yctr, bfymin, bfymax); 402 half_a_bf(Yctr); 403 404 Height = b * sin(tmpa); 405 *Magnification = 2/Height; /* 1/(h/2) */ 406 *Xmagfactor = (double)(Height / (DEFAULTASPECT * a)); 407 408 /* if vector_a cross vector_b is negative */ 409 /* then adjust for left-hand coordinate system */ 410 if ( tmpx1*tmpy2 - tmpx2*tmpy1 < 0 && debugflag != 4010) 411 { 412 *Skew = -*Skew; 413 *Xmagfactor = -*Xmagfactor; 414 *Magnification = -*Magnification; 415 } 416 } 417 if (*Magnification < 0) 418 { 419 *Magnification = -*Magnification; 420 *Rotation += 180; 421 } 422 restore_stack(saved); 423 return; 424 } 425 426 427 /* convert center/mag to corners using bf */ 428 void cvtcornersbf(bf_t Xctr, bf_t Yctr, LDBL Magnification, double Xmagfactor, double Rotation, double Skew) 429 { 430 LDBL x, y; 431 LDBL h, w; /* half height, width */ 432 LDBL xmin, ymin, xmax, ymax, x3rd, y3rd; 433 double tanskew, sinrot, cosrot; 434 bf_t bfh, bfw; 435 bf_t bftmp; 436 int saved; 437 438 saved = save_stack(); 439 bfh = alloc_stack(bflength+2); 440 bfw = alloc_stack(bflength+2); 441 442 if (Xmagfactor == 0.0) 443 Xmagfactor = 1.0; 444 445 h = 1/Magnification; 446 floattobf(bfh, h); 447 w = h / (DEFAULTASPECT * Xmagfactor); 448 floattobf(bfw, w); 449 450 if (Rotation == 0.0 && Skew == 0.0) 451 { /* simple, faster case */ 452 /* xx3rd = xxmin = Xctr - w; */ 453 sub_bf(bfxmin, Xctr, bfw); 454 copy_bf(bfx3rd, bfxmin); 455 /* xxmax = Xctr + w; */ 456 add_bf(bfxmax, Xctr, bfw); 457 /* yy3rd = yymin = Yctr - h; */ 458 sub_bf(bfymin, Yctr, bfh); 459 copy_bf(bfy3rd, bfymin); 460 /* yymax = Yctr + h; */ 461 add_bf(bfymax, Yctr, bfh); 462 restore_stack(saved); 463 return; 464 } 465 466 bftmp = alloc_stack(bflength+2); 467 /* in unrotated, untranslated coordinate system */ 468 tanskew = tan(deg_to_rad(Skew)); 469 xmin = -w + h*tanskew; 470 xmax = w - h*tanskew; 471 x3rd = -w - h*tanskew; 472 ymax = h; 473 y3rd = ymin = -h; 474 475 /* rotate coord system and then translate it */ 476 Rotation = deg_to_rad(Rotation); 477 sinrot = sin(Rotation); 478 cosrot = cos(Rotation); 479 480 /* top left */ 481 x = xmin * cosrot + ymax * sinrot; 482 y = -xmin * sinrot + ymax * cosrot; 483 /* xxmin = x + Xctr; */ 484 floattobf(bftmp, x); 485 add_bf(bfxmin, bftmp, Xctr); 486 /* yymax = y + Yctr; */ 487 floattobf(bftmp, y); 488 add_bf(bfymax, bftmp, Yctr); 489 490 /* bottom right */ 491 x = xmax * cosrot + ymin * sinrot; 492 y = -xmax * sinrot + ymin * cosrot; 493 /* xxmax = x + Xctr; */ 494 floattobf(bftmp, x); 495 add_bf(bfxmax, bftmp, Xctr); 496 /* yymin = y + Yctr; */ 497 floattobf(bftmp, y); 498 add_bf(bfymin, bftmp, Yctr); 499 500 /* bottom left */ 501 x = x3rd * cosrot + y3rd * sinrot; 502 y = -x3rd * sinrot + y3rd * cosrot; 503 /* xx3rd = x + Xctr; */ 504 floattobf(bftmp, x); 505 add_bf(bfx3rd, bftmp, Xctr); 506 /* yy3rd = y + Yctr; */ 507 floattobf(bftmp, y); 508 add_bf(bfy3rd, bftmp, Yctr); 509 510 restore_stack(saved); 511 return; 512 } 513 514 #ifdef _MSC_VER 515 #pragma optimize( "", on ) 516 #endif 517 518 void updatesavename(char *filename) /* go to the next file name */ 519 { 520 char *save, *hold; 521 char drive[FILE_MAX_DRIVE]; 522 char dir[FILE_MAX_DIR]; 523 char fname[FILE_MAX_FNAME]; 524 char ext[FILE_MAX_EXT]; 525 526 splitpath(filename ,drive,dir,fname,ext); 527 528 hold = fname + strlen(fname) - 1; /* start at the end */ 529 while(hold >= fname && (*hold == ' ' || isdigit(*hold))) /* skip backwards */ 530 hold--; 531 hold++; /* recover first digit */ 532 while (*hold == '0') /* skip leading zeros */ 533 hold++; 534 save = hold; 535 while (*save) { /* check for all nines */ 536 if (*save != '9') 537 break; 538 save++; 539 } 540 if (!*save) /* if the whole thing is nines then back */ 541 save = hold - 1; /* up one place. Note that this will eat */ 542 /* your last letter if you go to far. */ 543 else 544 save = hold; 545 sprintf(save,"%ld",atol(hold)+1); /* increment the number */ 546 makepath(filename,drive,dir,fname,ext); 547 } 548 549 int check_writefile(char *name,char *ext) 550 { 551 /* after v16 release, change encoder.c to also use this routine */ 552 char openfile[FILE_MAX_DIR]; 553 char opentype[20]; 554 /* int i; */ 555 char *period; 556 nextname: 557 strcpy(openfile,name); 558 strcpy(opentype,ext); 559 #if 0
560 for (i = 0; i < (int)strlen(openfile); i++) 561 if (openfile[i] == '.') { 562 strcpy(opentype,&openfile[i]); 563 openfile[i] = 0; 564 }
565 #endif 566 if((period = has_ext(openfile)) != NULL) 567 { 568 strcpy(opentype,period); 569 *period = 0; 570 } 571 strcat(openfile,opentype); 572 if (access(openfile,0) != 0) /* file doesn't exist */ 573 { 574 strcpy(name,openfile); 575 return 0; 576 } 577 /* file already exists */ 578 if (overwrite == 0) { 579 updatesavename(name); 580 goto nextname; 581 } 582 return 1; 583 } 584 585 /* ('check_key()' was moved to FRACTINT.C for MSC7-overlay speed purposes) */ 586 /* ('timer()' was moved to FRACTINT.C for MSC7-overlay speed purposes) */ 587 588 BYTE trigndx[] = {SIN,SQR,SINH,COSH}; 589 #ifndef XFRACT 590 void (*ltrig0)(void) = lStkSin; 591 void (*ltrig1)(void) = lStkSqr; 592 void (*ltrig2)(void) = lStkSinh; 593 void (*ltrig3)(void) = lStkCosh; 594 void (*mtrig0)(void) = mStkSin; 595 void (*mtrig1)(void) = mStkSqr; 596 void (*mtrig2)(void) = mStkSinh; 597 void (*mtrig3)(void) = mStkCosh; 598 #endif 599 void (*dtrig0)(void) = dStkSin; 600 void (*dtrig1)(void) = dStkSqr; 601 void (*dtrig2)(void) = dStkSinh; 602 void (*dtrig3)(void) = dStkCosh; 603 604 /* struct trig_funct_lst trigfn[] was moved to prompts1.c */ 605 606 void showtrig(char *buf) /* return display form of active trig functions */ 607 { 608 char tmpbuf[30]; 609 *buf = 0; /* null string if none */ 610 trigdetails(tmpbuf); 611 if (tmpbuf[0]) 612 sprintf(buf," function=%s",tmpbuf); 613 } 614 615 static void trigdetails(char *buf) 616 { 617 int i, numfn; 618 char tmpbuf[20]; 619 if(fractype==JULIBROT || fractype==JULIBROTFP) 620 numfn = (fractalspecific[neworbittype].flags >> 6) & 7; 621 else 622 numfn = (curfractalspecific->flags >> 6) & 7; 623 if(curfractalspecific == &fractalspecific[FORMULA] || 624 curfractalspecific == &fractalspecific[FFORMULA] ) 625 numfn = maxfn; 626 *buf = 0; /* null string if none */ 627 if (numfn>0) { 628 strcpy(buf,trigfn[trigndx[0]].name); 629 i = 0; 630 while(++i < numfn) { 631 sprintf(tmpbuf,"/%s",trigfn[trigndx[i]].name); 632 strcat(buf,tmpbuf); 633 } 634 } 635 } 636 637 /* set array of trig function indices according to "function=" command */ 638 int set_trig_array(int k, char *name) 639 { 640 char trigname[10]; 641 int i; 642 char *slash; 643 strncpy(trigname,name,6); 644 trigname[6] = 0; /* safety first */ 645 646 if ((slash = strchr(trigname,'/')) != NULL) 647 *slash = 0; 648 649 strlwr(trigname); 650 651 for(i=0;i<numtrigfn;i++) 652 { 653 if(strcmp(trigname,trigfn[i].name)==0) 654 { 655 trigndx[k] = (BYTE)i; 656 set_trig_pointers(k); 657 break; 658 } 659 } 660 return(0); 661 } 662 void set_trig_pointers(int which) 663 { 664 /* set trig variable functions to avoid array lookup time */ 665 int i; 666 switch(which) 667 { 668 case 0: 669 #ifndef XFRACT 670 ltrig0 = trigfn[trigndx[0]].lfunct; 671 mtrig0 = trigfn[trigndx[0]].mfunct; 672 #endif 673 dtrig0 = trigfn[trigndx[0]].dfunct; 674 break; 675 case 1: 676 #ifndef XFRACT 677 ltrig1 = trigfn[trigndx[1]].lfunct; 678 mtrig1 = trigfn[trigndx[1]].mfunct; 679 #endif 680 dtrig1 = trigfn[trigndx[1]].dfunct; 681 break; 682 case 2: 683 #ifndef XFRACT 684 ltrig2 = trigfn[trigndx[2]].lfunct; 685 mtrig2 = trigfn[trigndx[2]].mfunct; 686 #endif 687 dtrig2 = trigfn[trigndx[2]].dfunct; 688 break; 689 case 3: 690 #ifndef XFRACT 691 ltrig3 = trigfn[trigndx[3]].lfunct; 692 mtrig3 = trigfn[trigndx[3]].mfunct; 693 #endif 694 dtrig3 = trigfn[trigndx[3]].dfunct; 695 break; 696 default: /* do 'em all */ 697 for(i=0;i<4;i++) 698 set_trig_pointers(i); 699 break; 700 } 701 } 702 703 static FCODE sfractal_type[] = {"Fractal type:"}; 704 static FCODE sitem_name[] = {"Item name:"}; 705 static FCODE sitem_file[] = {"Item file:"}; 706 static FCODE s3D_transform[] = {"3D Transform"}; 707 static FCODE syou_are_cycling[] = {"You are in color-cycling mode"}; 708 static FCODE sfloating_point[] = {"Floating-point"}; 709 static FCODE ssolid_guessing[] = {"Solid Guessing"}; 710 static FCODE sboundary_tracing[] = {"Boundary Tracing"}; 711 static FCODE stesseral[] = {"Tesseral"}; 712 static FCODE sdiffusion[] = {"Diffusion"}; 713 static FCODE sorbits[] = {"Orbits"}; 714 static FCODE scalculation_time[] = {"Calculation time:"}; 715 static FCODE siterations[] = {" 1000's of points:"}; 716 static FCODE scornersxy[] = {"Corners: X Y"}; 717 static FCODE stop_left[] = {"Top-l"}; 718 static FCODE sbottom_right[] = {"Bot-r"}; 719 static FCODE sbottom_left[] = {"Bot-l"}; 720 static FCODE scenter[] = {"Ctr"}; 721 static FCODE struncate[] = {"(Center values shown truncated to 320 decimals)"}; 722 static FCODE smag[] = {"Mag"}; 723 static FCODE sxmag[] = {"X-Mag-Factor"}; 724 static FCODE srot[] = {"Rotation"}; 725 static FCODE sskew[] = {"Skew"}; 726 static FCODE sparams[] = {"Params "}; 727 static FCODE siteration_maximum[] ={"Current (Max) Iteration: "}; 728 static FCODE seffective_bailout[] ={" Effective bailout: "}; 729 static FCODE scurrent_rseed[] = {"Current 'rseed': "}; 730 static FCODE sinversion_radius[] = {"Inversion radius: "}; 731 static FCODE sxcenter[] = {" xcenter: "}; 732 static FCODE sycenter[] = {" ycenter: "}; 733 static FCODE sparms_chgd[] = {"Parms chgd since generated"}; 734 static FCODE sstill_being[] = {"Still being generated"}; 735 static FCODE sinterrupted_resumable[] = {"Interrupted, resumable"}; 736 static FCODE sinterrupted_non_resumable[] = {"Interrupted, non-resumable"}; 737 static FCODE simage_completed[] = {"Image completed"}; 738 static FCODE sflag_is_activated[] = {" flag is activated"}; 739 static FCODE sinteger_math[] = {"Integer math is in use"}; 740 static FCODE sin_use_required[] = {" in use (required)"}; 741 static FCODE sarbitrary_precision[] = {"Arbitrary precision "}; 742 #ifdef XFRACT
743 static FCODE spressanykey[] = {"Press any key to continue, F6 for area, F7 for next page"};
744 #else 745 static FCODE spressanykey[] = {"Press any key to continue, F6 for area, CTRL-TAB for next page"}; 746 #endif 747 static FCODE spressanykey1[] = {"Press Esc to continue, Backspace for first screen"}; 748 static FCODE sbatch[] = {" (Batch mode)"}; 749 static FCODE ssavename[] = {"Savename: "}; 750 static FCODE sstopsecret[] = {"Top Secret Developer's Screen"}; 751 static FCODE sthreepass[] = {" (threepass)"}; 752 static FCODE sreallylongtime[] = {"A long time! (> 24.855 days)"}; 753 754 void get_calculation_time(char *msg, long ctime) 755 { 756 if (ctime >= 0) 757 { 758 sprintf(msg,"%3ld:%02ld:%02ld.%02ld", ctime/360000L, 759 (ctime%360000L)/6000, (ctime%6000)/100, ctime%100); 760 } 761 else 762 far_strcpy(msg,sreallylongtime); 763 } 764 765 static void show_str_var(char *name, char *var, int *row, char *msg) 766 { 767 if(var == NULL) 768 return; 769 if(*var != 0) 770 { 771 sprintf(msg,"%s=%s",name,var); 772 putstring((*row)++,2,C_GENERAL_HI,msg); 773 } 774 } 775 776 int tab_display_2(char *msg) 777 { 778 extern long maxptr, maxstack, startstack; 779 int s_row,key,ret=0; 780 helptitle(); 781 setattr(1,0,C_GENERAL_MED,24*80); /* init rest to background */ 782 783 s_row = 1; 784 putstringcenter(s_row++,0,80,C_PROMPT_HI, sstopsecret); 785 sprintf(msg,"Version %d patch %d",release, patchlevel); 786 putstring(++s_row,2,C_GENERAL_HI,msg); 787 sprintf(msg,"%lu bytes conventional stack free",stackavail()); 788 putstring(++s_row,2,C_GENERAL_HI,msg); 789 sprintf(msg,"%ld of %ld bignum memory used",maxptr,maxstack); 790 putstring(++s_row,2,C_GENERAL_HI,msg); 791 sprintf(msg," %ld used for bignum globals", startstack); 792 putstring(++s_row,2,C_GENERAL_HI,msg); 793 sprintf(msg," %ld stack used == %ld variables of length %d", 794 maxptr-startstack,(long)((maxptr-startstack)/(rbflength+2)),rbflength+2); 795 putstring(++s_row,2,C_GENERAL_HI,msg); 796 if(bf_math) 797 { 798 sprintf(msg,"intlength %-d bflength %-d ",intlength, bflength); 799 putstring(++s_row,2,C_GENERAL_HI,msg); 800 } 801 s_row++; 802 show_str_var(s_tempdir, tempdir, &s_row, msg); 803 show_str_var(s_workdir, workdir, &s_row, msg); 804 show_str_var(s_printfile, PrintName, &s_row, msg); 805 show_str_var(s_filename, readname, &s_row, msg); 806 show_str_var(s_formulafile,FormFileName, &s_row, msg); 807 show_str_var(s_savename, savename, &s_row, msg); 808 show_str_var(s_parmfile, CommandFile, &s_row, msg); 809 show_str_var(s_ifsfile, IFSFileName, &s_row, msg); 810 show_str_var(s_autokeyname,autoname, &s_row, msg); 811 show_str_var(s_lightname, light_name, &s_row, msg); 812 show_str_var(s_map, MAP_name, &s_row, msg); 813 sprintf(msg,"Sizeof fractalspecific array %d", 814 num_fractal_types*(int)sizeof(struct fractalspecificstuff)); 815 putstring(s_row++,2,C_GENERAL_HI,msg); 816 sprintf(msg,"calc_status %d pixel [%d,%d]",calc_status,col,row); 817 putstring(s_row++,2,C_GENERAL_HI,msg); 818 if(fractype==FORMULA || fractype==FFORMULA) 819 { 820 sprintf(msg,"total_formula_mem %ld Max_Ops (posp) %u Max_Args (vsp) %u Used_extra %u", 821 total_formula_mem,posp,vsp,used_extra); 822 putstring(s_row++,2,C_GENERAL_HI,msg); 823 sprintf(msg," Store ptr %d Loadptr %d Max_Ops var %u Max_Args var %u LastInitOp %d", 824 StoPtr,LodPtr,Max_Ops,Max_Args,LastInitOp); 825 putstring(s_row++,2,C_GENERAL_HI,msg); 826 } 827 else if(rhombus_stack[0]) 828 { 829 sprintf(msg,"SOI Recursion %d stack free %d %d %d %d %d %d %d %d %d %d", 830 max_rhombus_depth+1, 831 rhombus_stack[0], 832 rhombus_stack[1], 833 rhombus_stack[2], 834 rhombus_stack[3], 835 rhombus_stack[4], 836 rhombus_stack[5], 837 rhombus_stack[6], 838 rhombus_stack[7], 839 rhombus_stack[8], 840 rhombus_stack[9]); 841 putstring(s_row++,2,C_GENERAL_HI,msg); 842 } 843 844 /* 845 sprintf(msg,"xdots %d ydots %d sxdots %d sydots %d",xdots,ydots,sxdots,sydots); 846 putstring(s_row++,2,C_GENERAL_HI,msg); 847 */ 848 sprintf(msg,"xxstart %d xxstop %d yystart %d yystop %d %s uses_ismand %d", 849 xxstart,xxstop,yystart,yystop, 850 #ifndef XFRACT 851 curfractalspecific->orbitcalc == fFormula?"fast parser": 852 #endif 853 curfractalspecific->orbitcalc == Formula?"slow parser": 854 curfractalspecific->orbitcalc == BadFormula?"bad formula": 855 "",uses_ismand); 856 putstring(s_row++,2,C_GENERAL_HI,msg); 857 /* 858 sprintf(msg,"ixstart %d ixstop %d iystart %d iystop %d bitshift %d", 859 ixstart,ixstop,iystart,iystop,bitshift); 860 */ 861 { 862 sprintf(msg,"minstackavail %d llimit2 %ld use_grid %d", 863 minstackavail,llimit2,use_grid); 864 } 865 putstring(s_row++,2,C_GENERAL_HI,msg); 866 putstringcenter(24,0,80,C_GENERAL_LO,spressanykey1); 867 *msg = 0; 868 again: 869 putstring(s_row,2,C_GENERAL_HI,msg); 870 key=getakeynohelp(); 871 if(key != ESC && key != BACKSPACE && key != TAB) 872 { 873 sprintf(msg,"%d ",key); 874 goto again; 875 } 876 if(key == BACKSPACE || key == TAB) 877 ret = 1; 878 return(ret); 879 } 880 881 int tab_display() /* display the status of the current image */ 882 { 883 int s_row, i, j, addrow=0; 884 double Xctr, Yctr; 885 LDBL Magnification; 886 double Xmagfactor, Rotation, Skew; 887 bf_t bfXctr=NULL, bfYctr=NULL; 888 char msg[350]; 889 char far *msgptr; 890 int key; 891 int saved=0; 892 int dec; 893 int k; 894 U16 save_extra_handle = 0; 895 BYTE far *ptr_to_extraseg = NULL; 896 int hasformparam = 0; 897 898 if (calc_status < 0) { /* no active fractal image */ 899 return(0); /* (no TAB on the credits screen) */ 900 } 901 if (calc_status == 1) /* next assumes CLK_TCK is 10^n, n>=2 */ 902 calctime += (clock_ticks() - timer_start) / (CLK_TCK/100); 903 stackscreen(); 904 if(bf_math) 905 { 906 /* Save memory from the beginning of extraseg to ENDVID=22400 */ 907 /* This is so the bf_math manipulations here don't corrupt */ 908 /* the video modes or screen prompts. */ 909 ptr_to_extraseg = MK_FP(extraseg,0); 910 save_extra_handle = MemoryAlloc((U16)22400, 1L, FARMEM); 911 MoveToMemory(ptr_to_extraseg,(U16)22400,1L,0L,save_extra_handle); 912 saved = save_stack(); 913 bfXctr = alloc_stack(bflength+2); 914 bfYctr = alloc_stack(bflength+2); 915 } 916 if (fractype == FORMULA || fractype == FFORMULA) 917 for (i = 0; i < MAXPARAMS; i += 2) 918 if (!paramnotused(i)) 919 hasformparam++; 920 top: 921 k = 0; /* initialize here so parameter line displays correctly on return 922 from control-tab */ 923 helptitle(); 924 setattr(1,0,C_GENERAL_MED,24*80); /* init rest to background */ 925 s_row = 2; 926 putstring(s_row,2,C_GENERAL_MED,sfractal_type); 927 if (display3d > 0) 928 putstring(s_row,16,C_GENERAL_HI,s3D_transform); 929 else { 930 putstring(s_row,16,C_GENERAL_HI, 931 curfractalspecific->name[0] == '*' ? 932 &curfractalspecific->name[1] : 933 curfractalspecific->name); 934 i = 0; 935 if (fractype == FORMULA || fractype == FFORMULA) 936 { 937 putstring(s_row+1,3,C_GENERAL_MED,sitem_name); 938 putstring(s_row+1,16,C_GENERAL_HI,FormName); 939 i = strlen(FormName)+1; 940 putstring(s_row+2,3,C_GENERAL_MED,sitem_file); 941 if((int)strlen(FormFileName) >= 29) 942 addrow = 1; 943 putstring(s_row+2+addrow,16,C_GENERAL_HI,FormFileName); 944 } 945 trigdetails(msg); 946 putstring(s_row+1,16+i,C_GENERAL_HI,msg); 947 if (fractype == LSYSTEM) 948 { 949 putstring(s_row+1,3,C_GENERAL_MED,sitem_name); 950 putstring(s_row+1,16,C_GENERAL_HI,LName); 951 putstring(s_row+2,3,C_GENERAL_MED,sitem_file); 952 if((int)strlen(LFileName) >= 28) 953 addrow = 1; 954 putstring(s_row+2+addrow,16,C_GENERAL_HI,LFileName); 955 } 956 if (fractype == IFS || fractype == IFS3D) 957 { 958 putstring(s_row+1,3,C_GENERAL_MED,sitem_name); 959 putstring(s_row+1,16,C_GENERAL_HI,IFSName); 960 putstring(s_row+2,3,C_GENERAL_MED,sitem_file); 961 if((int)strlen(IFSFileName) >= 28) 962 addrow = 1; 963 putstring(s_row+2+addrow,16,C_GENERAL_HI,IFSFileName); 964 } 965 } 966 967 switch (calc_status) { 968 case 0: msgptr = sparms_chgd; 969 break; 970 case 1: msgptr = sstill_being; 971 break; 972 case 2: msgptr = sinterrupted_resumable; 973 break; 974 case 3: msgptr = sinterrupted_non_resumable; 975 break; 976 case 4: msgptr = simage_completed; 977 break; 978 default: msgptr = ""; 979 } 980 putstring(s_row,45,C_GENERAL_HI,msgptr); 981 if(initbatch && calc_status != 0) 982 putstring(-1,-1,C_GENERAL_HI,sbatch); 983 984 if (helpmode == HELPCYCLING) 985 putstring(s_row+1,45,C_GENERAL_HI,syou_are_cycling); 986 ++s_row; 987 /* if(bf_math == 0) */ 988 ++s_row; 989 990 i = j = 0; 991 if (display3d > 0) { 992 if (usr_floatflag) 993 j = 1; 994 } 995 else 996 if (floatflag) 997 j = (usr_floatflag) ? 1 : 2; 998 if(bf_math==0) 999 { 1000 if (j) { 1001 putstring(s_row,45,C_GENERAL_HI,sfloating_point); 1002 1003 putstring(-1,-1,C_GENERAL_HI,(j == 1) ? sflag_is_activated 1004 : sin_use_required ); 1005 i = 1; 1006 } 1007 else 1008 { 1009 putstring(s_row,45,C_GENERAL_HI,sinteger_math); 1010 i = 1; 1011 } 1012 } else 1013 { 1014 sprintf(msg,"(%-d decimals)",decimals /*getprecbf(CURRENTREZ)*/); 1015 putstring(s_row,45,C_GENERAL_HI,sarbitrary_precision); 1016 putstring(-1,-1,C_GENERAL_HI,msg); 1017 1018 i = 1; 1019 } 1020 1021 s_row += i; 1022 1023 if (calc_status == 1 || calc_status == 2) 1024 if (curfractalspecific->flags&NORESUME) 1025 { 1026 static FCODE msg[] = {"Note: can't resume this type after interrupts other than <tab> and <F1>"}; 1027 putstring(s_row++,2,C_GENERAL_HI,msg); 1028 } 1029 s_row += addrow; 1030 putstring(s_row,2,C_GENERAL_MED,ssavename); 1031 putstring(s_row,-1,C_GENERAL_HI,savename); 1032 1033 /* if(bf_math == 0) */ 1034 ++s_row; 1035 1036 if (got_status >= 0 && (calc_status == 1 || calc_status == 2)) { 1037 switch (got_status) { 1038 case 0: 1039 sprintf(msg,"%d Pass Mode",totpasses); 1040 putstring(s_row,2,C_GENERAL_HI,msg); 1041 if(usr_stdcalcmode=='3') 1042 putstring(s_row,-1,C_GENERAL_HI,sthreepass); 1043 break; 1044 case 1: 1045 putstring(s_row,2,C_GENERAL_HI,ssolid_guessing); 1046 if(usr_stdcalcmode=='3') 1047 putstring(s_row,-1,C_GENERAL_HI,sthreepass); 1048 break; 1049 case 2: 1050 putstring(s_row,2,C_GENERAL_HI,sboundary_tracing); 1051 break; 1052 case 3: 1053 sprintf(msg,"Processing row %d (of %d) of input image",currow,fileydots); 1054 putstring(s_row,2,C_GENERAL_HI,msg); 1055 break; 1056 case 4: 1057 putstring(s_row,2,C_GENERAL_HI,stesseral); 1058 break; 1059 case 5: 1060 putstring(s_row,2,C_GENERAL_HI,sdiffusion); 1061 break; 1062 case 6: 1063 putstring(s_row,2,C_GENERAL_HI,sorbits); 1064 break; 1065 } 1066 ++s_row; 1067 if (got_status == 5 ) { 1068 sprintf(msg,"%2.2f%% done, counter at %lu of %lu (%u bits)", 1069 (100.0 * dif_counter)/dif_limit, 1070 dif_counter,dif_limit,bits); 1071 putstring(s_row,2,C_GENERAL_MED,msg); 1072 ++s_row; 1073 } else 1074 if (got_status != 3) { 1075 sprintf(msg,"Working on block (y,x) [%d,%d]...[%d,%d], ", 1076 yystart,xxstart,yystop,xxstop); 1077 putstring(s_row,2,C_GENERAL_MED,msg); 1078 if (got_status == 2 || got_status == 4) { /* btm or tesseral */ 1079 putstring(-1,-1,C_GENERAL_MED,"at "); 1080 sprintf(msg,"[%d,%d]",currow,curcol); 1081 putstring(-1,-1,C_GENERAL_HI,msg); 1082 } 1083 else { 1084 if (totpasses > 1) { 1085 putstring(-1,-1,C_GENERAL_MED,"pass "); 1086 sprintf(msg,"%d",curpass); 1087 putstring(-1,-1,C_GENERAL_HI,msg); 1088 putstring(-1,-1,C_GENERAL_MED," of "); 1089 sprintf(msg,"%d",totpasses); 1090 putstring(-1,-1,C_GENERAL_HI,msg); 1091 putstring(-1,-1,C_GENERAL_MED,", "); 1092 } 1093 putstring(-1,-1,C_GENERAL_MED,"at row "); 1094 sprintf(msg,"%d",currow); 1095 putstring(-1,-1,C_GENERAL_HI,msg); 1096 putstring(-1,-1,C_GENERAL_MED," col "); 1097 sprintf(msg,"%d",col); 1098 putstring(-1,-1,C_GENERAL_HI,msg); 1099 } 1100 ++s_row; 1101 } 1102 } 1103 putstring(s_row,2,C_GENERAL_MED,scalculation_time); 1104 get_calculation_time(msg,calctime); 1105 putstring(-1,-1,C_GENERAL_HI,msg); 1106 if ((got_status == 5) && (calc_status == 1)) { /* estimate total time */ 1107 putstring(-1,-1,C_GENERAL_MED," estimated total time: "); 1108 get_calculation_time( msg,(long)(calctime*((dif_limit*1.0)/dif_counter)) ); 1109 putstring(-1,-1,C_GENERAL_HI,msg); 1110 } 1111 1112 if ((curfractalspecific->flags&INFCALC) && (coloriter != 0)) { 1113 putstring(s_row,-1,C_GENERAL_MED,siterations); 1114 sprintf(msg," %ld of %ld",coloriter-2,maxct); 1115 putstring(s_row,-1,C_GENERAL_HI,msg); 1116 } 1117 1118 ++s_row; 1119 if(bf_math == 0) 1120 ++s_row; 1121 if (videoentry.xdots && bf_math==0) { 1122 sprintf(msg,"Video: %dx%dx%d %s %s", 1123 videoentry.xdots, videoentry.ydots, videoentry.colors, 1124 videoentry.name, videoentry.comment); 1125 putstring(s_row++,2,C_GENERAL_MED,msg); 1126 } 1127 if(!(curfractalspecific->flags&NOZOOM)) 1128 { 1129 adjust_corner(); /* make bottom left exact if very near exact */ 1130 if(bf_math) 1131 { 1132 int truncate, truncaterow; 1133 dec = min(320,decimals); 1134 adjust_cornerbf(); /* make bottom left exact if very near exact */ 1135 cvtcentermagbf(bfXctr, bfYctr, &Magnification, &Xmagfactor, &Rotation, &Skew); 1136 /* find alignment information */ 1137 msg[0] = 0; 1138 truncate = 0; 1139 if(dec < decimals) 1140 truncate = 1; 1141 truncaterow = row; 1142 putstring(++s_row,2,C_GENERAL_MED,scenter); 1143 putstring(s_row,8,C_GENERAL_MED,s_x); 1144 bftostr(msg,dec,bfXctr); 1145 if(putstringwrap(&s_row,10,78,C_GENERAL_HI,msg,5)==1) 1146 truncate = 1; 1147 putstring(++s_row,8,C_GENERAL_MED,s_y); 1148 bftostr(msg,dec,bfYctr); 1149 if(putstringwrap(&s_row,10,78,C_GENERAL_HI,msg,5)==1 || truncate) 1150 putstring(truncaterow,2,C_GENERAL_MED,struncate); 1151 putstring(++s_row,2,C_GENERAL_MED,smag); 1152 #ifdef USE_LONG_DOUBLE 1153 sprintf(msg,"%10.8Le",Magnification);
1154 #else 1155 sprintf(msg,"%10.8le",Magnification);
1156 #endif 1157 putstring(-1,11,C_GENERAL_HI,msg); 1158 putstring(++s_row,2,C_GENERAL_MED,sxmag); 1159 sprintf(msg,"%11.4f ",Xmagfactor); 1160 putstring(-1,-1,C_GENERAL_HI,msg); 1161 putstring(-1,-1,C_GENERAL_MED,srot); 1162 sprintf(msg,"%9.3f ",Rotation); 1163 putstring(-1,-1,C_GENERAL_HI,msg); 1164 putstring(-1,-1,C_GENERAL_MED,sskew); 1165 sprintf(msg,"%9.3f",Skew); 1166 putstring(-1,-1,C_GENERAL_HI,msg); 1167 } 1168 else /* bf != 1 */ 1169 { 1170 putstring(s_row,2,C_GENERAL_MED,scornersxy); 1171 putstring(++s_row,3,C_GENERAL_MED,stop_left); 1172 sprintf(msg,"%20.16f %20.16f",xxmin,yymax); 1173 putstring(-1,17,C_GENERAL_HI,msg); 1174 putstring(++s_row,3,C_GENERAL_MED,sbottom_right); 1175 sprintf(msg,"%20.16f %20.16f",xxmax,yymin); 1176 putstring(-1,17,C_GENERAL_HI,msg); 1177 1178 if (xxmin != xx3rd || yymin != yy3rd) 1179 { 1180 putstring(++s_row,3,C_GENERAL_MED,sbottom_left); 1181 sprintf(msg,"%20.16f %20.16f",xx3rd,yy3rd); 1182 putstring(-1,17,C_GENERAL_HI,msg); 1183 } 1184 cvtcentermag(&Xctr, &Yctr, &Magnification, &Xmagfactor, &Rotation, &Skew); 1185 putstring(s_row+=2,2,C_GENERAL_MED,scenter); 1186 sprintf(msg,"%20.16f %20.16f ",Xctr,Yctr); 1187 putstring(-1,-1,C_GENERAL_HI,msg); 1188 putstring(-1,-1,C_GENERAL_MED,smag); 1189 #ifdef USE_LONG_DOUBLE 1190 sprintf(msg," %10.8Le",Magnification);
1191 #else 1192 sprintf(msg," %10.8le",Magnification);
1193 #endif 1194 putstring(-1,-1,C_GENERAL_HI,msg); 1195 putstring(++s_row,2,C_GENERAL_MED,sxmag); 1196 sprintf(msg,"%11.4f ",Xmagfactor); 1197 putstring(-1,-1,C_GENERAL_HI,msg); 1198 putstring(-1,-1,C_GENERAL_MED,srot); 1199 sprintf(msg,"%9.3f ",Rotation); 1200 putstring(-1,-1,C_GENERAL_HI,msg); 1201 putstring(-1,-1,C_GENERAL_MED,sskew); 1202 sprintf(msg,"%9.3f",Skew); 1203 putstring(-1,-1,C_GENERAL_HI,msg); 1204 1205 } 1206 } 1207 1208 if(typehasparm(fractype,0,msg) || hasformparam) 1209 for (i = 0; i < MAXPARAMS; i++) 1210 { 1211 int col; 1212 char p[50]; 1213 if(typehasparm(fractype,i,p)) 1214 { 1215 if(k%4 == 0) 1216 { 1217 s_row++; 1218 col = 9; 1219 } 1220 else 1221 col = -1; 1222 if(k == 0) /* only true with first displayed parameter */ 1223 putstring(++s_row,2,C_GENERAL_MED,sparams); 1224 sprintf(msg,"%3d: ",i+1); 1225 putstring(s_row,col,C_GENERAL_MED,msg); 1226 if(*p == '+') 1227 sprintf(msg,"%-12d",(int)param[i]); 1228 else if(*p == '#') 1229 sprintf(msg,"%-12lu",(U32)param[i]); 1230 else 1231 sprintf(msg,"%-12.9f",param[i]); 1232 putstring(-1,-1,C_GENERAL_HI,msg); 1233 k++; 1234 } 1235 } 1236 putstring(s_row+=2,2,C_GENERAL_MED,siteration_maximum); 1237 sprintf(msg,"%ld (%ld)",coloriter,maxit); 1238 putstring(-1,-1,C_GENERAL_HI,msg); 1239 putstring(-1,-1,C_GENERAL_MED,seffective_bailout); 1240 sprintf(msg,"%f",rqlim); 1241 putstring(-1,-1,C_GENERAL_HI,msg); 1242 1243 if (fractype == PLASMA || fractype == ANT || fractype == CELLULAR) { 1244 putstring(++s_row,2,C_GENERAL_MED,scurrent_rseed); 1245 sprintf(msg,"%d",rseed); 1246 putstring(-1,-1,C_GENERAL_HI,msg); 1247 } 1248 1249 if(invert) { 1250 putstring(++s_row,2,C_GENERAL_MED,sinversion_radius); 1251 sprintf(msg,"%12.9f",f_radius); 1252 putstring(-1,-1,C_GENERAL_HI,msg); 1253 putstring(-1,-1,C_GENERAL_MED,sxcenter); 1254 sprintf(msg,"%12.9f",f_xcenter); 1255 putstring(-1,-1,C_GENERAL_HI,msg); 1256 putstring(-1,-1,C_GENERAL_MED,sycenter); 1257 sprintf(msg,"%12.9f",f_ycenter); 1258 putstring(-1,-1,C_GENERAL_HI,msg); 1259 } 1260 1261 if ((s_row += 2) < 23) ++s_row; 1262 /*waitforkey:*/ 1263 putstringcenter(/*s_row*/24,0,80,C_GENERAL_LO,spressanykey); 1264 movecursor(25,80); 1265 #ifdef XFRACT
1266 while (keypressed()) { 1267 getakey(); 1268 }
1269 #endif 1270 key = getakeynohelp(); 1271 if (key==F6) { 1272 unstackscreen(); 1273 area(); 1274 stackscreen(); 1275 /* goto waitforkey;*/ 1276 goto top; 1277 } 1278 else if(key==CTL_TAB || key==BACK_TAB || key==F7) { 1279 if(tab_display_2(msg)) 1280 goto top; 1281 } 1282 unstackscreen(); 1283 timer_start = clock_ticks(); /* tab display was "time out" */ 1284 if(bf_math) 1285 { 1286 restore_stack(saved); 1287 MoveFromMemory(ptr_to_extraseg,(U16)22400,1L,0L,save_extra_handle); 1288 MemoryRelease(save_extra_handle); 1289 save_extra_handle = 0; 1290 } 1291 return(0); 1292 } 1293 1294 static void area(void) 1295 { 1296 /* apologies to UNIX folks, we PC guys have to save near space */ 1297 static FCODE warning[] = {"Warning: inside may not be unique\n"}; 1298 static FCODE total_area[] = {". Total area "}; 1299 char far *msg; 1300 int x,y; 1301 char buf[160]; 1302 long cnt=0; 1303 if (inside<0) { 1304 static FCODE msg[] = {"Need solid inside to compute area"}; 1305 stopmsg(0,msg); 1306 return; 1307 } 1308 for (y=0;y<ydots;y++) { 1309 for (x=0;x<xdots;x++) { 1310 if (getcolor(x,y)==inside) { 1311 cnt++; 1312 } 1313 } 1314 } 1315 if (inside>0 && outside<0 && maxit>inside) { 1316 msg = warning; 1317 } else { 1318 msg = (char far *)""; 1319 } 1320 #ifndef XFRACT 1321 sprintf(buf,"%Fs%ld inside pixels of %ld%Fs%f", 1322 msg,cnt,(long)xdots*(long)ydots,(char far *)total_area, 1323 cnt/((float)xdots*(float)ydots)*(xxmax-xxmin)*(yymax-yymin));
1324 #else 1325 sprintf(buf,"%s%ld inside pixels of %ld%s%f", 1326 msg,cnt,(long)xdots*(long)ydots,total_area, 1327 cnt/((float)xdots*(float)ydots)*(xxmax-xxmin)*(yymax-yymin));
1328 #endif 1329 stopmsg(4,buf); 1330 } 1331 1332 int endswithslash(char far *fl) 1333 { 1334 int len; 1335 len = far_strlen(fl); 1336 if(len) 1337 if(fl[--len] == SLASHC) 1338 return(1); 1339 return(0); 1340 } 1341 1342 /* --------------------------------------------------------------------- */ 1343 static char seps[] = {"' ','\t',\n',\r'"}; 1344 char *get_ifs_token(char *buf,FILE *ifsfile) 1345 { 1346 char *bufptr; 1347 for(;;) 1348 { 1349 if(file_gets(buf,200,ifsfile) < 0) 1350 return(NULL); 1351 else 1352 { 1353 if((bufptr = strchr(buf,';')) != NULL) /* use ';' as comment to eol */ 1354 *bufptr = 0; 1355 if((bufptr = strtok(buf, seps)) != NULL) 1356 return(bufptr); 1357 } 1358 } 1359 } 1360 1361 FCODE insufficient_ifs_mem[]={"Insufficient memory for IFS"}; 1362 int numaffine; 1363 int ifsload() /* read in IFS parameters */ 1364 { 1365 int i; 1366 FILE *ifsfile; 1367 char buf[201]; 1368 char *bufptr; 1369 int ret,rowsize; 1370 1371 if (ifs_defn) { /* release prior parms */ 1372 farmemfree((char far *)ifs_defn); 1373 ifs_defn = NULL; 1374 } 1375 1376 ifs_type = 0; 1377 rowsize = IFSPARM; 1378 if (find_file_item(IFSFileName,IFSName,&ifsfile, 3) < 0) 1379 return(-1); 1380 1381 file_gets(buf,200,ifsfile); 1382 if((bufptr = strchr(buf,';')) != NULL) /* use ';' as comment to eol */ 1383 *bufptr = 0; 1384 1385 strlwr(buf); 1386 bufptr = &buf[0]; 1387 while (*bufptr) { 1388 if (strncmp(bufptr,"(3d)",4) == 0) { 1389 ifs_type = 1; 1390 rowsize = IFS3DPARM; 1391 } 1392 ++bufptr; 1393 } 1394 1395 for (i = 0; i < (NUMIFS+1)*IFS3DPARM; ++i) 1396 ((float *)tstack)[i] = 0; 1397 i = ret = 0; 1398 bufptr = get_ifs_token(buf,ifsfile); 1399 while(bufptr != NULL) 1400 { 1401 if(sscanf(bufptr," %f ",&((float *)tstack)[i]) != 1) 1402 break ; 1403 if (++i >= NUMIFS*rowsize) 1404 { 1405 static FCODE msg[]={"IFS definition has too many lines"}; 1406 stopmsg(0,msg); 1407 ret = -1; 1408 break; 1409 } 1410 if((bufptr = strtok( NULL, seps ))==NULL) 1411 { 1412 if((bufptr = get_ifs_token(buf,ifsfile)) == NULL) 1413 { 1414 ret = -1; 1415 break; 1416 } 1417 } 1418 if(ret == -1) 1419 break; 1420 if(*bufptr == '}') 1421 break; 1422 } 1423 1424 if ((i % rowsize) != 0 || *bufptr != '}') { 1425 static FCODE msg[]={"invalid IFS definition"}; 1426 stopmsg(0,msg); 1427 ret = -1; 1428 } 1429 if (i == 0 && ret == 0) { 1430 static FCODE msg[]={"Empty IFS definition"}; 1431 stopmsg(0,msg); 1432 ret = -1; 1433 } 1434 fclose(ifsfile); 1435 1436 if (ret == 0) { 1437 numaffine = i/rowsize; 1438 if ((ifs_defn = (float far *)farmemalloc( 1439 (long)((NUMIFS+1)*IFS3DPARM*sizeof(float)))) == NULL) { 1440 stopmsg(0,insufficient_ifs_mem); 1441 ret = -1; 1442 } 1443 else 1444 for (i = 0; i < (NUMIFS+1)*IFS3DPARM; ++i) 1445 ifs_defn[i] = ((float *)tstack)[i]; 1446 } 1447 return(ret); 1448 } 1449 /* TW 5-31-94 - added search of current directory for entry files if 1450 entry item not found */ 1451 1452 int find_file_item(char *filename,char *itemname,FILE **fileptr, int itemtype) 1453 { 1454 FILE *infile=NULL; 1455 int found = 0; 1456 char parsearchname[ITEMNAMELEN + 6]; 1457 char drive[FILE_MAX_DRIVE]; 1458 char dir[FILE_MAX_DIR]; 1459 char fname[FILE_MAX_FNAME]; 1460 char ext[FILE_MAX_EXT]; 1461 char fullpath[FILE_MAX_PATH]; 1462 char defaultextension[5]; 1463 1464 1465 splitpath(filename,drive,dir,fname,ext); 1466 makepath(fullpath,"","",fname,ext); 1467 if(stricmp(filename, CommandFile)) { 1468 if((infile=fopen(filename, "rb")) != NULL) { 1469 if(scan_entries(infile, NULL, itemname) == -1) { 1470 found = 1; 1471 } 1472 else { 1473 fclose(infile); 1474 infile = NULL; 1475 } 1476 } 1477 1478 if(!found && checkcurdir) { 1479 makepath(fullpath,"",DOTSLASH,fname,ext); 1480 if((infile=fopen(fullpath, "rb")) != NULL) { 1481 if(scan_entries(infile, NULL, itemname) == -1) { 1482 strcpy(filename, fullpath); 1483 found = 1; 1484 } 1485 else { 1486 fclose(infile); 1487 infile = NULL; 1488 } 1489 } 1490 } 1491 } 1492 1493 switch (itemtype) { 1494 case 1: 1495 strcpy(parsearchname, "frm:"); 1496 strcat(parsearchname, itemname); 1497 parsearchname[ITEMNAMELEN + 5] = (char) 0; /*safety*/ 1498 strcpy(defaultextension, ".frm"); 1499 splitpath(searchfor.frm,drive,dir,NULL,NULL); 1500 break; 1501 case 2: 1502 strcpy(parsearchname, "lsys:"); 1503 strcat(parsearchname, itemname); 1504 parsearchname[ITEMNAMELEN + 5] = (char) 0; /*safety*/ 1505 strcpy(defaultextension, ".l"); 1506 splitpath(searchfor.lsys,drive,dir,NULL,NULL); 1507 break; 1508 case 3: 1509 strcpy(parsearchname, "ifs:"); 1510 strcat(parsearchname, itemname); 1511 parsearchname[ITEMNAMELEN + 5] = (char) 0; /*safety*/ 1512 strcpy(defaultextension, ".ifs"); 1513 splitpath(searchfor.ifs,drive,dir,NULL,NULL); 1514 break; 1515 default: 1516 strcpy(parsearchname, itemname); 1517 parsearchname[ITEMNAMELEN + 5] = (char) 0; /*safety*/ 1518 strcpy(defaultextension, ".par"); 1519 splitpath(searchfor.par,drive,dir,NULL,NULL); 1520 break; 1521 } 1522 1523 if(!found) { 1524 if((infile=fopen(CommandFile, "rb")) != NULL) { 1525 if(scan_entries(infile, NULL, parsearchname) == -1) { 1526 strcpy(filename, CommandFile); 1527 found = 1; 1528 } 1529 else { 1530 fclose(infile); 1531 infile = NULL; 1532 } 1533 } 1534 } 1535 1536 if(!found) { 1537 makepath(fullpath,drive,dir,fname,ext); 1538 if((infile=fopen(fullpath, "rb")) != NULL) { 1539 if(scan_entries(infile, NULL, itemname) == -1) { 1540 strcpy(filename, fullpath); 1541 found = 1; 1542 } 1543 else { 1544 fclose(infile); 1545 infile = NULL; 1546 } 1547 } 1548 } 1549 1550 if(!found) { /* search for file */ 1551 int out; 1552 makepath(fullpath,drive,dir,"*",defaultextension); 1553 out = fr_findfirst(fullpath); 1554 while(out == 0) { 1555 char msg[200]; 1556 DTA.filename[FILE_MAX_FNAME+FILE_MAX_EXT-2]=0; 1557 sprintf(msg,"Searching %13s for %s ",DTA.filename,itemname); 1558 showtempmsg(msg); 1559 if(!(DTA.attribute & SUBDIR) && 1560 strcmp(DTA.filename,".")&& 1561 strcmp(DTA.filename,"..")) { 1562 #ifndef XFRACT 1563 strlwr(DTA.filename); 1564 #endif 1565 splitpath(DTA.filename,NULL,NULL,fname,ext); 1566 makepath(fullpath,drive,dir,fname,ext); 1567 if((infile=fopen(fullpath, "rb")) != NULL) { 1568 if(scan_entries(infile, NULL, itemname) == -1) { 1569 strcpy(filename, fullpath); 1570 found = 1; 1571 break; 1572 } 1573 else { 1574 fclose(infile); 1575 infile = NULL; 1576 } 1577 } 1578 } 1579 out = fr_findnext(); 1580 } 1581 cleartempmsg(); 1582 } 1583 1584 if (!found && orgfrmsearch && itemtype == 1) { 1585 splitpath(orgfrmdir,drive,dir,NULL,NULL); 1586 fname[0] = '_'; 1587 fname[1] = (char) 0; 1588 if (isalpha(itemname[0])) { 1589 if (strnicmp(itemname, "carr", 4)) { 1590 fname[1] = itemname[0]; 1591 fname[2] = (char) 0; 1592 } 1593 else if (isdigit(itemname[4])) { 1594 strcat(fname, "rc"); 1595 fname[3] = itemname[4]; 1596 fname[4] = (char) 0; 1597 } 1598 else { 1599 strcat(fname, "rc"); 1600 } 1601 } 1602 else if (isdigit(itemname[0])) { 1603 strcat(fname, "num"); 1604 } 1605 else { 1606 strcat(fname, "chr"); 1607 } 1608 makepath(fullpath,drive,dir,fname,defaultextension); 1609 if((infile=fopen(fullpath, "rb")) != NULL) { 1610 if(scan_entries(infile, NULL, itemname) == -1) { 1611 strcpy(filename, fullpath); 1612 found = 1; 1613 } 1614 else { 1615 fclose(infile); 1616 infile = NULL; 1617 } 1618 } 1619 } 1620 1621 if(!found) { 1622 sprintf(fullpath,"'%s' file entry item not found",itemname); 1623 stopmsg(0,fullpath); 1624 return(-1); 1625 } 1626 /* found file */ 1627 if(fileptr != NULL) 1628 *fileptr = infile; 1629 else if(infile != NULL) 1630 fclose(infile); 1631 return(0); 1632 } 1633 1634 1635 int file_gets(char *buf,int maxlen,FILE *infile) 1636 { 1637 int len,c; 1638 /* similar to 'fgets', but file may be in either text or binary mode */ 1639 /* returns -1 at eof, length of string otherwise */ 1640 if (feof(infile)) return -1; 1641 len = 0; 1642 while (len < maxlen) { 1643 if ((c = getc(infile)) == EOF || c == '\032') { 1644 if (len) break; 1645 return -1; 1646 } 1647 if (c == '\n') break; /* linefeed is end of line */ 1648 if (c != '\r') buf[len++] = (char)c; /* ignore c/r */ 1649 } 1650 buf[len] = 0; 1651 return len; 1652 } 1653 1654 int matherr_ct = 0; 1655 1656 #ifndef XFRACT 1657 #ifdef WINFRACT
1658 /* call this something else to dodge the QC4WIN bullet... */ 1659 int win_matherr( struct exception *except )
1660 #else 1661 int _cdecl _matherr( struct exception *except ) 1662 #endif 1663 { 1664 if(debugflag != 0) 1665 { 1666 static FILE *fp=NULL; 1667 static FCODE msg[]={"Math error, but we'll try to keep going"}; 1668 if(matherr_ct++ == 0) 1669 if(debugflag == 4000 || debugflag == 3200) 1670 stopmsg(0,msg); 1671 if(fp==NULL) 1672 fp = fopen("matherr","w"); 1673 if(matherr_ct < 100) 1674 { 1675 fprintf(fp,"err #%d: %d\nname: %s\narg: %e\n", 1676 matherr_ct, except->type, except->name, except->arg1); 1677 fflush(fp); 1678 } 1679 else 1680 matherr_ct = 100; 1681 1682 } 1683 if( except->type == DOMAIN ) 1684 { 1685 char buf[40]; 1686 sprintf(buf,"%e",except->arg1); 1687 /* This test may be unnecessary - from my experiments if the 1688 argument is too large or small the error is TLOSS not DOMAIN */ 1689 if(strstr(buf,"IN")||strstr(buf,"NAN")) /* trashed arg? */ 1690 /* "IND" with MSC, "INF" with BC++ */ 1691 { 1692 if( strcmp( except->name, s_sin ) == 0 ) 1693 { 1694 except->retval = 0.0; 1695 return(1); 1696 } 1697 else if( strcmp( except->name, s_cos ) == 0 ) 1698 { 1699 except->retval = 1.0; 1700 return(1); 1701 } 1702 else if( strcmp( except->name, s_log ) == 0 ) 1703 { 1704 except->retval = 1.0; 1705 return(1); 1706 } 1707 } 1708 } 1709 if( except->type == TLOSS ) 1710 { 1711 /* try valiantly to keep going */ 1712 if( strcmp( except->name, s_sin ) == 0 ) 1713 { 1714 except->retval = 0.5; 1715 return(1); 1716 } 1717 else if( strcmp( except->name, s_cos ) == 0 ) 1718 { 1719 except->retval = 0.5; 1720 return(1); 1721 } 1722 } 1723 /* shucks, no idea what went wrong, but our motto is "keep going!" */ 1724 except->retval = 1.0; 1725 return(1); 1726 } 1727 #endif 1728 1729 void roundfloatd(double *x) /* make double converted from float look ok */ 1730 { 1731 char buf[30]; 1732 sprintf(buf,"%-10.7g",*x); 1733 *x = atof(buf); 1734 } 1735 1736 void fix_inversion(double *x) /* make double converted from string look ok */ 1737 { 1738 char buf[30]; 1739 sprintf(buf,"%-1.15lg",*x); 1740 *x = atof(buf); 1741 } 1742 1743 /* fake a keystroke, returns old pending key */ 1744 int ungetakey(int key) 1745 { 1746 int old; 1747 old = keybuffer; 1748 keybuffer = key; 1749 return(old); 1750 } 1751 1752 #if _MSC_VER == 800 1753 #ifdef FIXTAN_DEFINED 1754 #undef tan 1755 /* !!!!! stupid MSVC tan(x) bug fix !!!!!!!! */ 1756 /* tan(x) can return -tan(x) if -pi/2 < x < pi/2 */ 1757 /* if tan(x) has been called before outside this range. */ 1758 double fixtan( double x ) 1759 { 1760 double y; 1761 1762 y = tan(x); 1763 if ((x > -PI/2 && x < 0 && y > 0) || (x > 0 && x < PI/2 && y < 0)) 1764 y = -y; 1765 return y; 1766 } 1767 #define tan fixtan 1768 #endif 1769 #endif 1770 1771 1772