1%% options 2 3copyright owner = Dirk Krause 4copyright year = 2012-xxxx 5SPDX-License-Identifier: BSD-3-Clause 6 7 8 9%% header 10 11#ifdef __cplusplus 12extern "C" { 13#endif 14 15/** Process command line arguments. 16 @param job Job to process. 17 @return 1 on success, 0 on error. 18*/ 19int 20f2lopt_process(f2l_job_t *job); 21 22#ifdef __cplusplus 23} 24#endif 25 26 27 28%% module 29 30#include <fig2lat/fig2lat.h> 31 32 33 34$!trace-include 35 36 37 38/** Options for the fig2lat program. 39*/ 40static dk3_option_t const f2lopt_options[] = { 41 { dkT('h'), dkT("help"), 0 }, 42 { dkT('v'), dkT("version"), 0 }, 43 { dkT('L'), dkT("license-terms"), 0 }, 44 { dkT('l'), dkT("language"), 1 }, 45 { dkT('m'), dkT("make"), 0 } 46}; 47 48/** Number of options in f2lopt_options. 49*/ 50static size_t const f2lopt_sz_options = 51sizeof(f2lopt_options)/sizeof(dk3_option_t); 52 53 54 55/** Key names for key/value pairs. 56*/ 57static dkChar const * f2lopt_key_names[] = { 58$!string-table macro=dkT 59# 60# 0: Text font (similar or fig) 61# 62tf 63# 64# 1: Text size (none or scale factor). 65# 66ts 67# 68# 2: Compatibility for splines. 69# 70cosp 71# 72# 3: Compatibility for arrowheads. 73# 74coah 75# 76# 4: X-spline segments Bezier segments. 77# 78xsss 79# 80# 5: Quadrant Bezier segments. 81# 82qbs 83# 84# 6: Lighten look. 85# 86# lighten 87lw 88# 89# 7: Write debug information. 90# 91debug 92# 93# 8: Write showpage operator at end of EPS files. 94# 95showpage 96# 97# 9: PS level. 98# 99level 100# 101# 10: DSC comments. 102# 103dsc 104# 105# 11: 106# 107xfig 108# 109# 12: 110# 111jfig 112# 113# 13: 114# 115winfig 116# 117# 14: Arrowhead arc segments 118# 119ahas 120# 121# 15: Arrowhead spline segments 122# 123ahss 124# 125# 16: Arrowhead min segments 126# 127ahms 128# 129# 17: Arrowhead interpolation precision 130# 131ahip 132# 133# 18: Use smash in LaTeX output 134# 135smash 136# 137# 19: Use mbox in LaTeX output 138# 139mbox 140# 141# 20: Use reset@font in LaTeX output 142# 143reset@font 144# 145# 21: Number of color digits. 146# 147codi 148# 149# 22: TeX text size. 150# 151dcts 152# 153# 23: Align SVG output to grid. 154# 155css 156# 157# 24: Write SVG fragment 158# 159fragment 160# 161# 25: Where to obtain SVG fonts 162# 163fontbase 164# 165# 26: Group SVG object with its arrowheads 166# 167group 168# 169# 27: Miterlimit 170# 171miterlimit 172# 173# 28: Compatible line styles. 174# 175cols 176# 177# 29: Use replacement fonts 178# 179replacementfonts 180# 181# 30: Use text size for bounding box. 182# 183bbts 184# 185# 31: Special text encoding. 186# 187ste 188# 189# 32: Compatible fill open paths. 190# 191cofop 192# 193# 33: X-spline arrowheads. 194# 195xsah 196# 197# 34: Bisection iteration on X-spline arrowheads. 198# 199ahbs 200$!end 201}; 202 203 204 205/** Values for font base choices. 206*/ 207static dkChar const * const f2lopt_svg_font_bases[] = { 208$!string-table macro=dkT 209none 210local 211web 212$!end 213}; 214 215 216/** Fixed keywords used by the module, not localized. 217*/ 218static dkChar const * const f2lopt_kw[] = { 219$!string-table macro=dkT 220# 221# 0: none (used to specify the font size). 222# 223none 224# 225# 1: lighten 226# 227lighten 228# 229# 2: automatic 230# 231auto$matic 232$!end 233}; 234 235 236 237/** Units for line width specification. 238*/ 239static dkChar const * const f2lopt_units[] = { 240$!string-table macro=dkT 241bp 242pt 243in 244mm 245cm 246$!end 247}; 248 249 250/** Language (output driver) names. 251 The order of names must correspond the the numbers defined 252 in fig2lat.ctr, see @ref fig2latdrivers. 253*/ 254static dkChar const * const f2lopt_language_names[] = { 255$!string-table macro=dkT 256pgf 257tex 258tex.pdf 259eps.tex 260pdf.tex 261eps 262svg 263# @DRIVER@ 264# Add name of new driver above this comment section 265# The order of driver names must correspond to the 266# driver names defined in fig2lat.ctr. 267$!end 268}; 269 270 271 272/** Keywords for font name decision. 273*/ 274static dkChar const * f2lopt_text_font_names[] = { 275$!string-table macro=dkT 276# 277# 0: similar 278# 279similar 280# 281# 1: fig 282# 283fig 284$!end 285}; 286 287 288 289/** Set default options depending on the driver just configured. 290 @param job Job structure. 291*/ 292static 293void 294f2lopt_set_default_options_for_language(f2l_job_t *job) 295{ 296 $? "+ f2lopt_set_default_options_for_language" 297 job->ntf = 0; 298 job->nts = -1.0; 299 job->showpage = 0; 300 job->dsc = 0; 301 job->smash = 1; 302 job->mbox = 0; 303 job->resfont = 0; 304 switch(job->dr) { 305 case FIG2LAT_DRIVER_EPS_STANDALONE: { 306 job->ntf = 1; 307 job->showpage = 1; 308 job->dsc = 1; 309 job->smash = 0; 310 job->mbox = 0; 311 job->resfont = 0; 312 } break; 313 case FIG2LAT_DRIVER_SVG_STANDALONE: 314 { 315 job->smash = 0; job->mbox = 0; job->resfont = 0; 316 job->ntf = 1; 317 } break; 318 case FIG2LAT_DRIVER_TEX_FULL_PGF: 319 case FIG2LAT_DRIVER_TEX_FULL_PDF: 320 { 321 job->ntf = 1; 322 } break; 323 } 324 $? "- f2lopt_set_default_options_for_language" 325} 326 327 328 329/** Set language. 330 @param job Job structure to configure. 331 @param lstr Language name without trailing options. 332 @return 1 on success, 0 on error. 333*/ 334static 335int 336f2lopt_apply_language(f2l_job_t *job, dkChar const *lstr) 337{ 338 int back = 0; 339 $? "+ f2lopt_apply_language \"%!ds\"", TR_STR(lstr) 340 job->dr = dk3str_array_index(f2lopt_language_names, lstr, 0); 341 if(job->dr > -1) { 342 back = 1; 343 f2lopt_set_default_options_for_language(job); 344 } else { $? "! unknown language" 345 /* ERROR: Unknown language ... */ 346 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 7, 8, lstr); 347 job->exval = FIG2LAT_EXIT_ERROR_SYNTAX; $? ". exitcode" 348 } $? "- f2lopt_apply_language %d", back 349 return back; 350} 351 352 353 354/** Set text font. 355 @param job Job structure. 356 @param vptr Font specification (similar or fig). 357 @return 1 on success, 0 on error. 358*/ 359static 360int 361f2lopt_set_text_font(f2l_job_t *job, dkChar const *vptr) 362{ 363 int i; /* Decision for font handling. */ 364 int back = 0; 365 $? "+ f2lopt_set_text_font \"%!ds\"", TR_STR(vptr) 366 switch((i = dk3str_array_index(f2lopt_text_font_names, vptr, 0))) { 367 case 0: case 1: { $? ". font selection = %d", i 368 job->ntf = i; 369 back = 1; 370 } break; 371 default: { $? "! wrong font selection" 372 /* ERROR: No such text font selection! */ 373 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 9, 10, vptr); 374 } break; 375 } 376 $? "- f2lopt_set_text_font %d", back 377 return back; 378} 379 380 381 382/** Set text size. 383 @param job Job structure. 384 @param vptr Text size as string (none or scale factor). 385 @return 1 on success, 0 on error. 386*/ 387static 388int 389f2lopt_set_text_size(f2l_job_t *job, dkChar const *vptr) 390{ 391 double d; /* Font size factor. */ 392 int back = 0; 393 $? "+ f2lopt_set_text_font \"%!ds\"", vptr 394 if(dk3str_cmp(vptr, f2lopt_kw[0]) == 0) { $? ". no size" 395 job->nts = -1.0; 396 back = 1; 397 } else { 398#if VERSION_BEFORE_20140716 399 if(dk3sf_sscanf3(vptr, dkT("%lf"), &d) == 1) 400#else 401 if (0 != dk3ma_d_from_string(&d, vptr, NULL)) 402#endif 403 { $? ". size %lg", d 404 job->nts = d; 405 back = 1; 406 } else { $? "! invalid size" 407 /* ERROR: Invalid font size specification! */ 408 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 11, 12, vptr); 409 } 410 } 411 $? "- f2lopt_set_text_font %d", back 412 return back; 413} 414 415 416 417/** Read a size_t from text. 418 @param dptr Pointer to destination variable. 419 @param vptr Source text. 420 @param job Job structure. 421 @return 1 on success, 0 on error. 422*/ 423static 424int 425f2lopt_read_size_t(size_t *dptr, dkChar const *vptr, f2l_job_t *job) 426{ 427#if VERSION_BEFORE_20140809 428 unsigned u; /* Conversion result. */ 429 int back = 0; 430 if(1 == dk3sf_sscanf3(vptr, dkT("%u"), &u)) { 431 *dptr = (size_t)u; 432 back = 1; 433 if((unsigned)(*dptr) != u) { 434 back = 0; 435 /* ERROR: Range overflow */ 436 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 13, 14, vptr); 437 } 438 } else { 439 /* ERRROR: Not a number! */ 440 dk3app_log_i3(job->app, DK3_LL_ERROR, 141, 142, vptr); 441 } 442 return back; 443#else 444 dk3_um_t um = DK3_UM_0; 445 int back = 0; 446 int mec = 0; 447 448 if (dk3ma_um_from_string(&um, vptr, NULL)) { /* OK: Number */ 449 *dptr = dk3ma_um_to_sz(um, &mec); 450 if (0 == mec) { /* OK: Converted */ 451 back = 1; 452 } else { /* Overflow */ 453 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 13, 14, vptr); 454 } 455 } else { /* Not a number */ 456 dk3app_log_i3(job->app, DK3_LL_ERROR, 141, 142, vptr); 457 } 458 return back; 459#endif 460} 461 462 463 464/** Read double value from string to configuration variable. 465 @param job Job structure. 466 @param dvar Pointer to destination variable. 467 @param src Source text. 468 @param min Minimum value. 469 @param max Maximum value. 470 @param tp Type (1=check minimum, 2=positive number + check max). 471 @param optnr Option index, used for error messages. 472 @return 1 on success, 0 on error. 473*/ 474static 475int 476f2lopt_read_double( 477 f2l_job_t *job, 478 double *dvar, 479 dkChar const *src, 480 double min, 481 double max, 482 int tp, 483 size_t optnr 484) 485{ 486 dkChar buf[128]; /* Conversion buffer. */ 487 double dval = 0.0; /* Conversion result. */ 488 int back = 0; 489 if(src) { 490#if VERSION_BEFORE_20140716 491 if(dk3sf_sscanf3(src, dkT("%lg"), &dval) == 1) 492#else 493 if (0 != dk3ma_d_from_string(&dval, src, NULL)) 494#endif 495 { 496 switch(tp) { 497 case 1: { 498 if(dval >= min) { 499 *dvar = dval; 500 back = 1; 501 } else { 502 /* ERROR: Minimum for option ... is ...! */ 503#if VERSION_BEFORE_20140716 504 dk3sf_sprintf3(buf, dkT("%g"), min); 505 dk3app_log_5( 506 job->app, DK3_LL_ERROR, job->msg, 15, 16, 17, src, buf 507 ); 508#else 509 if (0 != dk3ma_d_to_string(buf, DK3_SIZEOF(buf,dkChar), min)) { 510 dk3app_log_5( 511 job->app, DK3_LL_ERROR, job->msg, 15, 16, 17, src, buf 512 ); 513 } 514#endif 515 } 516 } break; 517 case 2: { 518 if(dval > 0) { 519 if(dval < max) { 520 *dvar = dval; 521 back = 1; 522 } else { 523 /* ERROR: Maximum for option ... is ...! */ 524#if VERSION_BEFORE_20140716 525 dk3sf_sprintf3(buf, dkT("%g"), max); 526 dk3app_log_5(job->app,DK3_LL_ERROR,job->msg,15,18,17,src,buf); 527#else 528 if (0 != dk3ma_d_to_string(buf, DK3_SIZEOF(buf,dkChar), max)) { 529 dk3app_log_5(job->app,DK3_LL_ERROR,job->msg,15,18,17,src,buf); 530 } 531#endif 532 } 533 } else { 534 /* ERROR: Option ... requires positive value! */ 535 dk3app_log_3( 536 job->app, DK3_LL_ERROR, job->msg, 19, 20, 537 f2lopt_key_names[optnr] 538 ); 539 } 540 } break; 541 } 542 } else { 543 /* ERROR: Option argument is not numeric! */ 544 dk3app_log_i3(job->app, DK3_LL_ERROR, 141, 142, src); 545 } 546 } else { 547 /* ERROR: Option requires an argument. */ 548 dk3app_log_3( 549 job->app, DK3_LL_ERROR, job->msg, 21, 22, 550 f2lopt_key_names[optnr] 551 ); 552 } 553 return back; 554} 555 556 557/** Process one option. 558 @param job Job structure to configure. 559 @param str Key=value text. 560 @return 1 on success, 0 on error. 561*/ 562static 563int 564f2lopt_apply_option(f2l_job_t *job, dkChar const *str) 565{ 566 dkChar bu[1024]; /* Private copy of str. */ 567 dkChar *kptr; /* Key pointer. */ 568 dkChar *vptr; /* Value pointer. */ 569 int back = 0; 570 $? "+ f2lopt_apply_option \"%!ds\"", TR_STR(str) 571 if(dk3str_len(str) < DK3_SIZEOF(bu,dkChar)) { 572 dk3str_cpy_not_overlapped(bu, str); 573 kptr = dk3str_start(bu, NULL); 574 if(kptr) { 575 vptr = dk3str_chr(kptr, dkT('=')); 576 if(vptr) { 577 *(vptr++) = dkT('\0'); 578 vptr = dk3str_start(vptr, NULL); 579 } 580 switch(dk3str_array_index(f2lopt_key_names, kptr, 0)) { 581 case 0: { $? ". tf" 582 if(vptr) { 583 back = f2lopt_set_text_font(job, vptr); 584 } else { 585 /* ERRROR: Key needs an argument! */ 586 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 21, 22, kptr); 587 } 588 } break; 589 case 1: { $? ". ts" 590 if(vptr) { 591 back = f2lopt_set_text_size(job, vptr); 592 } else { 593 job->nts = -1.0; 594 back = 1; 595 } 596 } break; 597 case 2: { $? ". cosp" 598 if(vptr) { 599 if(dk3str_is_bool(vptr)) { 600 job->cosp = (dk3str_is_on(vptr) ? 1 : 0); 601 back = 1; 602 } else { 603 /* ERROR: Not a boolean */ 604 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 605 } 606 } else { 607 job->cosp = 1; back = 1; 608 } 609 } break; 610 case 3: { $? ". coah" 611 if(vptr) { 612 if(dk3str_is_bool(vptr)) { 613 job->coah = (dk3str_is_on(vptr) ? 1 : 0); 614 back = 1; 615 } else { 616 /* ERROR: Not a boolean */ 617 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 618 } 619 } else { 620 job->coah = 1; back = 1; 621 } 622 } break; 623 case 4: { $? ". xssbs" 624 if(vptr) { 625 back = f2lopt_read_size_t(&(job->xssbs), vptr, job); 626 } else { 627 /* ERROR: Argument required! */ 628 dk3app_log_i3(job->app, DK3_LL_ERROR, 133, 134, kptr); 629 } 630 } break; 631 case 5: { $? ". qbs" 632 if(vptr) { 633 back = f2lopt_read_size_t(&(job->qbs), vptr, job); 634 } else { 635 /* ERROR: Argument required! */ 636 dk3app_log_i3(job->app, DK3_LL_ERROR, 133, 134, kptr); 637 } 638 } break; 639 case 6: { 640#if VERSION_BEFORE_20140330 641 if(vptr) { 642 if(dk3str_is_bool(vptr)) { 643 job->lighten = ((dk3str_is_on(vptr)) ? 1 : 0); 644 back = 1; 645 } else { 646 /* ERROR: Not a boolean value! */ 647 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 648 } 649 } else { 650 back = 1; 651 job->lighten = 1; 652 } 653#else 654 job->lwbp = 0.9; 655 job->lwauto = 0; 656 if (vptr) { 657 double x; 658 size_t vplen; 659 vplen = dk3str_len(vptr); 660 if (0 == dk3str_cmp(f2lopt_kw[1], vptr)) { 661 job->lwbp = 0.45; 662 job->lwauto = 0; 663 back = 1; 664 } else { 665 if (dk3str_is_abbr(vptr,f2lopt_kw[2],dkT('$'), 0)) { 666 job->lwauto = 1; 667 back = 1; 668 } else { 669 if (2 < vplen) { 670 switch (dk3str_array_index(f2lopt_units, &(vptr[vplen-2]), 0)) 671 { 672 case 0: { /* bp */ 673 vptr[vplen - 2] = dkT('\0'); 674#if VERSION_BEFORE_20140716 675 if (dk3sf_sscanf3(vptr, dkT("%lg"), &x) == 1) 676#else 677 if (0 != dk3ma_d_from_string(&x, vptr, NULL)) 678#endif 679 { 680 job->lwbp = x; 681 back = 1; 682 } else { 683 /* ERROR: Failed to process */ 684 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,45,46,vptr); 685 } 686 } break; 687 case 1: { /* pt */ 688 vptr[vplen - 2] = dkT('\0'); 689#if VERSION_BEFORE_20140716 690 if (dk3sf_sscanf3(vptr, dkT("%lg"), &x) == 1) 691#else 692 if (0 != dk3ma_d_from_string(&x, vptr, NULL)) 693#endif 694 { 695 job->lwbp = x * 72.0 / 72.27; 696 back = 1; 697 } else { 698 /* ERROR: Failed to process */ 699 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,45,46,vptr); 700 } 701 } break; 702 case 2: { /* in */ 703 vptr[vplen - 2] = dkT('\0'); 704#if VERSION_BEFORE_20140716 705 if (dk3sf_sscanf3(vptr, dkT("%lg"), &x) == 1) 706#else 707 if (0 != dk3ma_d_from_string(&x, vptr, NULL)) 708#endif 709 { 710 job->lwbp = x * 72.0; 711 back = 1; 712 } else { 713 /* ERROR: Failed to process */ 714 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,45,46,vptr); 715 } 716 } break; 717 case 3: { /* mm */ 718 vptr[vplen - 2] = dkT('\0'); 719#if VERSION_BEFORE_20140716 720 if (dk3sf_sscanf3(vptr, dkT("%lg"), &x) == 1) 721#else 722 if (0 != dk3ma_d_from_string(&x, vptr, NULL)) 723#endif 724 { 725 job->lwbp = x * 72.0 / 25.4; 726 back = 1; 727 } else { 728 /* ERROR: Failed to process */ 729 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,45,46,vptr); 730 } 731 } break; 732 case 4: { /* cm */ 733 vptr[vplen - 2] = dkT('\0'); 734#if VERSION_BEFORE_20140716 735 if (dk3sf_sscanf3(vptr, dkT("%lg"), &x) == 1) 736#else 737 if (0 != dk3ma_d_from_string(&x, vptr, NULL)) 738#endif 739 { 740 job->lwbp = x * 72.0 / 2.54; 741 back = 1; 742 } else { 743 /* ERROR: Failed to process */ 744 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,45,46,vptr); 745 } 746 } break; 747 default: { 748#if VERSION_BEFORE_20140716 749 if (dk3sf_sscanf3(vptr, dkT("%lg"), &x) == 1) 750#else 751 if (0 != dk3ma_d_from_string(&x, vptr, NULL)) 752#endif 753 { 754 job->lwbp = x; 755 back = 1; 756 } else { 757 /* ERROR: Failed to process */ 758 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,45,46,vptr); 759 } 760 } break; 761 } 762 } else { 763#if VERSION_BEFORE_20140716 764 if (dk3sf_sscanf3(vptr, dkT("%lg"), &x) == 1) 765#else 766 if (0 != dk3ma_d_from_string(&x, vptr, NULL)) 767#endif 768 { 769 job->lwbp = x; 770 back = 1; 771 } else { 772 /* ERROR: Failed to process */ 773 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,45,46,vptr); 774 } 775 } 776 } 777 } 778 } else { 779 job->lwbp = 0.9; 780 job->lwauto = 1; 781 back = 1; 782 if (job->lwbp < 0.001) { 783 job->lwbp = 0.001; 784 } 785 } $? ". lwbp=%lg lwauto=%d", job->lwbp, job->lwauto 786#endif 787 } break; 788 case 7: { 789 if(vptr) { 790 if(dk3str_is_bool(vptr)) { 791 back = 1; 792 job->debug = ((dk3str_is_on(vptr)) ? 1 : 0); 793 } else { 794 /* ERROR: Not a boolean value! */ 795 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 796 } 797 } else { 798 back = 1; 799 job->debug = 1; 800 } 801 } break; 802 case 8: { 803 if(vptr) { 804 if(dk3str_is_bool(vptr)) { 805 job->showpage = ((dk3str_is_on(vptr)) ? 1 : 0); 806 back = 1; 807 } else { 808 /* ERROR: Not a boolean value! */ 809 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 810 } 811 } else { 812 job->showpage = 1; 813 back = 1; 814 } 815 } break; 816 case 9: { 817 if(vptr) { 818 int i; 819#if VERSION_BEFORE_20140716 820 if(dk3sf_sscanf3(vptr, dkT("%d"), &i) == 1) 821#else 822 if (0 != dk3ma_i_from_string(&i, vptr, NULL)) 823#endif 824 { 825 if((i >= 2) && (i <= 3)) { 826 job->pslevel = i; 827 } else { 828 /* ERROR: Must be 2 or 3! */ 829 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 33); 830 } 831 } else { 832 /* ERROR: Argument not a number! */ 833 dk3app_log_i3(job->app, DK3_LL_ERROR, 141, 142, vptr); 834 } 835 } else { 836 /* ERROR: Argument required! */ 837 dk3app_log_i3(job->app, DK3_LL_ERROR, 133, 134, kptr); 838 } 839 } break; 840 case 10: { 841 if(vptr) { 842 if(dk3str_is_bool(vptr)) { 843 job->dsc = ((dk3str_is_on(vptr)) ? 1 : 0); 844 back = 1; 845 } else { 846 /* ERROR: Not a boolean argument. */ 847 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 848 } 849 } else { 850 job->dsc = 1; 851 back = 1; 852 } 853 } break; 854 case 11: { 855 if(DK3_FIG_SRCTYPE_UNKNOWN == job->srctype) { 856 job->srctype = DK3_FIG_SRCTYPE_XFIG; 857 back = 1; 858 } else { 859 /* ERROR: Source type already set! */ 860 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 23); 861 } 862 } break; 863 case 12: { 864 if(DK3_FIG_SRCTYPE_UNKNOWN == job->srctype) { 865 job->srctype = DK3_FIG_SRCTYPE_JFIG; 866 back = 1; 867 } else { 868 /* ERROR: Source type already set! */ 869 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 23); 870 } 871 } break; 872 case 13: { 873 if(DK3_FIG_SRCTYPE_UNKNOWN == job->srctype) { 874 job->srctype = DK3_FIG_SRCTYPE_WINFIG; 875 back = 1; 876 } else { 877 /* ERROR: Source type already set! */ 878 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 23); 879 } 880 } break; 881 case 14: { /* Arrowhead arc segments */ 882 back = f2lopt_read_double(job,&(job->arcspp),vptr,2.0,-1.0,1,14); 883 } break; 884 case 15: { /* Arrowhead spline segments */ 885 back = f2lopt_read_double(job,&(job->splspp),vptr,2.0,-1.0,1,15); 886 } break; 887 case 16: { /* Arrowhead min segments. */ 888 unsigned u = 2; 889 if(vptr) { 890#if VERSION_BEFORE_20140716 891 if(dk3sf_sscanf3(vptr, dkT("%u"), &u) == 1) 892#else 893 if (0 != dk3ma_ui_from_string(&u, vptr, NULL)) 894#endif 895 { 896 if(2 <= u) { 897 job->minspp = (size_t)u; 898 back = 1; 899 } else { 900 /* Warning: Must be at least 2! */ 901 job->minspp = 2; 902 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 34); 903 back = 1; 904 } 905 } else { 906 /* ERROR: Argument is not numeric */ 907 dk3app_log_i3(job->app, DK3_LL_ERROR, 141, 142, vptr); 908 } 909 } else { 910 /* ERROR: Option requires an argument! */ 911 dk3app_log_i3(job->app, DK3_LL_ERROR, 133, 134, kptr); 912 } 913 } break; 914 case 17: { /* Arrowhead interpolation precision. */ 915 back = f2lopt_read_double(job,&(job->xsprec),vptr,0.0,0.1,2,17); 916 } break; 917 case 18: { /* smash */ 918 if(vptr) { 919 if(dk3str_is_bool(vptr)) { 920 job->smash = ((dk3str_is_on(vptr)) ? 1 : 0); 921 back = 1; 922 } else { 923 /* ERROR: Option requires boolean argument */ 924 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 925 } 926 } else { 927 job->smash = 1; 928 back = 1; 929 } 930 } break; 931 case 19: { /* mbox */ 932 if(vptr) { 933 if(dk3str_is_bool(vptr)) { 934 job->mbox = ((dk3str_is_on(vptr)) ? 1 : 0); 935 back = 1; 936 } else { 937 /* ERROR: Option requires boolean argument! */ 938 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 939 } 940 } else { 941 job->mbox = 1; 942 back = 1; 943 } 944 } break; 945 case 20: { 946 if(vptr) { 947 if(dk3str_is_bool(vptr)) { 948 job->resfont = ((dk3str_is_on(vptr)) ? 1 : 0); 949 back = 1; 950 } else { 951 /* ERROR: Option requires boolean argument! */ 952 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 953 } 954 } else { 955 job->resfont = 1; 956 back = 1; 957 } 958 } break; 959 case 21: { 960 if(vptr) { 961 unsigned u; 962#if VERSION_BEFORE_20140716 963 if(dk3sf_sscanf3(vptr, dkT("%u"), &u) == 1) 964#else 965 if (0 != dk3ma_ui_from_string(&u, vptr, NULL)) 966#endif 967 { 968 job->codi = (size_t)u; 969 back = 1; 970 } else { 971 /* ERROR: Option requires an unsigned numeric argument! */ 972 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 24, 25, kptr); 973 } 974 } else { 975 job->codi = 0; 976 back = 1; 977 } 978 } break; 979 case 22: { 980 if(vptr) { 981 double d; 982#if VERSION_BEFORE_20140716 983 if(dk3sf_sscanf3(vptr, dkT("%lg"), &d) == 1) 984#else 985 if (0 != dk3ma_d_from_string(&d, vptr, NULL)) 986#endif 987 { 988 if(d > 0.0) { 989 job->tts = d; back = 1; 990 } else { 991 /* ERROR: Cannot handle negative font size! */ 992 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 26); 993 } 994 } else { 995 /* ERROR: Option requires a floating point number arg! */ 996 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 12, 22, kptr); 997 } 998 } else { 999 job->tts = 12.0; back = 1; 1000 } 1001 } break; 1002 case 23: { 1003 if(vptr) { 1004 if(dk3str_is_bool(vptr)) { 1005 job->css = ((dk3str_is_on(vptr)) ? 1 : 0); back = 1; 1006 } else { 1007 /* ERROR: Option requires boolean argument! */ 1008 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 1009 } 1010 } else { 1011 job->css = 1; back = 1; 1012 } 1013 } break; 1014 case 24: { 1015 if(vptr) { 1016 if(dk3str_is_bool(vptr)) { 1017 job->fragment = ((dk3str_is_on(vptr)) ? 1 : 0); back = 1; 1018 } else { 1019 /* ERROR: Option requires boolean argument! */ 1020 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 1021 } 1022 } else { 1023 job->fragment = 1; back = 1; 1024 } 1025 } break; 1026 case 25: { 1027 if(vptr) { 1028 job->svgfontbase = dk3str_array_index(f2lopt_svg_font_bases, vptr, 0); 1029 if(0 <= job->svgfontbase) { 1030 back = 1; 1031 } else { 1032 /* ##### ERROR: Illegal font base name! */ 1033 } 1034 } else { 1035 job->svgfontbase = 0; back = 1; 1036 } 1037 } break; 1038 case 26: { 1039 if(vptr) { 1040 if(dk3str_is_bool(vptr)) { 1041 job->group = ((dk3str_is_on(vptr)) ? 1 : 0); back = 1; 1042 } else { 1043 /* ERROR: Option requires boolean argument! */ 1044 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 1045 } 1046 } else { 1047 job->group = 1; back = 1; 1048 } 1049 } break; 1050 case 27: { 1051 if(vptr) { 1052 if(dk3str_is_bool(vptr)) { 1053 job->miterlim = ((dk3str_is_on(vptr)) ? 1 : 0); back = 1; 1054 } else { 1055 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 1056 } 1057 } else { 1058 job->miterlim = 1; back = 1; 1059 } 1060 } break; 1061 case 28: { 1062 if(vptr) { 1063 if(dk3str_is_bool(vptr)) { 1064 job->cols = ((dk3str_is_on(vptr)) ? 1 : 0); back = 1; 1065 } else { 1066 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 1067 } 1068 } else { 1069 job->cols = 1; back = 1; 1070 } 1071 } break; 1072 case 29: { 1073 if(vptr) { 1074 if(dk3str_is_bool(vptr)) { 1075 job->otherfonts = ((dk3str_is_on(vptr)) ? 1 : 0); back = 1; 1076 } else { 1077 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 1078 } 1079 } else { 1080 job->otherfonts = 1; back = 1; 1081 } 1082 } break; 1083 case 30: { 1084 if(vptr) { 1085 if(dk3str_is_bool(vptr)) { 1086 job->bbts = ((dk3str_is_on(vptr)) ? 1 : 0); back = 1; 1087 } else { 1088 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 1089 } 1090 } else { 1091 job->bbts = 1; back = 1; 1092 } 1093 } break; 1094 case 31: { 1095 int enc; 1096 if(vptr) { 1097 enc = dk3enc_get_text_encoding_app(vptr, job->app); 1098 } else { 1099 if(DK3_ENCODING_UTF8 == dk3app_get_encoding(job->app)) { 1100 enc = DK3_ENCODING_PLAIN; 1101 } else { 1102 enc = DK3_ENCODING_UTF8; 1103 } 1104 } 1105 back = 1; 1106 switch(enc) { 1107 case DK3_ENCODING_UTF8: { 1108 job->stu8 = 1; 1109 } break; 1110 case DK3_ENCODING_PLAIN: { 1111 job->stu8 = 0; 1112 } break; 1113 default: { 1114 job->stu8 = 0; 1115 /* ##### WARNING Only ascii and utf-8 allowed. */ 1116 } break; 1117 } 1118 } break; 1119 case 32: { 1120 if(vptr) { 1121 if(dk3str_is_bool(vptr)) { 1122 job->cofop = ((dk3str_is_on(vptr)) ? 1 : 0); 1123 back = 1; 1124 } else { 1125 /* ERROR: Not a boolean! */ 1126 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 1127 } 1128 } else { 1129 job->cofop = 1; 1130 back = 1; 1131 } 1132 } break; 1133 case 33: { 1134 if (vptr) { 1135 if(dk3str_is_bool(vptr)) { 1136 job->xsah = ((dk3str_is_on(vptr)) ? 1 : 0); 1137 back = 1; 1138 } else { 1139 /* ERROR: Not a boolean! */ 1140 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 1141 } 1142 } else { 1143 job->xsah = 1; 1144 back = 1; 1145 } 1146 } break; 1147 case 34: { 1148 if (vptr) { 1149 if (dk3str_is_bool(vptr)) { 1150 job->ahbs = ((dk3str_is_on(vptr)) ? 1 : 0); 1151 back = 1; 1152 } else { 1153 /* ERROR: Not a boolean! */ 1154 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 147, kptr); 1155 } 1156 } else { 1157 job->ahbs = 1; 1158 back = 1; 1159 } 1160 } break; 1161 default: { 1162 /* ERROR: Unknown key name! */ 1163 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 27, 28, kptr); 1164 } break; 1165 } 1166 } else { $? "! empty option" 1167 back = 1; 1168 } 1169 if(!(back)) { 1170 job->exval = FIG2LAT_EXIT_ERROR_SYNTAX; $? ". exitcode" 1171 } 1172 } else { 1173 /* ERROR: Option ... too long! */ 1174 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 29, 30, str); 1175 job->exval = FIG2LAT_EXIT_ERROR_SYNTAX; $? ". exitcode" 1176 } $? "- f2lopt_apply_option %d", back 1177 return back; 1178} 1179 1180 1181 1182/** Set language, apply options if any. 1183 @param job Job structure to set up. 1184 @param optarg Language, optionally with further options. 1185 @return 1 on success, 0 on error. 1186*/ 1187static 1188int 1189f2lopt_set_language(f2l_job_t *job, dkChar const *optarg) 1190{ 1191 dkChar bu[1024]; /* Private copy of optarg. */ 1192 dkChar *pc; /* Current string. */ 1193 dkChar *pn; /* Next string. */ 1194 int back = 0; 1195 $? "+ f2lopt_set_language \"%!ds\"", TR_STR(optarg) 1196 if(dk3str_len(optarg) < DK3_SIZEOF(bu,dkChar)) { 1197 dk3str_cpy_not_overlapped(bu, optarg); 1198 pc = dk3str_chr(bu, dkT(',')); 1199 if(pc) { 1200 *(pc++) = dkT('\0'); 1201 pc = dk3str_start(pc, NULL); 1202 } 1203 if(f2lopt_apply_language(job, bu)) { 1204 back = 1; 1205 while(pc) { $? ". pc = \"%!ds\"", TR_STR(pc) 1206 pn = dk3str_chr(pc, dkT(',')); 1207 if(pn) { *(pn++) = dkT('\0'); pn = dk3str_start(pn, NULL); } 1208 if(!f2lopt_apply_option(job, pc)) { 1209 back = 0; $? "! f2lopt_apply_option" 1210 pn = NULL; 1211 } 1212 pc = pn; 1213 } 1214 } 1215 } else { 1216 /* ERROR: Option argument too long! */ 1217 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 31, 30, optarg); 1218 } $? "- f2lopt_set_language %d", back 1219 return back; 1220} 1221 1222 1223 1224int 1225f2lopt_process(f2l_job_t *job) 1226{ 1227 dkChar const *optarg; /* Option argument. */ 1228 int back = 0; 1229 int i; /* Current file name. */ 1230 $? "+ f2lopt_process" 1231 job->opt = dk3opt_open_from_app( 1232 f2lopt_options, f2lopt_sz_options, 1233 dkT('o'), dkT("option"), 1234 job->app 1235 ); 1236 if(job->opt) { $? ". option set" 1237 if(0 == dk3opt_get_error_code(job->opt)) { $? ". error check" 1238 back = 1; 1239 if(dk3opt_is_set(job->opt, dkT('h'))) { 1240 job->cmd |= DK3_APP_CMD_HELP; 1241 } 1242 if(dk3opt_is_set(job->opt, dkT('v'))) { 1243 job->cmd |= DK3_APP_CMD_VERSION; 1244 } 1245 if(dk3opt_is_set(job->opt, dkT('L'))) { 1246 job->cmd |= DK3_APP_CMD_LICENSE; 1247 } 1248 if(0 == job->cmd) { 1249 if(dk3opt_is_set(job->opt, dkT('m'))) { 1250 job->mm = 1; 1251 } 1252 if(dk3opt_is_set(job->opt, dkT('l'))) { 1253 optarg = dk3opt_get_short_arg(job->opt, dkT('l')); 1254 if(optarg) { $? ". optarg" 1255 if(f2lopt_set_language(job, optarg)) { 1256 for(i = 0; i < dk3opt_get_num_fo(job->opt); i++) { 1257 optarg = dk3opt_get_fo(job->opt, i); 1258 if(optarg) { 1259 if(!f2lopt_apply_option(job, optarg)) { 1260 back = 0; 1261 } 1262 } 1263 } 1264 } else { 1265 back = 0; 1266 } 1267 } else { $? "! optarg" 1268 back = 0; 1269 /* ERROR: Option requires an argument! */ 1270 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 32); 1271 } 1272 } else { 1273 } 1274 } 1275 /* Automatically calculate line width in points 1276 from TeX text size. 1277 */ 1278 if (job->lwauto) { 1279 job->lwbp = 0.4 * 72.0 * job->tts / (10 * 72.27); 1280 $? ". lwbp=%lg", job->lwbp 1281 } 1282 } else { $? "! error check" 1283 } 1284 } else { $? "! option set" 1285 job->exval = FIG2LAT_EXIT_ERROR_SYSTEM; $? ". exitcode" 1286 } $? "- f2lopt_process %d", back 1287 return back; 1288} 1289 1290 1291