From: John Darrington Date: Fri, 25 Dec 2009 09:51:01 +0000 (+0100) Subject: Merge branch 'master' into output X-Git-Tag: fc11-x64-build61~2 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8b71948cd57dbd2787cb4c50525b957e9be8a62b;hp=1085f5128713881e135ea83fbdf411b99e8f32b6;p=pspp-builds.git Merge branch 'master' into output Conflicts: configure.ac --- diff --git a/INSTALL b/INSTALL index 4f1bc84c..0f4f5c96 100644 --- a/INSTALL +++ b/INSTALL @@ -33,12 +33,13 @@ The following packages are required to install PSPP: If you don't have a version already, you can install GNU libiconv (http://www.gnu.org/software/libiconv/). -The following package is required to enable PSPP's graphing features. -If you cannot arrange to install it, you must run `configure' with ---without-libplot. +The following packages are required to enable PSPP's graphing +features. If you cannot arrange to install them, you must run +`configure' with --without-cairo. - * libplot, from GNU plotutils - (http://www.gnu.org/software/plotutils/). + * Cairo (http://cairographics.org/), version 1.5 or later. + + * Pango (http://www.pango.org/), version 1.22 or later. The following packages are required to enable PSPPIRE, the graphical user interface for PSPP. If you cannot install them or do not wish to @@ -209,14 +210,17 @@ suffix on their names by giving `configure' the option Optional Features ================= -`--without-libplot' - Don't compile in support for charts (using libplot). This is - useful if your system doesn't have the libplot library. +`--without-cairo' + Don't compile in support for charts (using Cairo and Pango). This + is useful if your system lacks these libraries. `--without-gui' Don't build the PSPPIRE gui. Use this option if you only want to build the command line version of PSPP. + Cairo and Pango required to build the GUI, so --without-cairo + implies --without-gui. + `--with-gui-tools' Build the gui developer tools. There is no reason to use this option unless you're involved with the development of PSPP diff --git a/NEWS b/NEWS index 149d1dea..ab21afde 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,19 @@ PSPP NEWS -- history of user-visible changes. -Time-stamp: <2009-10-06 20:46:21 blp> +Time-stamp: <2009-12-05 20:39:07 blp> Copyright (C) 1996-9, 2000, 2008, 2009 Free Software Foundation, Inc. See the end for copying conditions. Please send PSPP bug reports to bug-gnu-pspp@gnu.org. +Changes from 0.7.2 to 0.7.3: + + * Charts are now produced with Cairo and Pango, instead of libplot. + Without them, the new graphing features will not work. If you do + not have Cairo and Pango installed, you must run `configure' with + --without-cairo. + + * The PostScript driver has been removed. + Changes from 0.7.1 to 0.7.2: * Updated Perl module interface. diff --git a/THANKS b/THANKS index 5af73108..b5bd839e 100644 --- a/THANKS +++ b/THANKS @@ -12,5 +12,3 @@ Thanks to... * François Pinard for advice on proceeding with development. * Jim Van Zandt for Debian packaging and suggestions. - - * The authors of libplot and libgsl for providing those libraries. diff --git a/acinclude.m4 b/acinclude.m4 index 307ce149..14d11dc7 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -43,40 +43,6 @@ AC_DEFUN([PSPP_PERL], AC_SUBST([VERSION_FOR_PERL]) ]) -dnl Check that libplot is available. -AC_DEFUN([PSPP_LIBPLOT], -[ - AC_ARG_WITH( - libplot, - [AS_HELP_STRING([--without-libplot], - [don't compile in support of charts (using libplot)])]) - - if test x"$with_libplot" != x"no" ; then - # Check whether we can link against libplot without any extra libraries. - AC_CHECK_LIB(plot, pl_newpl_r, [LIBPLOT_LIBS="-lplot"]) - - # Check whether we can link against libplot if we also link X. - if test x"$LIBPLOT_LIBS" = x""; then - AC_PATH_XTRA - extra_libs="-lXaw -lXmu -lXt $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS -lm" - AC_CHECK_LIB(plot, pl_newpl_r, - [LIBPLOT_LIBS="-lplot $extra_libs" - LDFLAGS="$LDFLAGS $X_LIBS"],, - [$extra_libs]) - fi - - # Still can't link? - if test x"$LIBPLOT_LIBS" = x""; then - PSPP_REQUIRED_PREREQ([libplot (or use --without-libplot)]) - fi - - # Set up to make everything work. - LIBS="$LIBPLOT_LIBS $LIBS" - AC_DEFINE(HAVE_LIBPLOT, 1, - [Define to 1 if you have the `libplot' library (-lplot).]) - fi -]) - dnl PSPP_CHECK_CC_OPTION([OPTION], [ACTION-IF-ACCEPTED], [ACTION-IF-REJECTED]) dnl Check whether the given C compiler OPTION is accepted. dnl If so, execute ACTION-IF-ACCEPTED, otherwise ACTION-IF-REJECTED. diff --git a/config/automake.mk b/config/automake.mk index 88b63ac1..509706e5 100644 --- a/config/automake.mk +++ b/config/automake.mk @@ -4,19 +4,4 @@ dist_pkgsysconf_DATA = \ config/devices -psfontsdir = $(pkgsysconfdir)/psfonts -dist_psfonts_DATA = \ - config/psfonts/Helvetica-Bold.afm \ - config/psfonts/Times-Bold.afm \ - config/psfonts/Courier-Bold.afm \ - config/psfonts/Helvetica-BoldOblique.afm \ - config/psfonts/Times-BoldItalic.afm \ - config/psfonts/Courier-BoldOblique.afm \ - config/psfonts/Helvetica-Oblique.afm \ - config/psfonts/Times-Italic.afm \ - config/psfonts/Courier-Oblique.afm \ - config/psfonts/Helvetica.afm \ - config/psfonts/Times-Roman.afm \ - config/psfonts/Courier.afm - EXTRA_DIST += config/OChangeLog diff --git a/config/devices b/config/devices index 48513fe6..3bc685a0 100644 --- a/config/devices +++ b/config/devices @@ -80,6 +80,13 @@ html:html:: # PostScript device. list-ps:postscript:: +# Cairo devices. +pdf:cairo:listing: +svg:cairo:listing:output-type=svg output-file="pspp.svg" +ps-cairo:cairo:listing:output-type=ps output-file="pspp-cairo.ps" + +odt:odf:listing:debug=off output-file="pspp.odt" + # Devices that support the IBM PC line-drawing characters. define ibmpc-graphics \ box[0000]='\x20' box[0001]='\xb3' box[0002]='\xba' \ @@ -115,6 +122,89 @@ tty-ibmpc:ascii:screen:length=$viewlength width=$viewwidth ${ibmpc-graphics} \ list-ibmpc:ascii:listing:length=66 width=79 output-file=${list-output-file} \ ${ibmpc-graphics} +# Devices that support Unicode line-drawing characters in UTF-8 encoding. +# PSPP doesn't support a \u escape but if it did then this is how these +# would appear: +# +# define utf8-graphics \ +# box[0000]='\u0020' box[1000]='\u2576' box[2000]='\u2550' \ +# box[0100]='\u2577' box[1100]='\u256D' box[2100]='\u2552' \ +# box[0200]='\u2551' box[1200]='\u2553' box[2200]='\u2554' \ +# box[0010]='\u2574' box[1010]='\u2500' box[2010]='\u2550' \ +# box[0110]='\u256E' box[1110]='\u252C' box[2110]='\u2564' \ +# box[0210]='\u2556' box[1210]='\u2565' box[2210]='\u2566' \ +# box[0020]='\u2550' box[1020]='\u2550' box[2020]='\u2550' \ +# box[0120]='\u2555' box[1120]='\u2564' box[2120]='\u2564' \ +# box[0220]='\u2557' box[1220]='\u2566' box[2220]='\u2566' \ +# box[0001]='\u2575' box[1001]='\u2570' box[2001]='\u2558' \ +# box[0101]='\u2502' box[1101]='\u251C' box[2101]='\u255E' \ +# box[0201]='\u2551' box[1201]='\u255F' box[2201]='\u2560' \ +# box[0011]='\u256F' box[1011]='\u2534' box[2011]='\u2567' \ +# box[0111]='\u2524' box[1111]='\u253C' box[2111]='\u256A' \ +# box[0211]='\u2562' box[1211]='\u256B' box[2211]='\u256C' \ +# box[0021]='\u255B' box[1021]='\u2567' box[2021]='\u2567' \ +# box[0121]='\u2561' box[1121]='\u256A' box[2121]='\u256A' \ +# box[0221]='\u2563' box[1221]='\u256C' box[2221]='\u256C' \ +# box[0002]='\u2551' box[1002]='\u2559' box[2002]='\u255A' \ +# box[0102]='\u2551' box[1102]='\u255F' box[2102]='\u2560' \ +# box[0202]='\u2551' box[1202]='\u255F' box[2202]='\u2560' \ +# box[0012]='\u255C' box[1012]='\u2568' box[2012]='\u2569' \ +# box[0112]='\u2562' box[1112]='\u256A' box[2112]='\u256C' \ +# box[0212]='\u2562' box[1212]='\u256B' box[2212]='\u256C' \ +# box[0022]='\u255D' box[1022]='\u2569' box[2022]='\u2569' \ +# box[0122]='\u2563' box[1122]='\u256C' box[2122]='\u256C' \ +# box[0222]='\u2563' box[1222]='\u256C' box[2222]='\u256C' +# +# Instead, we encode them in UTF-8 by hand below. +# +# Here is a little Perl program that I used to do this translation: +# +# sub utf8_encode { +# my $val = hex($_[0]); +# my $d0 = 0xe0 | ($val >> 12); +# my $d1 = 0x80 | (($val >> 6) & 0x3f); +# my $d2 = 0x80 | ($val & 0x3f); +# return sprintf('\x%02x\x%02x\x%02x', $d0, $d1, $d2); +# } +# while (<>) { +# s/\\u(....)/utf8_encode($1)/ge; +# print $_; +# } +# +define utf8-graphics \ + box[0000]='\xe0\x80\xa0' box[1000]='\xe2\x95\xb6' box[2000]='\xe2\x95\x90' \ + box[0100]='\xe2\x95\xb7' box[1100]='\xe2\x95\xad' box[2100]='\xe2\x95\x92' \ + box[0200]='\xe2\x95\x91' box[1200]='\xe2\x95\x93' box[2200]='\xe2\x95\x94' \ + box[0010]='\xe2\x95\xb4' box[1010]='\xe2\x94\x80' box[2010]='\xe2\x95\x90' \ + box[0110]='\xe2\x95\xae' box[1110]='\xe2\x94\xac' box[2110]='\xe2\x95\xa4' \ + box[0210]='\xe2\x95\x96' box[1210]='\xe2\x95\xa5' box[2210]='\xe2\x95\xa6' \ + box[0020]='\xe2\x95\x90' box[1020]='\xe2\x95\x90' box[2020]='\xe2\x95\x90' \ + box[0120]='\xe2\x95\x95' box[1120]='\xe2\x95\xa4' box[2120]='\xe2\x95\xa4' \ + box[0220]='\xe2\x95\x97' box[1220]='\xe2\x95\xa6' box[2220]='\xe2\x95\xa6' \ + box[0001]='\xe2\x95\xb5' box[1001]='\xe2\x95\xb0' box[2001]='\xe2\x95\x98' \ + box[0101]='\xe2\x94\x82' box[1101]='\xe2\x94\x9c' box[2101]='\xe2\x95\x9e' \ + box[0201]='\xe2\x95\x91' box[1201]='\xe2\x95\x9f' box[2201]='\xe2\x95\xa0' \ + box[0011]='\xe2\x95\xaf' box[1011]='\xe2\x94\xb4' box[2011]='\xe2\x95\xa7' \ + box[0111]='\xe2\x94\xa4' box[1111]='\xe2\x94\xbc' box[2111]='\xe2\x95\xaa' \ + box[0211]='\xe2\x95\xa2' box[1211]='\xe2\x95\xab' box[2211]='\xe2\x95\xac' \ + box[0021]='\xe2\x95\x9b' box[1021]='\xe2\x95\xa7' box[2021]='\xe2\x95\xa7' \ + box[0121]='\xe2\x95\xa1' box[1121]='\xe2\x95\xaa' box[2121]='\xe2\x95\xaa' \ + box[0221]='\xe2\x95\xa3' box[1221]='\xe2\x95\xac' box[2221]='\xe2\x95\xac' \ + box[0002]='\xe2\x95\x91' box[1002]='\xe2\x95\x99' box[2002]='\xe2\x95\x9a' \ + box[0102]='\xe2\x95\x91' box[1102]='\xe2\x95\x9f' box[2102]='\xe2\x95\xa0' \ + box[0202]='\xe2\x95\x91' box[1202]='\xe2\x95\x9f' box[2202]='\xe2\x95\xa0' \ + box[0012]='\xe2\x95\x9c' box[1012]='\xe2\x95\xa8' box[2012]='\xe2\x95\xa9' \ + box[0112]='\xe2\x95\xa2' box[1112]='\xe2\x95\xaa' box[2112]='\xe2\x95\xac' \ + box[0212]='\xe2\x95\xa2' box[1212]='\xe2\x95\xab' box[2212]='\xe2\x95\xac' \ + box[0022]='\xe2\x95\x9d' box[1022]='\xe2\x95\xa9' box[2022]='\xe2\x95\xa9' \ + box[0122]='\xe2\x95\xa3' box[1122]='\xe2\x95\xac' box[2122]='\xe2\x95\xac' \ + box[0222]='\xe2\x95\xa3' box[1222]='\xe2\x95\xac' box[2222]='\xe2\x95\xac' + +tty-utf8:ascii:screen:length=$viewlength width=$viewwidth ${utf8-graphics} \ + output-file=${tty-output-file} emphasis=none +list-utf8:ascii:listing:length=66 width=79 output-file=${list-output-file} \ + ${utf8-graphics} emphasis=none + # Local Variables: # fill-prefix: "# " # End: diff --git a/config/psfonts/Courier-Bold.afm b/config/psfonts/Courier-Bold.afm deleted file mode 100644 index dbfdddb2..00000000 --- a/config/psfonts/Courier-Bold.afm +++ /dev/null @@ -1,348 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1989 1990 Adobe Systems Incorporated. All rights reserved. -Comment Creation Date: Thu Jan 18 16:13:14 1990 -Comment UniqueID 27058 -Comment VMusage 28444 40812 -FontName Courier-Bold -FullName Courier Bold -FamilyName Courier -Weight Bold -ItalicAngle 0 -IsFixedPitch true -FontBBox -40 -206 786 801 -UnderlinePosition -100 -UnderlineThickness 50 -Version 002.003 -Notice Copyright (c) 1989 1990 Adobe Systems Incorporated. All rights reserved. -EncodingScheme AdobeStandardEncoding -CapHeight 562 -XHeight 439 -Ascender 626 -Descender -142 -StartCharMetrics 260 -C 32 ; WX 600 ; N space ; B 0 0 0 0 ; -C 33 ; WX 600 ; N exclam ; B 212 -15 388 572 ; -C 34 ; WX 600 ; N quotedbl ; B 145 297 455 562 ; -C 35 ; WX 600 ; N numbersign ; B 66 -45 534 651 ; -C 36 ; WX 600 ; N dollar ; B 92 -126 509 666 ; -C 37 ; WX 600 ; N percent ; B 5 -15 595 616 ; -C 38 ; WX 600 ; N ampersand ; B 46 -15 536 543 ; -C 39 ; WX 600 ; N quoteright ; B 188 297 412 562 ; -C 40 ; WX 600 ; N parenleft ; B 229 -102 451 616 ; -C 41 ; WX 600 ; N parenright ; B 149 -102 371 616 ; -C 42 ; WX 600 ; N asterisk ; B 91 219 509 601 ; -C 43 ; WX 600 ; N plus ; B 81 0 519 439 ; -C 44 ; WX 600 ; N comma ; B 140 -101 374 164 ; -C 45 ; WX 600 ; N hyphen ; B 110 213 490 303 ; -C 46 ; WX 600 ; N period ; B 206 -15 394 151 ; -C 47 ; WX 600 ; N slash ; B 105 -77 496 626 ; -C 48 ; WX 600 ; N zero ; B 97 -15 503 616 ; -C 49 ; WX 600 ; N one ; B 91 0 529 616 ; -C 50 ; WX 600 ; N two ; B 71 0 489 616 ; -C 51 ; WX 600 ; N three ; B 73 -15 491 616 ; -C 52 ; WX 600 ; N four ; B 63 0 497 616 ; -C 53 ; WX 600 ; N five ; B 80 -15 511 601 ; -C 54 ; WX 600 ; N six ; B 100 -15 511 616 ; -C 55 ; WX 600 ; N seven ; B 65 0 484 601 ; -C 56 ; WX 600 ; N eight ; B 93 -15 507 616 ; -C 57 ; WX 600 ; N nine ; B 89 -15 500 616 ; -C 58 ; WX 600 ; N colon ; B 206 -15 394 405 ; -C 59 ; WX 600 ; N semicolon ; B 140 -101 394 405 ; -C 60 ; WX 600 ; N less ; B 66 -15 503 453 ; -C 61 ; WX 600 ; N equal ; B 81 89 519 349 ; -C 62 ; WX 600 ; N greater ; B 97 -15 534 453 ; -C 63 ; WX 600 ; N question ; B 108 -15 491 580 ; -C 64 ; WX 600 ; N at ; B 26 -15 574 616 ; -C 65 ; WX 600 ; N A ; B 1 0 599 562 ; -C 66 ; WX 600 ; N B ; B 40 0 563 562 ; -C 67 ; WX 600 ; N C ; B 32 -18 554 580 ; -C 68 ; WX 600 ; N D ; B 40 0 584 562 ; -C 69 ; WX 600 ; N E ; B 40 0 545 562 ; -C 70 ; WX 600 ; N F ; B 54 0 555 562 ; -C 71 ; WX 600 ; N G ; B 32 -18 584 580 ; -C 72 ; WX 600 ; N H ; B 30 0 570 562 ; -C 73 ; WX 600 ; N I ; B 87 0 513 562 ; -C 74 ; WX 600 ; N J ; B 47 -18 591 562 ; -C 75 ; WX 600 ; N K ; B 36 0 584 562 ; -C 76 ; WX 600 ; N L ; B 49 0 568 562 ; -C 77 ; WX 600 ; N M ; B 3 0 597 562 ; -C 78 ; WX 600 ; N N ; B 18 -12 600 562 ; -C 79 ; WX 600 ; N O ; B 32 -18 568 580 ; -C 80 ; WX 600 ; N P ; B 58 0 549 562 ; -C 81 ; WX 600 ; N Q ; B 32 -123 568 580 ; -C 82 ; WX 600 ; N R ; B 34 0 589 562 ; -C 83 ; WX 600 ; N S ; B 57 -22 543 582 ; -C 84 ; WX 600 ; N T ; B 31 0 569 562 ; -C 85 ; WX 600 ; N U ; B 14 -18 586 562 ; -C 86 ; WX 600 ; N V ; B -3 0 603 562 ; -C 87 ; WX 600 ; N W ; B -8 0 608 562 ; -C 88 ; WX 600 ; N X ; B 22 0 578 562 ; -C 89 ; WX 600 ; N Y ; B 22 0 579 562 ; -C 90 ; WX 600 ; N Z ; B 72 0 529 562 ; -C 91 ; WX 600 ; N bracketleft ; B 255 -102 465 616 ; -C 92 ; WX 600 ; N backslash ; B 105 -77 496 626 ; -C 93 ; WX 600 ; N bracketright ; B 135 -102 345 616 ; -C 94 ; WX 600 ; N asciicircum ; B 108 249 492 616 ; -C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ; -C 96 ; WX 600 ; N quoteleft ; B 188 297 412 562 ; -C 97 ; WX 600 ; N a ; B 45 -15 560 454 ; -C 98 ; WX 600 ; N b ; B 10 -15 574 626 ; -C 99 ; WX 600 ; N c ; B 50 -15 539 459 ; -C 100 ; WX 600 ; N d ; B 30 -15 581 626 ; -C 101 ; WX 600 ; N e ; B 50 -15 553 454 ; -C 102 ; WX 600 ; N f ; B 93 0 537 626 ; L i fi ; L l fl ; -C 103 ; WX 600 ; N g ; B 40 -146 570 454 ; -C 104 ; WX 600 ; N h ; B 15 0 582 626 ; -C 105 ; WX 600 ; N i ; B 87 0 513 648 ; -C 106 ; WX 600 ; N j ; B 73 -146 430 648 ; -C 107 ; WX 600 ; N k ; B 30 0 575 626 ; -C 108 ; WX 600 ; N l ; B 87 0 513 626 ; -C 109 ; WX 600 ; N m ; B -12 0 616 454 ; -C 110 ; WX 600 ; N n ; B 28 0 582 454 ; -C 111 ; WX 600 ; N o ; B 40 -15 560 454 ; -C 112 ; WX 600 ; N p ; B 9 -142 560 454 ; -C 113 ; WX 600 ; N q ; B 30 -142 581 454 ; -C 114 ; WX 600 ; N r ; B 57 0 570 454 ; -C 115 ; WX 600 ; N s ; B 78 -17 525 459 ; -C 116 ; WX 600 ; N t ; B 57 -15 522 562 ; -C 117 ; WX 600 ; N u ; B 9 -15 559 439 ; -C 118 ; WX 600 ; N v ; B 9 0 591 439 ; -C 119 ; WX 600 ; N w ; B -8 0 608 439 ; -C 120 ; WX 600 ; N x ; B 16 0 584 439 ; -C 121 ; WX 600 ; N y ; B 6 -142 591 439 ; -C 122 ; WX 600 ; N z ; B 91 0 510 439 ; -C 123 ; WX 600 ; N braceleft ; B 170 -102 454 616 ; -C 124 ; WX 600 ; N bar ; B 255 -77 345 626 ; -C 125 ; WX 600 ; N braceright ; B 146 -102 430 616 ; -C 126 ; WX 600 ; N asciitilde ; B 81 124 520 307 ; -C 161 ; WX 600 ; N exclamdown ; B 212 -146 388 449 ; -C 162 ; WX 600 ; N cent ; B 76 -49 508 614 ; -C 163 ; WX 600 ; N sterling ; B 82 -28 548 611 ; -C 164 ; WX 600 ; N fraction ; B 30 -60 571 661 ; -C 165 ; WX 600 ; N yen ; B 20 0 580 591 ; -C 166 ; WX 600 ; N florin ; B -20 -131 562 616 ; -C 167 ; WX 600 ; N section ; B 103 -70 497 580 ; -C 168 ; WX 600 ; N currency ; B 54 49 546 517 ; -C 169 ; WX 600 ; N quotesingle ; B 237 297 363 562 ; -C 170 ; WX 600 ; N quotedblleft ; B 81 297 519 562 ; -C 171 ; WX 600 ; N guillemotleft ; B 8 70 553 446 ; -C 172 ; WX 600 ; N guilsinglleft ; B 141 70 459 446 ; -C 173 ; WX 600 ; N guilsinglright ; B 141 70 459 446 ; -C 174 ; WX 600 ; N fi ; B 22 0 583 626 ; -C 175 ; WX 600 ; N fl ; B 22 0 583 626 ; -C 177 ; WX 600 ; N endash ; B 75 213 525 303 ; -C 178 ; WX 600 ; N dagger ; B 116 -70 484 580 ; -C 179 ; WX 600 ; N daggerdbl ; B 116 -70 484 580 ; -C 180 ; WX 600 ; N periodcentered ; B 206 136 394 302 ; -C 182 ; WX 600 ; N paragraph ; B 16 -70 566 580 ; -C 183 ; WX 600 ; N bullet ; B 150 142 450 420 ; -C 184 ; WX 600 ; N quotesinglbase ; B 188 -140 412 125 ; -C 185 ; WX 600 ; N quotedblbase ; B 81 -140 519 125 ; -C 186 ; WX 600 ; N quotedblright ; B 81 297 519 562 ; -C 187 ; WX 600 ; N guillemotright ; B 47 70 592 446 ; -C 188 ; WX 600 ; N ellipsis ; B 36 -15 564 96 ; -C 189 ; WX 600 ; N perthousand ; B -40 -15 786 616 ; -C 191 ; WX 600 ; N questiondown ; B 109 -146 492 449 ; -C 193 ; WX 600 ; N grave ; B 132 508 395 661 ; -C 194 ; WX 600 ; N acute ; B 205 508 468 661 ; -C 195 ; WX 600 ; N circumflex ; B 103 483 497 657 ; -C 196 ; WX 600 ; N tilde ; B 89 493 512 636 ; -C 197 ; WX 600 ; N macron ; B 88 505 512 585 ; -C 198 ; WX 600 ; N breve ; B 83 468 517 631 ; -C 199 ; WX 600 ; N dotaccent ; B 240 505 360 625 ; -C 200 ; WX 600 ; N dieresis ; B 148 505 452 625 ; -C 202 ; WX 600 ; N ring ; B 198 481 402 678 ; -C 203 ; WX 600 ; N cedilla ; B 205 -206 387 0 ; -C 205 ; WX 600 ; N hungarumlaut ; B 95 508 578 661 ; -C 206 ; WX 600 ; N ogonek ; B 169 -199 367 0 ; -C 207 ; WX 600 ; N caron ; B 103 493 497 667 ; -C 208 ; WX 600 ; N emdash ; B 0 213 600 303 ; -C 225 ; WX 600 ; N AE ; B -29 0 562 562 ; -C 227 ; WX 600 ; N ordfeminine ; B 147 196 453 580 ; -C 232 ; WX 600 ; N Lslash ; B 49 0 568 562 ; -C 233 ; WX 600 ; N Oslash ; B 32 -22 568 584 ; -C 234 ; WX 600 ; N OE ; B 0 0 570 562 ; -C 235 ; WX 600 ; N ordmasculine ; B 147 196 453 580 ; -C 241 ; WX 600 ; N ae ; B 6 -15 591 454 ; -C 245 ; WX 600 ; N dotlessi ; B 87 0 513 439 ; -C 248 ; WX 600 ; N lslash ; B 87 0 513 626 ; -C 249 ; WX 600 ; N oslash ; B 40 -24 560 463 ; -C 250 ; WX 600 ; N oe ; B -8 -15 601 454 ; -C 251 ; WX 600 ; N germandbls ; B 32 -15 586 626 ; -C -1 ; WX 600 ; N scedilla ; B 78 -206 525 459 ; -C -1 ; WX 600 ; N notegraphic ; B 87 -15 513 572 ; -C -1 ; WX 600 ; N Ocircumflex ; B 32 -18 568 780 ; -C -1 ; WX 600 ; N ll ; B -2 0 590 626 ; -C -1 ; WX 600 ; N otilde ; B 40 -15 560 636 ; -C -1 ; WX 600 ; N scaron ; B 78 -17 525 667 ; -C -1 ; WX 600 ; N divide ; B 81 -15 519 453 ; -C -1 ; WX 600 ; N Thorn ; B 58 0 547 562 ; -C -1 ; WX 600 ; N format ; B 5 -146 95 598 ; -C -1 ; WX 600 ; N largebullet ; B 258 239 342 323 ; -C -1 ; WX 600 ; N Eth ; B 40 0 584 562 ; -C -1 ; WX 600 ; N Odieresis ; B 32 -18 568 748 ; -C -1 ; WX 600 ; N onesuperior ; B 158 230 442 616 ; -C -1 ; WX 600 ; N dectab ; B 18 0 582 290 ; -C -1 ; WX 600 ; N Ydieresis ; B 22 0 579 748 ; -C -1 ; WX 600 ; N merge ; B 144 -15 456 487 ; -C -1 ; WX 600 ; N IJ ; B 2 -18 612 562 ; -C -1 ; WX 600 ; N ccedilla ; B 50 -206 539 459 ; -C -1 ; WX 600 ; N multiply ; B 81 0 520 439 ; -C -1 ; WX 600 ; N degree ; B 86 243 474 616 ; -C -1 ; WX 600 ; N prescription ; B 34 -15 589 562 ; -C -1 ; WX 600 ; N indent ; B 70 52 530 364 ; -C -1 ; WX 600 ; N Otilde ; B 32 -18 568 759 ; -C -1 ; WX 600 ; N thorn ; B -4 -142 560 626 ; -C -1 ; WX 600 ; N mu ; B 9 -142 559 439 ; -C -1 ; WX 600 ; N Yacute ; B 22 0 579 784 ; -C -1 ; WX 600 ; N threesuperior ; B 148 222 423 616 ; -C -1 ; WX 600 ; N logicalnot ; B 81 59 519 349 ; -C -1 ; WX 600 ; N Ugrave ; B 14 -18 586 784 ; -C -1 ; WX 600 ; N eth ; B 68 -27 533 626 ; -C -1 ; WX 600 ; N left ; B 70 52 530 364 ; -C -1 ; WX 600 ; N Ecircumflex ; B 40 0 545 780 ; -C -1 ; WX 600 ; N edieresis ; B 50 -15 553 625 ; -C -1 ; WX 600 ; N Ograve ; B 32 -18 568 784 ; -C -1 ; WX 600 ; N down ; B 144 -15 456 422 ; -C -1 ; WX 600 ; N Agrave ; B 1 0 599 784 ; -C -1 ; WX 600 ; N atilde ; B 45 -15 560 636 ; -C -1 ; WX 600 ; N up ; B 144 0 456 437 ; -C -1 ; WX 600 ; N eacute ; B 50 -15 553 661 ; -C -1 ; WX 600 ; N graybox ; B 76 0 525 599 ; -C -1 ; WX 600 ; N lira ; B 82 -28 548 611 ; -C -1 ; WX 600 ; N Icircumflex ; B 87 0 513 780 ; -C -1 ; WX 600 ; N Adieresis ; B 1 0 599 748 ; -C -1 ; WX 600 ; N yacute ; B 6 -142 591 661 ; -C -1 ; WX 600 ; N icircumflex ; B 63 0 513 657 ; -C -1 ; WX 600 ; N adieresis ; B 45 -15 560 625 ; -C -1 ; WX 600 ; N zcaron ; B 91 0 510 667 ; -C -1 ; WX 600 ; N Scaron ; B 57 -22 543 790 ; -C -1 ; WX 600 ; N minus ; B 81 174 519 264 ; -C -1 ; WX 600 ; N Aring ; B 1 0 599 801 ; -C -1 ; WX 600 ; N Ucircumflex ; B 14 -18 586 780 ; -C -1 ; WX 600 ; N plusminus ; B 81 0 519 461 ; -C -1 ; WX 600 ; N ograve ; B 40 -15 560 661 ; -C -1 ; WX 600 ; N Edieresis ; B 40 0 545 748 ; -C -1 ; WX 600 ; N brokenbar ; B 255 -77 345 626 ; -C -1 ; WX 600 ; N Idieresis ; B 87 0 513 748 ; -C -1 ; WX 600 ; N acircumflex ; B 45 -15 560 657 ; -C -1 ; WX 600 ; N ydieresis ; B 6 -142 591 625 ; -C -1 ; WX 600 ; N Oacute ; B 32 -18 568 784 ; -C -1 ; WX 600 ; N Egrave ; B 40 0 545 784 ; -C -1 ; WX 600 ; N center ; B 40 14 560 580 ; -C -1 ; WX 600 ; N threequarters ; B -20 -60 675 661 ; -C -1 ; WX 600 ; N tab ; B 19 0 581 562 ; -C -1 ; WX 600 ; N ecircumflex ; B 50 -15 553 657 ; -C -1 ; WX 600 ; N Eacute ; B 40 0 545 784 ; -C -1 ; WX 600 ; N trademark ; B -9 230 749 562 ; -C -1 ; WX 600 ; N square ; B 19 0 581 562 ; -C -1 ; WX 600 ; N onehalf ; B -20 -60 675 661 ; -C -1 ; WX 600 ; N onequarter ; B -20 -60 692 661 ; -C -1 ; WX 600 ; N Uacute ; B 14 -18 586 784 ; -C -1 ; WX 600 ; N Atilde ; B 1 0 599 759 ; -C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ; -C -1 ; WX 600 ; N Igrave ; B 87 0 513 784 ; -C -1 ; WX 600 ; N Iacute ; B 87 0 513 784 ; -C -1 ; WX 600 ; N Acircumflex ; B 1 0 599 780 ; -C -1 ; WX 600 ; N Udieresis ; B 14 -18 586 748 ; -C -1 ; WX 600 ; N Gcaron ; B 32 -18 584 790 ; -C -1 ; WX 600 ; N Aacute ; B 1 0 599 784 ; -C -1 ; WX 600 ; N LL ; B -35 0 635 562 ; -C -1 ; WX 600 ; N twosuperior ; B 153 230 426 616 ; -C -1 ; WX 600 ; N Scedilla ; B 57 -206 543 582 ; -C -1 ; WX 600 ; N arrowboth ; B -24 143 624 455 ; -C -1 ; WX 600 ; N udieresis ; B 9 -15 559 625 ; -C -1 ; WX 600 ; N odieresis ; B 40 -15 560 625 ; -C -1 ; WX 600 ; N aring ; B 45 -15 560 678 ; -C -1 ; WX 600 ; N ij ; B 16 -146 564 648 ; -C -1 ; WX 600 ; N arrowdown ; B 144 -15 456 608 ; -C -1 ; WX 600 ; N igrave ; B 87 0 513 661 ; -C -1 ; WX 600 ; N aacute ; B 45 -15 560 661 ; -C -1 ; WX 600 ; N stop ; B 19 0 581 562 ; -C -1 ; WX 600 ; N ocircumflex ; B 40 -15 560 657 ; -C -1 ; WX 600 ; N gcaron ; B 40 -146 570 667 ; -C -1 ; WX 600 ; N iacute ; B 87 0 513 661 ; -C -1 ; WX 600 ; N Ntilde ; B 18 -12 600 759 ; -C -1 ; WX 600 ; N idieresis ; B 87 0 513 625 ; -C -1 ; WX 600 ; N Ccedilla ; B 32 -206 554 580 ; -C -1 ; WX 600 ; N arrowright ; B -24 143 624 455 ; -C -1 ; WX 600 ; N ucircumflex ; B 9 -15 559 657 ; -C -1 ; WX 600 ; N Idot ; B 87 0 513 748 ; -C -1 ; WX 600 ; N agrave ; B 45 -15 560 661 ; -C -1 ; WX 600 ; N ntilde ; B 28 0 582 636 ; -C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ; -C -1 ; WX 600 ; N return ; B 19 0 581 562 ; -C -1 ; WX 600 ; N Zcaron ; B 72 0 529 790 ; -C -1 ; WX 600 ; N uacute ; B 9 -15 559 661 ; -C -1 ; WX 600 ; N overscore ; B 0 579 600 629 ; -C -1 ; WX 600 ; N egrave ; B 50 -15 553 661 ; -C -1 ; WX 600 ; N ugrave ; B 9 -15 559 661 ; -C -1 ; WX 600 ; N oacute ; B 40 -15 560 661 ; -C -1 ; WX 600 ; N arrowleft ; B -24 143 624 455 ; -C -1 ; WX 600 ; N arrowup ; B 144 0 456 623 ; -EndCharMetrics -StartComposites 62 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 30 123 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex -30 123 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis -20 123 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave -50 123 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring -10 123 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde -30 123 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 0 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 30 123 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 0 123 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 0 123 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 0 123 ; -CC Gcaron 2 ; PCC G 0 0 ; PCC caron 10 123 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute 0 123 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 0 123 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 0 123 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave 0 123 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 0 123 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 0 123 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 0 123 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 0 123 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 0 123 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 0 123 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 0 123 ; -CC Scedilla 2 ; PCC S 0 0 ; PCC cedilla 20 0 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 30 123 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 0 123 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 0 123 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave -30 123 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 30 123 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 0 123 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 0 123 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 0 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex -20 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis -10 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave -30 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 0 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 0 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 0 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 0 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 0 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 0 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 0 0 ; -CC gcaron 2 ; PCC g 0 0 ; PCC caron -40 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -40 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -40 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave 0 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 0 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 0 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 0 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 0 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 0 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 0 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 0 0 ; -CC scedilla 2 ; PCC s 0 0 ; PCC cedilla 0 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute 0 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex -20 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis -20 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave -30 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute 30 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 10 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 0 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Courier-BoldOblique.afm b/config/psfonts/Courier-BoldOblique.afm deleted file mode 100644 index 77e50d78..00000000 --- a/config/psfonts/Courier-BoldOblique.afm +++ /dev/null @@ -1,348 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1989 1990 Adobe Systems Incorporated. All rights reserved. -Comment Creation Date: Thu Jan 18 17:20:38 1990 -Comment UniqueID 27068 -Comment VMusage 6910 48006 -FontName Courier-BoldOblique -FullName Courier Bold Oblique -FamilyName Courier -Weight Bold -ItalicAngle -12 -IsFixedPitch true -FontBBox -46 -206 868 801 -UnderlinePosition -100 -UnderlineThickness 50 -Version 002.003 -Notice Copyright (c) 1989 1990 Adobe Systems Incorporated. All rights reserved. -EncodingScheme AdobeStandardEncoding -CapHeight 562 -XHeight 439 -Ascender 626 -Descender -142 -StartCharMetrics 260 -C 32 ; WX 600 ; N space ; B 0 0 0 0 ; -C 33 ; WX 600 ; N exclam ; B 224 -15 484 572 ; -C 34 ; WX 600 ; N quotedbl ; B 226 297 574 562 ; -C 35 ; WX 600 ; N numbersign ; B 100 -45 628 651 ; -C 36 ; WX 600 ; N dollar ; B 97 -126 619 666 ; -C 37 ; WX 600 ; N percent ; B 103 -15 624 616 ; -C 38 ; WX 600 ; N ampersand ; B 72 -15 582 543 ; -C 39 ; WX 600 ; N quoteright ; B 251 297 531 562 ; -C 40 ; WX 600 ; N parenleft ; B 276 -102 582 616 ; -C 41 ; WX 600 ; N parenright ; B 127 -102 434 616 ; -C 42 ; WX 600 ; N asterisk ; B 179 219 597 601 ; -C 43 ; WX 600 ; N plus ; B 118 0 575 439 ; -C 44 ; WX 600 ; N comma ; B 119 -101 409 164 ; -C 45 ; WX 600 ; N hyphen ; B 155 213 554 303 ; -C 46 ; WX 600 ; N period ; B 219 -15 410 151 ; -C 47 ; WX 600 ; N slash ; B 96 -77 622 626 ; -C 48 ; WX 600 ; N zero ; B 146 -15 583 616 ; -C 49 ; WX 600 ; N one ; B 103 0 547 616 ; -C 50 ; WX 600 ; N two ; B 71 0 583 616 ; -C 51 ; WX 600 ; N three ; B 82 -15 561 616 ; -C 52 ; WX 600 ; N four ; B 92 0 544 616 ; -C 53 ; WX 600 ; N five ; B 87 -15 611 601 ; -C 54 ; WX 600 ; N six ; B 146 -15 642 616 ; -C 55 ; WX 600 ; N seven ; B 157 0 612 601 ; -C 56 ; WX 600 ; N eight ; B 125 -15 594 616 ; -C 57 ; WX 600 ; N nine ; B 86 -15 582 616 ; -C 58 ; WX 600 ; N colon ; B 219 -15 464 405 ; -C 59 ; WX 600 ; N semicolon ; B 119 -101 464 405 ; -C 60 ; WX 600 ; N less ; B 113 -15 584 453 ; -C 61 ; WX 600 ; N equal ; B 100 89 593 349 ; -C 62 ; WX 600 ; N greater ; B 109 -15 581 453 ; -C 63 ; WX 600 ; N question ; B 193 -15 581 580 ; -C 64 ; WX 600 ; N at ; B 76 -15 627 616 ; -C 65 ; WX 600 ; N A ; B 1 0 617 562 ; -C 66 ; WX 600 ; N B ; B 40 0 619 562 ; -C 67 ; WX 600 ; N C ; B 85 -18 664 580 ; -C 68 ; WX 600 ; N D ; B 40 0 654 562 ; -C 69 ; WX 600 ; N E ; B 40 0 654 562 ; -C 70 ; WX 600 ; N F ; B 54 0 668 562 ; -C 71 ; WX 600 ; N G ; B 85 -18 664 580 ; -C 72 ; WX 600 ; N H ; B 30 0 689 562 ; -C 73 ; WX 600 ; N I ; B 87 0 632 562 ; -C 74 ; WX 600 ; N J ; B 69 -18 710 562 ; -C 75 ; WX 600 ; N K ; B 36 0 676 562 ; -C 76 ; WX 600 ; N L ; B 49 0 625 562 ; -C 77 ; WX 600 ; N M ; B 3 0 716 562 ; -C 78 ; WX 600 ; N N ; B 18 -12 719 562 ; -C 79 ; WX 600 ; N O ; B 84 -18 636 580 ; -C 80 ; WX 600 ; N P ; B 58 0 634 562 ; -C 81 ; WX 600 ; N Q ; B 84 -123 636 580 ; -C 82 ; WX 600 ; N R ; B 34 0 607 562 ; -C 83 ; WX 600 ; N S ; B 64 -22 662 582 ; -C 84 ; WX 600 ; N T ; B 96 0 668 562 ; -C 85 ; WX 600 ; N U ; B 116 -18 705 562 ; -C 86 ; WX 600 ; N V ; B 99 0 722 562 ; -C 87 ; WX 600 ; N W ; B 94 0 727 562 ; -C 88 ; WX 600 ; N X ; B 22 0 679 562 ; -C 89 ; WX 600 ; N Y ; B 124 0 698 562 ; -C 90 ; WX 600 ; N Z ; B 72 0 626 562 ; -C 91 ; WX 600 ; N bracketleft ; B 233 -102 596 616 ; -C 92 ; WX 600 ; N backslash ; B 231 -77 487 626 ; -C 93 ; WX 600 ; N bracketright ; B 113 -102 476 616 ; -C 94 ; WX 600 ; N asciicircum ; B 171 249 555 616 ; -C 95 ; WX 600 ; N underscore ; B -27 -125 584 -75 ; -C 96 ; WX 600 ; N quoteleft ; B 251 297 531 562 ; -C 97 ; WX 600 ; N a ; B 72 -15 578 454 ; -C 98 ; WX 600 ; N b ; B 23 -15 626 626 ; -C 99 ; WX 600 ; N c ; B 91 -15 621 459 ; -C 100 ; WX 600 ; N d ; B 71 -15 634 626 ; -C 101 ; WX 600 ; N e ; B 91 -15 594 454 ; -C 102 ; WX 600 ; N f ; B 93 0 667 626 ; L i fi ; L l fl ; -C 103 ; WX 600 ; N g ; B 51 -146 663 454 ; -C 104 ; WX 600 ; N h ; B 28 0 600 626 ; -C 105 ; WX 600 ; N i ; B 87 0 531 648 ; -C 106 ; WX 600 ; N j ; B 47 -146 568 648 ; -C 107 ; WX 600 ; N k ; B 43 0 632 626 ; -C 108 ; WX 600 ; N l ; B 87 0 531 626 ; -C 109 ; WX 600 ; N m ; B -12 0 634 454 ; -C 110 ; WX 600 ; N n ; B 28 0 600 454 ; -C 111 ; WX 600 ; N o ; B 81 -15 612 454 ; -C 112 ; WX 600 ; N p ; B -21 -142 612 454 ; -C 113 ; WX 600 ; N q ; B 71 -142 674 454 ; -C 114 ; WX 600 ; N r ; B 57 0 644 454 ; -C 115 ; WX 600 ; N s ; B 77 -17 597 459 ; -C 116 ; WX 600 ; N t ; B 132 -15 556 562 ; -C 117 ; WX 600 ; N u ; B 84 -15 577 439 ; -C 118 ; WX 600 ; N v ; B 84 0 684 439 ; -C 119 ; WX 600 ; N w ; B 67 0 701 439 ; -C 120 ; WX 600 ; N x ; B 16 0 660 439 ; -C 121 ; WX 600 ; N y ; B -10 -142 684 439 ; -C 122 ; WX 600 ; N z ; B 91 0 603 439 ; -C 123 ; WX 600 ; N braceleft ; B 216 -102 585 616 ; -C 124 ; WX 600 ; N bar ; B 239 -77 478 626 ; -C 125 ; WX 600 ; N braceright ; B 124 -102 494 616 ; -C 126 ; WX 600 ; N asciitilde ; B 120 124 573 307 ; -C 161 ; WX 600 ; N exclamdown ; B 207 -146 468 449 ; -C 162 ; WX 600 ; N cent ; B 131 -49 594 614 ; -C 163 ; WX 600 ; N sterling ; B 117 -28 640 611 ; -C 164 ; WX 600 ; N fraction ; B 27 -60 702 661 ; -C 165 ; WX 600 ; N yen ; B 110 0 706 591 ; -C 166 ; WX 600 ; N florin ; B -46 -131 691 616 ; -C 167 ; WX 600 ; N section ; B 94 -70 599 580 ; -C 168 ; WX 600 ; N currency ; B 77 49 643 517 ; -C 169 ; WX 600 ; N quotesingle ; B 318 297 482 562 ; -C 170 ; WX 600 ; N quotedblleft ; B 144 297 638 562 ; -C 171 ; WX 600 ; N guillemotleft ; B 63 70 638 446 ; -C 172 ; WX 600 ; N guilsinglleft ; B 196 70 544 446 ; -C 173 ; WX 600 ; N guilsinglright ; B 166 70 514 446 ; -C 174 ; WX 600 ; N fi ; B 22 0 633 626 ; -C 175 ; WX 600 ; N fl ; B 22 0 633 626 ; -C 177 ; WX 600 ; N endash ; B 120 213 589 303 ; -C 178 ; WX 600 ; N dagger ; B 188 -70 573 580 ; -C 179 ; WX 600 ; N daggerdbl ; B 134 -70 574 580 ; -C 180 ; WX 600 ; N periodcentered ; B 251 136 442 302 ; -C 182 ; WX 600 ; N paragraph ; B 71 -70 689 580 ; -C 183 ; WX 600 ; N bullet ; B 207 142 513 420 ; -C 184 ; WX 600 ; N quotesinglbase ; B 158 -140 439 125 ; -C 185 ; WX 600 ; N quotedblbase ; B 51 -140 546 125 ; -C 186 ; WX 600 ; N quotedblright ; B 144 297 638 562 ; -C 187 ; WX 600 ; N guillemotright ; B 72 70 647 446 ; -C 188 ; WX 600 ; N ellipsis ; B 43 -15 574 96 ; -C 189 ; WX 600 ; N perthousand ; B 24 -15 815 616 ; -C 191 ; WX 600 ; N questiondown ; B 111 -146 499 449 ; -C 193 ; WX 600 ; N grave ; B 272 508 503 661 ; -C 194 ; WX 600 ; N acute ; B 313 508 608 661 ; -C 195 ; WX 600 ; N circumflex ; B 212 483 606 657 ; -C 196 ; WX 600 ; N tilde ; B 200 493 642 636 ; -C 197 ; WX 600 ; N macron ; B 195 505 636 585 ; -C 198 ; WX 600 ; N breve ; B 217 468 651 631 ; -C 199 ; WX 600 ; N dotaccent ; B 359 505 482 625 ; -C 200 ; WX 600 ; N dieresis ; B 267 505 574 625 ; -C 202 ; WX 600 ; N ring ; B 319 481 528 678 ; -C 203 ; WX 600 ; N cedilla ; B 169 -206 367 0 ; -C 205 ; WX 600 ; N hungarumlaut ; B 203 508 718 661 ; -C 206 ; WX 600 ; N ogonek ; B 144 -199 350 0 ; -C 207 ; WX 600 ; N caron ; B 238 493 632 667 ; -C 208 ; WX 600 ; N emdash ; B 45 213 664 303 ; -C 225 ; WX 600 ; N AE ; B -29 0 667 562 ; -C 227 ; WX 600 ; N ordfeminine ; B 189 196 526 580 ; -C 232 ; WX 600 ; N Lslash ; B 49 0 625 562 ; -C 233 ; WX 600 ; N Oslash ; B 48 -22 672 584 ; -C 234 ; WX 600 ; N OE ; B 51 0 675 562 ; -C 235 ; WX 600 ; N ordmasculine ; B 189 196 542 580 ; -C 241 ; WX 600 ; N ae ; B 30 -15 641 454 ; -C 245 ; WX 600 ; N dotlessi ; B 87 0 531 439 ; -C 248 ; WX 600 ; N lslash ; B 87 0 574 626 ; -C 249 ; WX 600 ; N oslash ; B 54 -24 637 463 ; -C 250 ; WX 600 ; N oe ; B 29 -15 651 454 ; -C 251 ; WX 600 ; N germandbls ; B 32 -15 618 626 ; -C -1 ; WX 600 ; N scedilla ; B 77 -206 597 459 ; -C -1 ; WX 600 ; N notegraphic ; B 99 -15 609 572 ; -C -1 ; WX 600 ; N Ocircumflex ; B 84 -18 636 780 ; -C -1 ; WX 600 ; N ll ; B 11 0 643 626 ; -C -1 ; WX 600 ; N otilde ; B 81 -15 642 636 ; -C -1 ; WX 600 ; N scaron ; B 77 -17 632 667 ; -C -1 ; WX 600 ; N divide ; B 118 -15 575 453 ; -C -1 ; WX 600 ; N Thorn ; B 58 0 613 562 ; -C -1 ; WX 600 ; N format ; B -26 -146 222 598 ; -C -1 ; WX 600 ; N largebullet ; B 317 239 403 323 ; -C -1 ; WX 600 ; N Eth ; B 40 0 654 562 ; -C -1 ; WX 600 ; N Odieresis ; B 84 -18 636 748 ; -C -1 ; WX 600 ; N onesuperior ; B 218 230 506 616 ; -C -1 ; WX 600 ; N dectab ; B 18 0 601 290 ; -C -1 ; WX 600 ; N Ydieresis ; B 124 0 698 748 ; -C -1 ; WX 600 ; N merge ; B 174 -15 526 487 ; -C -1 ; WX 600 ; N IJ ; B 2 -18 731 562 ; -C -1 ; WX 600 ; N ccedilla ; B 91 -206 621 459 ; -C -1 ; WX 600 ; N multiply ; B 94 0 600 439 ; -C -1 ; WX 600 ; N degree ; B 173 243 569 616 ; -C -1 ; WX 600 ; N prescription ; B 34 -15 632 562 ; -C -1 ; WX 600 ; N indent ; B 106 52 574 364 ; -C -1 ; WX 600 ; N Otilde ; B 84 -18 668 759 ; -C -1 ; WX 600 ; N thorn ; B -21 -142 612 626 ; -C -1 ; WX 600 ; N mu ; B 60 -142 577 439 ; -C -1 ; WX 600 ; N Yacute ; B 124 0 698 784 ; -C -1 ; WX 600 ; N threesuperior ; B 203 222 515 616 ; -C -1 ; WX 600 ; N logicalnot ; B 136 59 593 349 ; -C -1 ; WX 600 ; N Ugrave ; B 116 -18 705 784 ; -C -1 ; WX 600 ; N eth ; B 103 -27 651 626 ; -C -1 ; WX 600 ; N left ; B 114 52 582 364 ; -C -1 ; WX 600 ; N Ecircumflex ; B 40 0 654 780 ; -C -1 ; WX 600 ; N edieresis ; B 91 -15 594 625 ; -C -1 ; WX 600 ; N Ograve ; B 84 -18 636 784 ; -C -1 ; WX 600 ; N down ; B 174 -15 486 422 ; -C -1 ; WX 600 ; N Agrave ; B 1 0 617 784 ; -C -1 ; WX 600 ; N atilde ; B 72 -15 642 636 ; -C -1 ; WX 600 ; N up ; B 204 0 516 437 ; -C -1 ; WX 600 ; N eacute ; B 91 -15 608 661 ; -C -1 ; WX 600 ; N graybox ; B 76 0 652 599 ; -C -1 ; WX 600 ; N lira ; B 117 -28 640 611 ; -C -1 ; WX 600 ; N Icircumflex ; B 87 0 632 780 ; -C -1 ; WX 600 ; N Adieresis ; B 1 0 617 748 ; -C -1 ; WX 600 ; N yacute ; B -10 -142 684 661 ; -C -1 ; WX 600 ; N icircumflex ; B 87 0 566 657 ; -C -1 ; WX 600 ; N adieresis ; B 72 -15 578 625 ; -C -1 ; WX 600 ; N zcaron ; B 91 0 632 667 ; -C -1 ; WX 600 ; N Scaron ; B 64 -22 662 790 ; -C -1 ; WX 600 ; N minus ; B 118 174 575 264 ; -C -1 ; WX 600 ; N Aring ; B 1 0 617 801 ; -C -1 ; WX 600 ; N Ucircumflex ; B 116 -18 705 780 ; -C -1 ; WX 600 ; N plusminus ; B 81 0 592 461 ; -C -1 ; WX 600 ; N ograve ; B 81 -15 612 661 ; -C -1 ; WX 600 ; N Edieresis ; B 40 0 654 748 ; -C -1 ; WX 600 ; N brokenbar ; B 239 -77 478 626 ; -C -1 ; WX 600 ; N Idieresis ; B 87 0 632 748 ; -C -1 ; WX 600 ; N acircumflex ; B 72 -15 586 657 ; -C -1 ; WX 600 ; N ydieresis ; B -10 -142 684 625 ; -C -1 ; WX 600 ; N Oacute ; B 84 -18 636 784 ; -C -1 ; WX 600 ; N Egrave ; B 40 0 654 784 ; -C -1 ; WX 600 ; N center ; B 103 14 623 580 ; -C -1 ; WX 600 ; N threequarters ; B 35 -60 725 661 ; -C -1 ; WX 600 ; N tab ; B 19 0 641 562 ; -C -1 ; WX 600 ; N ecircumflex ; B 91 -15 606 657 ; -C -1 ; WX 600 ; N Eacute ; B 40 0 665 784 ; -C -1 ; WX 600 ; N trademark ; B 86 230 868 562 ; -C -1 ; WX 600 ; N square ; B 19 0 700 562 ; -C -1 ; WX 600 ; N onehalf ; B 50 -60 742 661 ; -C -1 ; WX 600 ; N onequarter ; B 50 -60 742 661 ; -C -1 ; WX 600 ; N Uacute ; B 116 -18 705 784 ; -C -1 ; WX 600 ; N Atilde ; B 1 0 638 759 ; -C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ; -C -1 ; WX 600 ; N Igrave ; B 87 0 632 784 ; -C -1 ; WX 600 ; N Iacute ; B 87 0 635 784 ; -C -1 ; WX 600 ; N Acircumflex ; B 1 0 617 780 ; -C -1 ; WX 600 ; N Udieresis ; B 116 -18 705 748 ; -C -1 ; WX 600 ; N Gcaron ; B 85 -18 669 790 ; -C -1 ; WX 600 ; N Aacute ; B 1 0 665 784 ; -C -1 ; WX 600 ; N LL ; B -35 0 684 562 ; -C -1 ; WX 600 ; N twosuperior ; B 202 230 531 616 ; -C -1 ; WX 600 ; N Scedilla ; B 64 -206 662 582 ; -C -1 ; WX 600 ; N arrowboth ; B 40 143 688 455 ; -C -1 ; WX 600 ; N udieresis ; B 84 -15 577 625 ; -C -1 ; WX 600 ; N odieresis ; B 81 -15 612 625 ; -C -1 ; WX 600 ; N aring ; B 72 -15 578 678 ; -C -1 ; WX 600 ; N ij ; B 16 -146 702 648 ; -C -1 ; WX 600 ; N arrowdown ; B 174 -15 486 608 ; -C -1 ; WX 600 ; N igrave ; B 87 0 531 661 ; -C -1 ; WX 600 ; N aacute ; B 72 -15 608 661 ; -C -1 ; WX 600 ; N stop ; B 19 0 700 562 ; -C -1 ; WX 600 ; N ocircumflex ; B 81 -15 612 657 ; -C -1 ; WX 600 ; N gcaron ; B 51 -146 663 667 ; -C -1 ; WX 600 ; N iacute ; B 87 0 608 661 ; -C -1 ; WX 600 ; N Ntilde ; B 18 -12 719 759 ; -C -1 ; WX 600 ; N idieresis ; B 87 0 534 625 ; -C -1 ; WX 600 ; N Ccedilla ; B 85 -206 664 580 ; -C -1 ; WX 600 ; N arrowright ; B 32 143 688 455 ; -C -1 ; WX 600 ; N ucircumflex ; B 84 -15 586 657 ; -C -1 ; WX 600 ; N Idot ; B 87 0 632 748 ; -C -1 ; WX 600 ; N agrave ; B 72 -15 578 661 ; -C -1 ; WX 600 ; N ntilde ; B 28 0 642 636 ; -C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ; -C -1 ; WX 600 ; N return ; B 79 0 700 562 ; -C -1 ; WX 600 ; N Zcaron ; B 72 0 659 790 ; -C -1 ; WX 600 ; N uacute ; B 84 -15 608 661 ; -C -1 ; WX 600 ; N overscore ; B 123 579 734 629 ; -C -1 ; WX 600 ; N egrave ; B 91 -15 594 661 ; -C -1 ; WX 600 ; N ugrave ; B 84 -15 577 661 ; -C -1 ; WX 600 ; N oacute ; B 81 -15 612 661 ; -C -1 ; WX 600 ; N arrowleft ; B 40 143 695 455 ; -C -1 ; WX 600 ; N arrowup ; B 243 0 555 623 ; -EndCharMetrics -StartComposites 62 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 56 123 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex -4 123 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 6 123 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave -24 123 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring 16 123 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde -4 123 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 0 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 56 123 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 26 123 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 26 123 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 26 123 ; -CC Gcaron 2 ; PCC G 0 0 ; PCC caron 36 123 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute 26 123 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 26 123 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 26 123 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave 26 123 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 26 123 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 26 123 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 26 123 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 26 123 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 26 123 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 26 123 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 26 123 ; -CC Scedilla 2 ; PCC S 0 0 ; PCC cedilla 20 0 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 56 123 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 26 123 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 26 123 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave -4 123 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 56 123 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 26 123 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 26 123 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 0 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex -20 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis -10 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave -30 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 0 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 0 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 0 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 0 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 0 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 0 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 0 0 ; -CC gcaron 2 ; PCC g 0 0 ; PCC caron -40 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -40 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -40 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave 0 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 0 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 0 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 0 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 0 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 0 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 0 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 0 0 ; -CC scedilla 2 ; PCC s 0 0 ; PCC cedilla 0 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute 0 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex -20 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis -20 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave -30 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute 30 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 10 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 0 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Courier-Oblique.afm b/config/psfonts/Courier-Oblique.afm deleted file mode 100644 index 4dc94197..00000000 --- a/config/psfonts/Courier-Oblique.afm +++ /dev/null @@ -1,348 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1989, 1990 Adobe Systems Incorporated. All rights reserved. -Comment Creation Date: Thu Jan 18 18:32:01 1990 -Comment UniqueID 27082 -Comment VMusage 6415 46660 -FontName Courier-Oblique -FullName Courier Oblique -FamilyName Courier -Weight Medium -ItalicAngle -12 -IsFixedPitch true -FontBBox -30 -157 734 805 -UnderlinePosition -100 -UnderlineThickness 50 -Version 002.003 -Notice Copyright (c) 1989, 1990 Adobe Systems Incorporated. All rights reserved. -EncodingScheme AdobeStandardEncoding -CapHeight 562 -XHeight 426 -Ascender 629 -Descender -157 -StartCharMetrics 260 -C 32 ; WX 600 ; N space ; B 0 0 0 0 ; -C 33 ; WX 600 ; N exclam ; B 243 -15 457 572 ; -C 34 ; WX 600 ; N quotedbl ; B 273 328 532 562 ; -C 35 ; WX 600 ; N numbersign ; B 142 -32 587 639 ; -C 36 ; WX 600 ; N dollar ; B 115 -126 589 662 ; -C 37 ; WX 600 ; N percent ; B 147 -15 596 622 ; -C 38 ; WX 600 ; N ampersand ; B 94 -15 572 543 ; -C 39 ; WX 600 ; N quoteright ; B 283 328 495 562 ; -C 40 ; WX 600 ; N parenleft ; B 320 -108 565 622 ; -C 41 ; WX 600 ; N parenright ; B 144 -108 389 622 ; -C 42 ; WX 600 ; N asterisk ; B 212 257 580 607 ; -C 43 ; WX 600 ; N plus ; B 128 0 562 426 ; -C 44 ; WX 600 ; N comma ; B 157 -112 370 122 ; -C 45 ; WX 600 ; N hyphen ; B 161 238 549 278 ; -C 46 ; WX 600 ; N period ; B 238 -15 382 109 ; -C 47 ; WX 600 ; N slash ; B 111 -80 606 629 ; -C 48 ; WX 600 ; N zero ; B 161 -15 568 622 ; -C 49 ; WX 600 ; N one ; B 105 0 505 622 ; -C 50 ; WX 600 ; N two ; B 77 0 561 622 ; -C 51 ; WX 600 ; N three ; B 89 -15 531 622 ; -C 52 ; WX 600 ; N four ; B 120 0 532 622 ; -C 53 ; WX 600 ; N five ; B 105 -15 589 607 ; -C 54 ; WX 600 ; N six ; B 162 -15 629 622 ; -C 55 ; WX 600 ; N seven ; B 191 0 605 607 ; -C 56 ; WX 600 ; N eight ; B 139 -15 581 622 ; -C 57 ; WX 600 ; N nine ; B 100 -15 567 622 ; -C 58 ; WX 600 ; N colon ; B 238 -15 441 385 ; -C 59 ; WX 600 ; N semicolon ; B 157 -112 441 385 ; -C 60 ; WX 600 ; N less ; B 86 -2 603 428 ; -C 61 ; WX 600 ; N equal ; B 108 101 582 325 ; -C 62 ; WX 600 ; N greater ; B 87 -2 604 428 ; -C 63 ; WX 600 ; N question ; B 224 -15 576 572 ; -C 64 ; WX 600 ; N at ; B 134 -15 575 622 ; -C 65 ; WX 600 ; N A ; B 10 0 597 562 ; -C 66 ; WX 600 ; N B ; B 50 0 609 562 ; -C 67 ; WX 600 ; N C ; B 100 -18 651 580 ; -C 68 ; WX 600 ; N D ; B 50 0 638 562 ; -C 69 ; WX 600 ; N E ; B 60 0 653 562 ; -C 70 ; WX 600 ; N F ; B 60 0 653 562 ; -C 71 ; WX 600 ; N G ; B 90 -18 641 580 ; -C 72 ; WX 600 ; N H ; B 39 0 680 562 ; -C 73 ; WX 600 ; N I ; B 103 0 616 562 ; -C 74 ; WX 600 ; N J ; B 59 -18 678 562 ; -C 75 ; WX 600 ; N K ; B 45 0 664 562 ; -C 76 ; WX 600 ; N L ; B 54 0 598 562 ; -C 77 ; WX 600 ; N M ; B 11 0 708 562 ; -C 78 ; WX 600 ; N N ; B 14 -13 705 562 ; -C 79 ; WX 600 ; N O ; B 94 -18 625 580 ; -C 80 ; WX 600 ; N P ; B 86 0 637 562 ; -C 81 ; WX 600 ; N Q ; B 95 -129 625 580 ; -C 82 ; WX 600 ; N R ; B 45 0 590 562 ; -C 83 ; WX 600 ; N S ; B 83 -20 643 580 ; -C 84 ; WX 600 ; N T ; B 116 0 658 562 ; -C 85 ; WX 600 ; N U ; B 132 -18 695 562 ; -C 86 ; WX 600 ; N V ; B 115 -13 716 562 ; -C 87 ; WX 600 ; N W ; B 115 -13 716 562 ; -C 88 ; WX 600 ; N X ; B 30 0 668 562 ; -C 89 ; WX 600 ; N Y ; B 143 0 688 562 ; -C 90 ; WX 600 ; N Z ; B 86 0 610 562 ; -C 91 ; WX 600 ; N bracketleft ; B 253 -108 574 622 ; -C 92 ; WX 600 ; N backslash ; B 256 -80 461 629 ; -C 93 ; WX 600 ; N bracketright ; B 135 -108 456 622 ; -C 94 ; WX 600 ; N asciicircum ; B 175 359 587 622 ; -C 95 ; WX 600 ; N underscore ; B -27 -125 584 -75 ; -C 96 ; WX 600 ; N quoteleft ; B 294 328 506 562 ; -C 97 ; WX 600 ; N a ; B 83 -15 559 441 ; -C 98 ; WX 600 ; N b ; B 36 -15 618 629 ; -C 99 ; WX 600 ; N c ; B 113 -15 607 441 ; -C 100 ; WX 600 ; N d ; B 92 -15 633 629 ; -C 101 ; WX 600 ; N e ; B 113 -15 591 441 ; -C 102 ; WX 600 ; N f ; B 121 0 655 629 ; L i fi ; L l fl ; -C 103 ; WX 600 ; N g ; B 68 -157 650 441 ; -C 104 ; WX 600 ; N h ; B 40 0 582 629 ; -C 105 ; WX 600 ; N i ; B 102 0 505 657 ; -C 106 ; WX 600 ; N j ; B 59 -157 543 657 ; -C 107 ; WX 600 ; N k ; B 65 0 626 629 ; -C 108 ; WX 600 ; N l ; B 102 0 505 629 ; -C 109 ; WX 600 ; N m ; B 2 0 606 441 ; -C 110 ; WX 600 ; N n ; B 33 0 575 441 ; -C 111 ; WX 600 ; N o ; B 102 -15 588 441 ; -C 112 ; WX 600 ; N p ; B -17 -157 598 441 ; -C 113 ; WX 600 ; N q ; B 92 -157 675 441 ; -C 114 ; WX 600 ; N r ; B 67 0 631 441 ; -C 115 ; WX 600 ; N s ; B 92 -15 570 441 ; -C 116 ; WX 600 ; N t ; B 157 -15 534 561 ; -C 117 ; WX 600 ; N u ; B 111 -15 562 426 ; -C 118 ; WX 600 ; N v ; B 100 -10 674 426 ; -C 119 ; WX 600 ; N w ; B 82 -10 692 426 ; -C 120 ; WX 600 ; N x ; B 27 0 648 426 ; -C 121 ; WX 600 ; N y ; B -30 -157 643 426 ; -C 122 ; WX 600 ; N z ; B 106 0 586 426 ; -C 123 ; WX 600 ; N braceleft ; B 240 -108 562 622 ; -C 124 ; WX 600 ; N bar ; B 265 -80 453 629 ; -C 125 ; WX 600 ; N braceright ; B 147 -108 470 622 ; -C 126 ; WX 600 ; N asciitilde ; B 110 160 585 269 ; -C 161 ; WX 600 ; N exclamdown ; B 232 -157 445 430 ; -C 162 ; WX 600 ; N cent ; B 158 -49 581 614 ; -C 163 ; WX 600 ; N sterling ; B 131 -21 614 611 ; -C 164 ; WX 600 ; N fraction ; B 23 -57 706 665 ; -C 165 ; WX 600 ; N yen ; B 135 0 693 594 ; -C 166 ; WX 600 ; N florin ; B -19 -143 664 622 ; -C 167 ; WX 600 ; N section ; B 111 -78 583 580 ; -C 168 ; WX 600 ; N currency ; B 99 65 621 499 ; -C 169 ; WX 600 ; N quotesingle ; B 345 328 460 562 ; -C 170 ; WX 600 ; N quotedblleft ; B 213 328 576 562 ; -C 171 ; WX 600 ; N guillemotleft ; B 92 70 652 446 ; -C 172 ; WX 600 ; N guilsinglleft ; B 204 70 540 446 ; -C 173 ; WX 600 ; N guilsinglright ; B 170 70 506 446 ; -C 174 ; WX 600 ; N fi ; B 10 0 612 629 ; -C 175 ; WX 600 ; N fl ; B 10 0 612 629 ; -C 177 ; WX 600 ; N endash ; B 126 238 584 278 ; -C 178 ; WX 600 ; N dagger ; B 226 -78 537 580 ; -C 179 ; WX 600 ; N daggerdbl ; B 171 -78 537 580 ; -C 180 ; WX 600 ; N periodcentered ; B 273 152 418 276 ; -C 182 ; WX 600 ; N paragraph ; B 107 -78 623 562 ; -C 183 ; WX 600 ; N bullet ; B 231 137 478 376 ; -C 184 ; WX 600 ; N quotesinglbase ; B 185 -134 397 100 ; -C 185 ; WX 600 ; N quotedblbase ; B 115 -134 478 100 ; -C 186 ; WX 600 ; N quotedblright ; B 213 328 576 562 ; -C 187 ; WX 600 ; N guillemotright ; B 58 70 618 446 ; -C 188 ; WX 600 ; N ellipsis ; B 51 -15 566 97 ; -C 189 ; WX 600 ; N perthousand ; B 57 -15 627 622 ; -C 191 ; WX 600 ; N questiondown ; B 112 -157 464 430 ; -C 193 ; WX 600 ; N grave ; B 294 497 484 672 ; -C 194 ; WX 600 ; N acute ; B 348 497 612 672 ; -C 195 ; WX 600 ; N circumflex ; B 229 477 581 654 ; -C 196 ; WX 600 ; N tilde ; B 219 503 617 606 ; -C 197 ; WX 600 ; N macron ; B 232 525 600 565 ; -C 198 ; WX 600 ; N breve ; B 279 501 576 609 ; -C 199 ; WX 600 ; N dotaccent ; B 379 508 452 580 ; -C 200 ; WX 600 ; N dieresis ; B 313 508 519 580 ; -C 202 ; WX 600 ; N ring ; B 344 483 492 627 ; -C 203 ; WX 600 ; N cedilla ; B 221 -151 340 10 ; -C 205 ; WX 600 ; N hungarumlaut ; B 239 497 683 672 ; -C 206 ; WX 600 ; N ogonek ; B 207 -151 348 0 ; -C 207 ; WX 600 ; N caron ; B 262 492 614 669 ; -C 208 ; WX 600 ; N emdash ; B 51 238 659 278 ; -C 225 ; WX 600 ; N AE ; B 10 0 648 562 ; -C 227 ; WX 600 ; N ordfeminine ; B 216 259 504 580 ; -C 232 ; WX 600 ; N Lslash ; B 54 0 598 562 ; -C 233 ; WX 600 ; N Oslash ; B 94 -80 625 629 ; -C 234 ; WX 600 ; N OE ; B 66 0 665 562 ; -C 235 ; WX 600 ; N ordmasculine ; B 217 259 530 580 ; -C 241 ; WX 600 ; N ae ; B 47 -15 620 441 ; -C 245 ; WX 600 ; N dotlessi ; B 102 0 505 426 ; -C 248 ; WX 600 ; N lslash ; B 102 0 559 629 ; -C 249 ; WX 600 ; N oslash ; B 102 -80 588 506 ; -C 250 ; WX 600 ; N oe ; B 61 -15 609 441 ; -C 251 ; WX 600 ; N germandbls ; B 55 -15 610 629 ; -C -1 ; WX 600 ; N scedilla ; B 92 -151 570 441 ; -C -1 ; WX 600 ; N notegraphic ; B 143 -15 557 572 ; -C -1 ; WX 600 ; N Ocircumflex ; B 94 -18 625 775 ; -C -1 ; WX 600 ; N ll ; B 40 0 609 629 ; -C -1 ; WX 600 ; N otilde ; B 102 -15 617 606 ; -C -1 ; WX 600 ; N scaron ; B 92 -15 614 669 ; -C -1 ; WX 600 ; N divide ; B 128 1 562 426 ; -C -1 ; WX 600 ; N Thorn ; B 86 0 599 562 ; -C -1 ; WX 600 ; N format ; B -28 -157 169 598 ; -C -1 ; WX 600 ; N largebullet ; B 322 227 388 290 ; -C -1 ; WX 600 ; N Eth ; B 50 0 638 562 ; -C -1 ; WX 600 ; N Odieresis ; B 94 -18 625 716 ; -C -1 ; WX 600 ; N onesuperior ; B 238 249 481 622 ; -C -1 ; WX 600 ; N dectab ; B 18 0 590 227 ; -C -1 ; WX 600 ; N Ydieresis ; B 143 0 688 716 ; -C -1 ; WX 600 ; N merge ; B 192 -15 497 436 ; -C -1 ; WX 600 ; N IJ ; B 39 -18 681 562 ; -C -1 ; WX 600 ; N ccedilla ; B 113 -151 607 441 ; -C -1 ; WX 600 ; N multiply ; B 93 -1 599 426 ; -C -1 ; WX 600 ; N degree ; B 214 269 576 622 ; -C -1 ; WX 600 ; N prescription ; B 34 -15 610 562 ; -C -1 ; WX 600 ; N indent ; B 110 75 574 341 ; -C -1 ; WX 600 ; N Otilde ; B 94 -18 644 732 ; -C -1 ; WX 600 ; N thorn ; B -17 -157 598 629 ; -C -1 ; WX 600 ; N mu ; B 79 -157 562 426 ; -C -1 ; WX 600 ; N Yacute ; B 143 0 688 793 ; -C -1 ; WX 600 ; N threesuperior ; B 220 240 494 622 ; -C -1 ; WX 600 ; N logicalnot ; B 148 64 582 325 ; -C -1 ; WX 600 ; N Ugrave ; B 132 -18 695 793 ; -C -1 ; WX 600 ; N eth ; B 102 -15 629 629 ; -C -1 ; WX 600 ; N left ; B 114 75 578 341 ; -C -1 ; WX 600 ; N Ecircumflex ; B 60 0 653 775 ; -C -1 ; WX 600 ; N edieresis ; B 113 -15 591 580 ; -C -1 ; WX 600 ; N Ograve ; B 94 -18 625 793 ; -C -1 ; WX 600 ; N down ; B 192 -15 458 422 ; -C -1 ; WX 600 ; N Agrave ; B 10 0 597 793 ; -C -1 ; WX 600 ; N atilde ; B 83 -15 617 606 ; -C -1 ; WX 600 ; N up ; B 232 0 498 437 ; -C -1 ; WX 600 ; N eacute ; B 113 -15 612 672 ; -C -1 ; WX 600 ; N graybox ; B 76 0 652 599 ; -C -1 ; WX 600 ; N lira ; B 125 -21 614 611 ; -C -1 ; WX 600 ; N Icircumflex ; B 103 0 616 775 ; -C -1 ; WX 600 ; N Adieresis ; B 10 0 597 716 ; -C -1 ; WX 600 ; N yacute ; B -30 -157 643 672 ; -C -1 ; WX 600 ; N icircumflex ; B 102 0 551 654 ; -C -1 ; WX 600 ; N adieresis ; B 83 -15 559 580 ; -C -1 ; WX 600 ; N zcaron ; B 106 0 624 669 ; -C -1 ; WX 600 ; N Scaron ; B 83 -20 673 805 ; -C -1 ; WX 600 ; N minus ; B 128 195 562 232 ; -C -1 ; WX 600 ; N Aring ; B 10 0 597 753 ; -C -1 ; WX 600 ; N Ucircumflex ; B 132 -18 695 775 ; -C -1 ; WX 600 ; N plusminus ; B 87 0 583 514 ; -C -1 ; WX 600 ; N ograve ; B 102 -15 588 672 ; -C -1 ; WX 600 ; N Edieresis ; B 60 0 653 716 ; -C -1 ; WX 600 ; N brokenbar ; B 265 -80 453 629 ; -C -1 ; WX 600 ; N Idieresis ; B 103 0 616 716 ; -C -1 ; WX 600 ; N acircumflex ; B 83 -15 581 654 ; -C -1 ; WX 600 ; N ydieresis ; B -30 -157 643 580 ; -C -1 ; WX 600 ; N Oacute ; B 94 -18 638 793 ; -C -1 ; WX 600 ; N Egrave ; B 60 0 653 793 ; -C -1 ; WX 600 ; N center ; B 103 14 623 580 ; -C -1 ; WX 600 ; N threequarters ; B 28 -57 711 665 ; -C -1 ; WX 600 ; N tab ; B 19 0 641 562 ; -C -1 ; WX 600 ; N ecircumflex ; B 113 -15 591 654 ; -C -1 ; WX 600 ; N Eacute ; B 60 0 668 793 ; -C -1 ; WX 600 ; N trademark ; B 108 263 710 562 ; -C -1 ; WX 600 ; N square ; B 19 0 700 562 ; -C -1 ; WX 600 ; N onehalf ; B 42 -57 725 665 ; -C -1 ; WX 600 ; N onequarter ; B 48 -57 731 665 ; -C -1 ; WX 600 ; N Uacute ; B 132 -18 695 793 ; -C -1 ; WX 600 ; N Atilde ; B 10 0 644 732 ; -C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ; -C -1 ; WX 600 ; N Igrave ; B 103 0 616 793 ; -C -1 ; WX 600 ; N Iacute ; B 103 0 638 793 ; -C -1 ; WX 600 ; N Acircumflex ; B 10 0 597 775 ; -C -1 ; WX 600 ; N Udieresis ; B 132 -18 695 716 ; -C -1 ; WX 600 ; N Gcaron ; B 90 -18 643 805 ; -C -1 ; WX 600 ; N Aacute ; B 10 0 658 793 ; -C -1 ; WX 600 ; N LL ; B 15 0 640 562 ; -C -1 ; WX 600 ; N twosuperior ; B 237 249 528 622 ; -C -1 ; WX 600 ; N Scedilla ; B 83 -151 643 580 ; -C -1 ; WX 600 ; N arrowboth ; B 36 122 692 476 ; -C -1 ; WX 600 ; N udieresis ; B 111 -15 562 580 ; -C -1 ; WX 600 ; N odieresis ; B 102 -15 588 580 ; -C -1 ; WX 600 ; N aring ; B 83 -15 559 627 ; -C -1 ; WX 600 ; N ij ; B 44 -157 623 657 ; -C -1 ; WX 600 ; N arrowdown ; B 157 -15 511 608 ; -C -1 ; WX 600 ; N igrave ; B 102 0 505 672 ; -C -1 ; WX 600 ; N aacute ; B 83 -15 612 672 ; -C -1 ; WX 600 ; N stop ; B 19 0 700 562 ; -C -1 ; WX 600 ; N ocircumflex ; B 102 -15 588 654 ; -C -1 ; WX 600 ; N gcaron ; B 68 -157 650 669 ; -C -1 ; WX 600 ; N iacute ; B 102 0 612 672 ; -C -1 ; WX 600 ; N Ntilde ; B 14 -13 705 732 ; -C -1 ; WX 600 ; N idieresis ; B 102 0 505 580 ; -C -1 ; WX 600 ; N Ccedilla ; B 100 -151 651 580 ; -C -1 ; WX 600 ; N arrowright ; B 35 122 688 476 ; -C -1 ; WX 600 ; N ucircumflex ; B 111 -15 571 654 ; -C -1 ; WX 600 ; N Idot ; B 103 0 616 716 ; -C -1 ; WX 600 ; N agrave ; B 83 -15 559 672 ; -C -1 ; WX 600 ; N ntilde ; B 33 0 617 606 ; -C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ; -C -1 ; WX 600 ; N return ; B 79 0 700 562 ; -C -1 ; WX 600 ; N Zcaron ; B 86 0 643 805 ; -C -1 ; WX 600 ; N uacute ; B 111 -15 602 672 ; -C -1 ; WX 600 ; N overscore ; B 123 579 734 629 ; -C -1 ; WX 600 ; N egrave ; B 113 -15 591 672 ; -C -1 ; WX 600 ; N ugrave ; B 111 -15 562 672 ; -C -1 ; WX 600 ; N oacute ; B 102 -15 612 672 ; -C -1 ; WX 600 ; N arrowleft ; B 40 122 692 476 ; -C -1 ; WX 600 ; N arrowup ; B 218 0 572 623 ; -EndCharMetrics -StartComposites 62 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 46 121 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex -4 121 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis -1 136 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave -4 121 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring 12 126 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde 27 126 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 0 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 56 121 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 26 121 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 29 136 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 26 121 ; -CC Gcaron 2 ; PCC G 0 0 ; PCC caron 29 136 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute 26 121 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 26 121 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 29 136 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave 26 121 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 27 126 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 26 121 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 26 121 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 29 136 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 26 121 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 27 126 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 59 136 ; -CC Scedilla 2 ; PCC S 0 0 ; PCC cedilla 0 0 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 56 121 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 26 121 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 29 136 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave -4 121 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 56 121 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 29 136 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 29 136 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 0 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 0 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 0 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave 0 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 0 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 0 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 0 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 0 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 0 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 0 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 0 0 ; -CC gcaron 2 ; PCC g 0 0 ; PCC caron -30 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -30 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -30 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -30 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 0 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 0 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 0 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 0 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 0 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 0 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 0 0 ; -CC scedilla 2 ; PCC s 0 0 ; PCC cedilla 0 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute -10 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex -10 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 0 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave -30 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute -20 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis -10 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 10 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Courier.afm b/config/psfonts/Courier.afm deleted file mode 100644 index 3688908c..00000000 --- a/config/psfonts/Courier.afm +++ /dev/null @@ -1,348 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1989, 1990 Adobe Systems Incorporated. All rights reserved. -Comment Creation Date: Thu Jan 18 17:48:17 1990 -Comment UniqueID 27077 -Comment VMusage 27874 40242 -FontName Courier -FullName Courier -FamilyName Courier -Weight Medium -ItalicAngle 0 -IsFixedPitch true -FontBBox -28 -157 628 805 -UnderlinePosition -100 -UnderlineThickness 50 -Version 002.003 -Notice Copyright (c) 1989, 1990 Adobe Systems Incorporated. All rights reserved. -EncodingScheme AdobeStandardEncoding -CapHeight 562 -XHeight 426 -Ascender 629 -Descender -157 -StartCharMetrics 260 -C 32 ; WX 600 ; N space ; B 0 0 0 0 ; -C 33 ; WX 600 ; N exclam ; B 236 -15 364 572 ; -C 34 ; WX 600 ; N quotedbl ; B 187 328 413 562 ; -C 35 ; WX 600 ; N numbersign ; B 100 -32 500 639 ; -C 36 ; WX 600 ; N dollar ; B 112 -126 489 662 ; -C 37 ; WX 600 ; N percent ; B 97 -15 515 622 ; -C 38 ; WX 600 ; N ampersand ; B 70 -15 531 543 ; -C 39 ; WX 600 ; N quoteright ; B 213 328 376 562 ; -C 40 ; WX 600 ; N parenleft ; B 276 -108 433 622 ; -C 41 ; WX 600 ; N parenright ; B 167 -108 324 622 ; -C 42 ; WX 600 ; N asterisk ; B 116 257 484 607 ; -C 43 ; WX 600 ; N plus ; B 87 0 513 426 ; -C 44 ; WX 600 ; N comma ; B 181 -112 344 122 ; -C 45 ; WX 600 ; N hyphen ; B 110 238 490 278 ; -C 46 ; WX 600 ; N period ; B 229 -15 371 109 ; -C 47 ; WX 600 ; N slash ; B 125 -80 475 629 ; -C 48 ; WX 600 ; N zero ; B 113 -15 487 622 ; -C 49 ; WX 600 ; N one ; B 102 0 498 622 ; -C 50 ; WX 600 ; N two ; B 77 0 464 622 ; -C 51 ; WX 600 ; N three ; B 82 -15 459 622 ; -C 52 ; WX 600 ; N four ; B 88 0 493 622 ; -C 53 ; WX 600 ; N five ; B 99 -15 490 607 ; -C 54 ; WX 600 ; N six ; B 118 -15 497 622 ; -C 55 ; WX 600 ; N seven ; B 89 0 476 607 ; -C 56 ; WX 600 ; N eight ; B 109 -15 491 622 ; -C 57 ; WX 600 ; N nine ; B 103 -15 482 622 ; -C 58 ; WX 600 ; N colon ; B 229 -15 371 385 ; -C 59 ; WX 600 ; N semicolon ; B 181 -112 371 385 ; -C 60 ; WX 600 ; N less ; B 41 -2 519 428 ; -C 61 ; WX 600 ; N equal ; B 87 101 513 325 ; -C 62 ; WX 600 ; N greater ; B 81 -2 559 428 ; -C 63 ; WX 600 ; N question ; B 136 -15 485 572 ; -C 64 ; WX 600 ; N at ; B 84 -15 526 622 ; -C 65 ; WX 600 ; N A ; B 10 0 590 562 ; -C 66 ; WX 600 ; N B ; B 50 0 552 562 ; -C 67 ; WX 600 ; N C ; B 48 -18 533 580 ; -C 68 ; WX 600 ; N D ; B 50 0 567 562 ; -C 69 ; WX 600 ; N E ; B 60 0 543 562 ; -C 70 ; WX 600 ; N F ; B 60 0 538 562 ; -C 71 ; WX 600 ; N G ; B 38 -18 568 580 ; -C 72 ; WX 600 ; N H ; B 39 0 561 562 ; -C 73 ; WX 600 ; N I ; B 103 0 497 562 ; -C 74 ; WX 600 ; N J ; B 41 -18 559 562 ; -C 75 ; WX 600 ; N K ; B 45 0 575 562 ; -C 76 ; WX 600 ; N L ; B 54 0 547 562 ; -C 77 ; WX 600 ; N M ; B 11 0 589 562 ; -C 78 ; WX 600 ; N N ; B 14 -13 586 562 ; -C 79 ; WX 600 ; N O ; B 43 -18 557 580 ; -C 80 ; WX 600 ; N P ; B 86 0 551 562 ; -C 81 ; WX 600 ; N Q ; B 43 -129 557 580 ; -C 82 ; WX 600 ; N R ; B 45 0 581 562 ; -C 83 ; WX 600 ; N S ; B 79 -20 522 580 ; -C 84 ; WX 600 ; N T ; B 45 0 556 562 ; -C 85 ; WX 600 ; N U ; B 24 -18 576 562 ; -C 86 ; WX 600 ; N V ; B 3 -13 597 562 ; -C 87 ; WX 600 ; N W ; B 3 -13 597 562 ; -C 88 ; WX 600 ; N X ; B 30 0 570 562 ; -C 89 ; WX 600 ; N Y ; B 31 0 569 562 ; -C 90 ; WX 600 ; N Z ; B 86 0 514 562 ; -C 91 ; WX 600 ; N bracketleft ; B 276 -108 442 622 ; -C 92 ; WX 600 ; N backslash ; B 125 -80 475 629 ; -C 93 ; WX 600 ; N bracketright ; B 158 -108 324 622 ; -C 94 ; WX 600 ; N asciicircum ; B 94 359 506 622 ; -C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ; -C 96 ; WX 600 ; N quoteleft ; B 224 328 387 562 ; -C 97 ; WX 600 ; N a ; B 60 -15 552 441 ; -C 98 ; WX 600 ; N b ; B 21 -15 568 629 ; -C 99 ; WX 600 ; N c ; B 73 -15 522 441 ; -C 100 ; WX 600 ; N d ; B 52 -15 584 629 ; -C 101 ; WX 600 ; N e ; B 73 -15 541 441 ; -C 102 ; WX 600 ; N f ; B 121 0 524 629 ; L i fi ; L l fl ; -C 103 ; WX 600 ; N g ; B 52 -157 559 441 ; -C 104 ; WX 600 ; N h ; B 25 0 575 629 ; -C 105 ; WX 600 ; N i ; B 102 0 498 657 ; -C 106 ; WX 600 ; N j ; B 89 -157 403 657 ; -C 107 ; WX 600 ; N k ; B 50 0 573 629 ; -C 108 ; WX 600 ; N l ; B 102 0 498 629 ; -C 109 ; WX 600 ; N m ; B 2 0 598 441 ; -C 110 ; WX 600 ; N n ; B 33 0 568 441 ; -C 111 ; WX 600 ; N o ; B 62 -15 538 441 ; -C 112 ; WX 600 ; N p ; B 16 -157 548 441 ; -C 113 ; WX 600 ; N q ; B 52 -157 584 441 ; -C 114 ; WX 600 ; N r ; B 67 0 552 441 ; -C 115 ; WX 600 ; N s ; B 94 -15 506 441 ; -C 116 ; WX 600 ; N t ; B 74 -15 503 561 ; -C 117 ; WX 600 ; N u ; B 28 -15 555 426 ; -C 118 ; WX 600 ; N v ; B 17 -10 583 426 ; -C 119 ; WX 600 ; N w ; B -1 -10 601 426 ; -C 120 ; WX 600 ; N x ; B 27 0 573 426 ; -C 121 ; WX 600 ; N y ; B -12 -157 552 426 ; -C 122 ; WX 600 ; N z ; B 106 0 495 426 ; -C 123 ; WX 600 ; N braceleft ; B 189 -108 430 622 ; -C 124 ; WX 600 ; N bar ; B 282 -80 319 629 ; -C 125 ; WX 600 ; N braceright ; B 170 -108 411 622 ; -C 126 ; WX 600 ; N asciitilde ; B 67 160 534 269 ; -C 161 ; WX 600 ; N exclamdown ; B 236 -157 364 430 ; -C 162 ; WX 600 ; N cent ; B 103 -49 493 614 ; -C 163 ; WX 600 ; N sterling ; B 91 -21 518 611 ; -C 164 ; WX 600 ; N fraction ; B 31 -57 569 665 ; -C 165 ; WX 600 ; N yen ; B 33 0 567 594 ; -C 166 ; WX 600 ; N florin ; B 11 -143 532 622 ; -C 167 ; WX 600 ; N section ; B 120 -78 481 580 ; -C 168 ; WX 600 ; N currency ; B 80 65 520 499 ; -C 169 ; WX 600 ; N quotesingle ; B 259 328 341 562 ; -C 170 ; WX 600 ; N quotedblleft ; B 143 328 457 562 ; -C 171 ; WX 600 ; N guillemotleft ; B 37 70 563 446 ; -C 172 ; WX 600 ; N guilsinglleft ; B 149 70 451 446 ; -C 173 ; WX 600 ; N guilsinglright ; B 149 70 451 446 ; -C 174 ; WX 600 ; N fi ; B 10 0 590 629 ; -C 175 ; WX 600 ; N fl ; B 10 0 590 629 ; -C 177 ; WX 600 ; N endash ; B 75 238 525 278 ; -C 178 ; WX 600 ; N dagger ; B 148 -78 452 580 ; -C 179 ; WX 600 ; N daggerdbl ; B 148 -78 452 580 ; -C 180 ; WX 600 ; N periodcentered ; B 229 152 371 276 ; -C 182 ; WX 600 ; N paragraph ; B 57 -78 504 562 ; -C 183 ; WX 600 ; N bullet ; B 179 137 421 376 ; -C 184 ; WX 600 ; N quotesinglbase ; B 213 -134 376 100 ; -C 185 ; WX 600 ; N quotedblbase ; B 143 -134 457 100 ; -C 186 ; WX 600 ; N quotedblright ; B 143 328 457 562 ; -C 187 ; WX 600 ; N guillemotright ; B 37 70 563 446 ; -C 188 ; WX 600 ; N ellipsis ; B 44 -15 556 97 ; -C 189 ; WX 600 ; N perthousand ; B 3 -15 600 622 ; -C 191 ; WX 600 ; N questiondown ; B 115 -157 464 430 ; -C 193 ; WX 600 ; N grave ; B 151 497 378 672 ; -C 194 ; WX 600 ; N acute ; B 242 497 469 672 ; -C 195 ; WX 600 ; N circumflex ; B 124 477 476 654 ; -C 196 ; WX 600 ; N tilde ; B 109 503 491 606 ; -C 197 ; WX 600 ; N macron ; B 120 525 480 565 ; -C 198 ; WX 600 ; N breve ; B 153 501 447 609 ; -C 199 ; WX 600 ; N dotaccent ; B 264 508 336 580 ; -C 200 ; WX 600 ; N dieresis ; B 198 508 402 580 ; -C 202 ; WX 600 ; N ring ; B 228 483 372 627 ; -C 203 ; WX 600 ; N cedilla ; B 249 -151 358 10 ; -C 205 ; WX 600 ; N hungarumlaut ; B 133 497 540 672 ; -C 206 ; WX 600 ; N ogonek ; B 227 -151 370 0 ; -C 207 ; WX 600 ; N caron ; B 124 492 476 669 ; -C 208 ; WX 600 ; N emdash ; B 0 238 600 278 ; -C 225 ; WX 600 ; N AE ; B 10 0 543 562 ; -C 227 ; WX 600 ; N ordfeminine ; B 161 259 437 580 ; -C 232 ; WX 600 ; N Lslash ; B 54 0 547 562 ; -C 233 ; WX 600 ; N Oslash ; B 43 -80 557 629 ; -C 234 ; WX 600 ; N OE ; B 14 0 560 562 ; -C 235 ; WX 600 ; N ordmasculine ; B 162 259 438 580 ; -C 241 ; WX 600 ; N ae ; B 26 -15 563 441 ; -C 245 ; WX 600 ; N dotlessi ; B 102 0 498 426 ; -C 248 ; WX 600 ; N lslash ; B 102 0 498 629 ; -C 249 ; WX 600 ; N oslash ; B 62 -80 538 506 ; -C 250 ; WX 600 ; N oe ; B 26 -15 552 441 ; -C 251 ; WX 600 ; N germandbls ; B 55 -15 581 629 ; -C -1 ; WX 600 ; N scedilla ; B 94 -151 506 441 ; -C -1 ; WX 600 ; N notegraphic ; B 136 -15 464 572 ; -C -1 ; WX 600 ; N Ocircumflex ; B 43 -18 557 775 ; -C -1 ; WX 600 ; N ll ; B 25 0 560 629 ; -C -1 ; WX 600 ; N otilde ; B 62 -15 538 606 ; -C -1 ; WX 600 ; N scaron ; B 94 -15 506 669 ; -C -1 ; WX 600 ; N divide ; B 87 1 513 426 ; -C -1 ; WX 600 ; N Thorn ; B 86 0 531 562 ; -C -1 ; WX 600 ; N format ; B 5 -157 42 598 ; -C -1 ; WX 600 ; N largebullet ; B 268 227 332 290 ; -C -1 ; WX 600 ; N Eth ; B 30 0 567 562 ; -C -1 ; WX 600 ; N Odieresis ; B 43 -18 557 716 ; -C -1 ; WX 600 ; N onesuperior ; B 179 249 421 622 ; -C -1 ; WX 600 ; N dectab ; B 18 0 582 227 ; -C -1 ; WX 600 ; N Ydieresis ; B 31 0 569 716 ; -C -1 ; WX 600 ; N merge ; B 167 -15 433 436 ; -C -1 ; WX 600 ; N IJ ; B 39 -18 562 562 ; -C -1 ; WX 600 ; N ccedilla ; B 73 -151 522 441 ; -C -1 ; WX 600 ; N multiply ; B 87 -1 514 426 ; -C -1 ; WX 600 ; N degree ; B 123 269 477 622 ; -C -1 ; WX 600 ; N prescription ; B 34 -15 570 562 ; -C -1 ; WX 600 ; N indent ; B 70 75 530 341 ; -C -1 ; WX 600 ; N Otilde ; B 43 -18 557 732 ; -C -1 ; WX 600 ; N thorn ; B 1 -157 548 629 ; -C -1 ; WX 600 ; N mu ; B 28 -157 555 426 ; -C -1 ; WX 600 ; N Yacute ; B 31 0 569 793 ; -C -1 ; WX 600 ; N threesuperior ; B 162 240 399 622 ; -C -1 ; WX 600 ; N logicalnot ; B 87 64 513 325 ; -C -1 ; WX 600 ; N Ugrave ; B 24 -18 576 793 ; -C -1 ; WX 600 ; N eth ; B 62 -15 538 629 ; -C -1 ; WX 600 ; N left ; B 70 75 530 341 ; -C -1 ; WX 600 ; N Ecircumflex ; B 60 0 543 775 ; -C -1 ; WX 600 ; N edieresis ; B 73 -15 541 580 ; -C -1 ; WX 600 ; N Ograve ; B 43 -18 557 793 ; -C -1 ; WX 600 ; N down ; B 167 -15 433 422 ; -C -1 ; WX 600 ; N Agrave ; B 10 0 590 793 ; -C -1 ; WX 600 ; N atilde ; B 60 -15 552 606 ; -C -1 ; WX 600 ; N up ; B 167 0 433 437 ; -C -1 ; WX 600 ; N eacute ; B 73 -15 541 672 ; -C -1 ; WX 600 ; N graybox ; B 76 0 525 599 ; -C -1 ; WX 600 ; N lira ; B 80 -21 518 611 ; -C -1 ; WX 600 ; N Icircumflex ; B 103 0 497 775 ; -C -1 ; WX 600 ; N Adieresis ; B 10 0 590 716 ; -C -1 ; WX 600 ; N yacute ; B -12 -157 552 672 ; -C -1 ; WX 600 ; N icircumflex ; B 94 0 498 654 ; -C -1 ; WX 600 ; N adieresis ; B 60 -15 552 580 ; -C -1 ; WX 600 ; N zcaron ; B 106 0 495 669 ; -C -1 ; WX 600 ; N Scaron ; B 79 -20 522 805 ; -C -1 ; WX 600 ; N minus ; B 87 195 513 232 ; -C -1 ; WX 600 ; N Aring ; B 10 0 590 753 ; -C -1 ; WX 600 ; N Ucircumflex ; B 24 -18 576 775 ; -C -1 ; WX 600 ; N plusminus ; B 87 0 513 514 ; -C -1 ; WX 600 ; N ograve ; B 62 -15 538 672 ; -C -1 ; WX 600 ; N Edieresis ; B 60 0 543 716 ; -C -1 ; WX 600 ; N brokenbar ; B 282 -80 319 629 ; -C -1 ; WX 600 ; N Idieresis ; B 103 0 497 716 ; -C -1 ; WX 600 ; N acircumflex ; B 60 -15 552 654 ; -C -1 ; WX 600 ; N ydieresis ; B -12 -157 552 580 ; -C -1 ; WX 600 ; N Oacute ; B 43 -18 557 793 ; -C -1 ; WX 600 ; N Egrave ; B 60 0 543 793 ; -C -1 ; WX 600 ; N center ; B 40 14 560 580 ; -C -1 ; WX 600 ; N threequarters ; B 22 -57 574 665 ; -C -1 ; WX 600 ; N tab ; B 19 0 581 562 ; -C -1 ; WX 600 ; N ecircumflex ; B 73 -15 541 654 ; -C -1 ; WX 600 ; N Eacute ; B 60 0 543 793 ; -C -1 ; WX 600 ; N trademark ; B 10 263 591 562 ; -C -1 ; WX 600 ; N square ; B 19 0 581 562 ; -C -1 ; WX 600 ; N onehalf ; B 0 -57 611 665 ; -C -1 ; WX 600 ; N onequarter ; B 6 -57 594 665 ; -C -1 ; WX 600 ; N Uacute ; B 24 -18 576 793 ; -C -1 ; WX 600 ; N Atilde ; B 10 0 590 732 ; -C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ; -C -1 ; WX 600 ; N Igrave ; B 103 0 497 793 ; -C -1 ; WX 600 ; N Iacute ; B 103 0 497 793 ; -C -1 ; WX 600 ; N Acircumflex ; B 10 0 590 775 ; -C -1 ; WX 600 ; N Udieresis ; B 24 -18 576 716 ; -C -1 ; WX 600 ; N Gcaron ; B 38 -18 568 805 ; -C -1 ; WX 600 ; N Aacute ; B 10 0 590 793 ; -C -1 ; WX 600 ; N LL ; B 15 0 585 562 ; -C -1 ; WX 600 ; N twosuperior ; B 184 249 417 622 ; -C -1 ; WX 600 ; N Scedilla ; B 79 -151 522 580 ; -C -1 ; WX 600 ; N arrowboth ; B -28 122 628 476 ; -C -1 ; WX 600 ; N udieresis ; B 28 -15 555 580 ; -C -1 ; WX 600 ; N odieresis ; B 62 -15 538 580 ; -C -1 ; WX 600 ; N aring ; B 60 -15 552 627 ; -C -1 ; WX 600 ; N ij ; B 44 -157 483 657 ; -C -1 ; WX 600 ; N arrowdown ; B 123 -15 477 608 ; -C -1 ; WX 600 ; N igrave ; B 102 0 498 672 ; -C -1 ; WX 600 ; N aacute ; B 60 -15 552 672 ; -C -1 ; WX 600 ; N stop ; B 19 0 581 562 ; -C -1 ; WX 600 ; N ocircumflex ; B 62 -15 538 654 ; -C -1 ; WX 600 ; N gcaron ; B 52 -157 559 669 ; -C -1 ; WX 600 ; N iacute ; B 102 0 498 672 ; -C -1 ; WX 600 ; N Ntilde ; B 14 -13 586 732 ; -C -1 ; WX 600 ; N idieresis ; B 102 0 498 580 ; -C -1 ; WX 600 ; N Ccedilla ; B 48 -151 533 580 ; -C -1 ; WX 600 ; N arrowright ; B -24 122 624 476 ; -C -1 ; WX 600 ; N ucircumflex ; B 28 -15 555 654 ; -C -1 ; WX 600 ; N Idot ; B 103 0 497 716 ; -C -1 ; WX 600 ; N agrave ; B 60 -15 552 672 ; -C -1 ; WX 600 ; N ntilde ; B 33 0 568 606 ; -C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ; -C -1 ; WX 600 ; N return ; B 19 0 581 562 ; -C -1 ; WX 600 ; N Zcaron ; B 86 0 514 805 ; -C -1 ; WX 600 ; N uacute ; B 28 -15 555 672 ; -C -1 ; WX 600 ; N overscore ; B 0 579 600 629 ; -C -1 ; WX 600 ; N egrave ; B 73 -15 541 672 ; -C -1 ; WX 600 ; N ugrave ; B 28 -15 555 672 ; -C -1 ; WX 600 ; N oacute ; B 62 -15 538 672 ; -C -1 ; WX 600 ; N arrowleft ; B -24 122 624 476 ; -C -1 ; WX 600 ; N arrowup ; B 123 0 477 623 ; -EndCharMetrics -StartComposites 62 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 20 121 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex -30 121 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis -30 136 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave -30 121 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring -15 126 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde 0 126 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 0 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 30 121 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 0 121 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 0 136 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 0 121 ; -CC Gcaron 2 ; PCC G 0 0 ; PCC caron 0 136 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute 0 121 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 0 121 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 0 136 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave 0 121 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 0 126 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 0 121 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 0 121 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 0 136 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 0 121 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 0 126 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 30 136 ; -CC Scedilla 2 ; PCC S 0 0 ; PCC cedilla 0 0 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 30 121 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 0 121 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 0 136 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave -30 121 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 30 121 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 0 136 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 0 136 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 0 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 0 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 0 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave 0 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 0 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 0 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 0 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 0 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 0 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 0 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 0 0 ; -CC gcaron 2 ; PCC g 0 0 ; PCC caron -30 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -30 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -30 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -30 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 0 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 0 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 0 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 0 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 0 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 0 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 0 0 ; -CC scedilla 2 ; PCC s 0 0 ; PCC cedilla 0 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute -10 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex -10 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 0 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave -30 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute -20 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis -10 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 10 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Helvetica-Bold.afm b/config/psfonts/Helvetica-Bold.afm deleted file mode 100644 index a1e1b33c..00000000 --- a/config/psfonts/Helvetica-Bold.afm +++ /dev/null @@ -1,570 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved. -Comment Creation Date: Thu Mar 15 09:43:00 1990 -Comment UniqueID 28357 -Comment VMusage 26878 33770 -FontName Helvetica-Bold -FullName Helvetica Bold -FamilyName Helvetica -Weight Bold -ItalicAngle 0 -IsFixedPitch false -FontBBox -170 -228 1003 962 -UnderlinePosition -100 -UnderlineThickness 50 -Version 001.007 -Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries. -EncodingScheme AdobeStandardEncoding -CapHeight 718 -XHeight 532 -Ascender 718 -Descender -207 -StartCharMetrics 228 -C 32 ; WX 278 ; N space ; B 0 0 0 0 ; -C 33 ; WX 333 ; N exclam ; B 90 0 244 718 ; -C 34 ; WX 474 ; N quotedbl ; B 98 447 376 718 ; -C 35 ; WX 556 ; N numbersign ; B 18 0 538 698 ; -C 36 ; WX 556 ; N dollar ; B 30 -115 523 775 ; -C 37 ; WX 889 ; N percent ; B 28 -19 861 710 ; -C 38 ; WX 722 ; N ampersand ; B 54 -19 701 718 ; -C 39 ; WX 278 ; N quoteright ; B 69 445 209 718 ; -C 40 ; WX 333 ; N parenleft ; B 35 -208 314 734 ; -C 41 ; WX 333 ; N parenright ; B 19 -208 298 734 ; -C 42 ; WX 389 ; N asterisk ; B 27 387 362 718 ; -C 43 ; WX 584 ; N plus ; B 40 0 544 506 ; -C 44 ; WX 278 ; N comma ; B 64 -168 214 146 ; -C 45 ; WX 333 ; N hyphen ; B 27 215 306 345 ; -C 46 ; WX 278 ; N period ; B 64 0 214 146 ; -C 47 ; WX 278 ; N slash ; B -33 -19 311 737 ; -C 48 ; WX 556 ; N zero ; B 32 -19 524 710 ; -C 49 ; WX 556 ; N one ; B 69 0 378 710 ; -C 50 ; WX 556 ; N two ; B 26 0 511 710 ; -C 51 ; WX 556 ; N three ; B 27 -19 516 710 ; -C 52 ; WX 556 ; N four ; B 27 0 526 710 ; -C 53 ; WX 556 ; N five ; B 27 -19 516 698 ; -C 54 ; WX 556 ; N six ; B 31 -19 520 710 ; -C 55 ; WX 556 ; N seven ; B 25 0 528 698 ; -C 56 ; WX 556 ; N eight ; B 32 -19 524 710 ; -C 57 ; WX 556 ; N nine ; B 30 -19 522 710 ; -C 58 ; WX 333 ; N colon ; B 92 0 242 512 ; -C 59 ; WX 333 ; N semicolon ; B 92 -168 242 512 ; -C 60 ; WX 584 ; N less ; B 38 -8 546 514 ; -C 61 ; WX 584 ; N equal ; B 40 87 544 419 ; -C 62 ; WX 584 ; N greater ; B 38 -8 546 514 ; -C 63 ; WX 611 ; N question ; B 60 0 556 727 ; -C 64 ; WX 975 ; N at ; B 118 -19 856 737 ; -C 65 ; WX 722 ; N A ; B 20 0 702 718 ; -C 66 ; WX 722 ; N B ; B 76 0 669 718 ; -C 67 ; WX 722 ; N C ; B 44 -19 684 737 ; -C 68 ; WX 722 ; N D ; B 76 0 685 718 ; -C 69 ; WX 667 ; N E ; B 76 0 621 718 ; -C 70 ; WX 611 ; N F ; B 76 0 587 718 ; -C 71 ; WX 778 ; N G ; B 44 -19 713 737 ; -C 72 ; WX 722 ; N H ; B 71 0 651 718 ; -C 73 ; WX 278 ; N I ; B 64 0 214 718 ; -C 74 ; WX 556 ; N J ; B 22 -18 484 718 ; -C 75 ; WX 722 ; N K ; B 87 0 722 718 ; -C 76 ; WX 611 ; N L ; B 76 0 583 718 ; -C 77 ; WX 833 ; N M ; B 69 0 765 718 ; -C 78 ; WX 722 ; N N ; B 69 0 654 718 ; -C 79 ; WX 778 ; N O ; B 44 -19 734 737 ; -C 80 ; WX 667 ; N P ; B 76 0 627 718 ; -C 81 ; WX 778 ; N Q ; B 44 -52 737 737 ; -C 82 ; WX 722 ; N R ; B 76 0 677 718 ; -C 83 ; WX 667 ; N S ; B 39 -19 629 737 ; -C 84 ; WX 611 ; N T ; B 14 0 598 718 ; -C 85 ; WX 722 ; N U ; B 72 -19 651 718 ; -C 86 ; WX 667 ; N V ; B 19 0 648 718 ; -C 87 ; WX 944 ; N W ; B 16 0 929 718 ; -C 88 ; WX 667 ; N X ; B 14 0 653 718 ; -C 89 ; WX 667 ; N Y ; B 15 0 653 718 ; -C 90 ; WX 611 ; N Z ; B 25 0 586 718 ; -C 91 ; WX 333 ; N bracketleft ; B 63 -196 309 722 ; -C 92 ; WX 278 ; N backslash ; B -33 -19 311 737 ; -C 93 ; WX 333 ; N bracketright ; B 24 -196 270 722 ; -C 94 ; WX 584 ; N asciicircum ; B 62 323 522 698 ; -C 95 ; WX 556 ; N underscore ; B 0 -125 556 -75 ; -C 96 ; WX 278 ; N quoteleft ; B 69 454 209 727 ; -C 97 ; WX 556 ; N a ; B 29 -14 527 546 ; -C 98 ; WX 611 ; N b ; B 61 -14 578 718 ; -C 99 ; WX 556 ; N c ; B 34 -14 524 546 ; -C 100 ; WX 611 ; N d ; B 34 -14 551 718 ; -C 101 ; WX 556 ; N e ; B 23 -14 528 546 ; -C 102 ; WX 333 ; N f ; B 10 0 318 727 ; L i fi ; L l fl ; -C 103 ; WX 611 ; N g ; B 40 -217 553 546 ; -C 104 ; WX 611 ; N h ; B 65 0 546 718 ; -C 105 ; WX 278 ; N i ; B 69 0 209 725 ; -C 106 ; WX 278 ; N j ; B 3 -214 209 725 ; -C 107 ; WX 556 ; N k ; B 69 0 562 718 ; -C 108 ; WX 278 ; N l ; B 69 0 209 718 ; -C 109 ; WX 889 ; N m ; B 64 0 826 546 ; -C 110 ; WX 611 ; N n ; B 65 0 546 546 ; -C 111 ; WX 611 ; N o ; B 34 -14 578 546 ; -C 112 ; WX 611 ; N p ; B 62 -207 578 546 ; -C 113 ; WX 611 ; N q ; B 34 -207 552 546 ; -C 114 ; WX 389 ; N r ; B 64 0 373 546 ; -C 115 ; WX 556 ; N s ; B 30 -14 519 546 ; -C 116 ; WX 333 ; N t ; B 10 -6 309 676 ; -C 117 ; WX 611 ; N u ; B 66 -14 545 532 ; -C 118 ; WX 556 ; N v ; B 13 0 543 532 ; -C 119 ; WX 778 ; N w ; B 10 0 769 532 ; -C 120 ; WX 556 ; N x ; B 15 0 541 532 ; -C 121 ; WX 556 ; N y ; B 10 -214 539 532 ; -C 122 ; WX 500 ; N z ; B 20 0 480 532 ; -C 123 ; WX 389 ; N braceleft ; B 48 -196 365 722 ; -C 124 ; WX 280 ; N bar ; B 84 -19 196 737 ; -C 125 ; WX 389 ; N braceright ; B 24 -196 341 722 ; -C 126 ; WX 584 ; N asciitilde ; B 61 163 523 343 ; -C 161 ; WX 333 ; N exclamdown ; B 90 -186 244 532 ; -C 162 ; WX 556 ; N cent ; B 34 -118 524 628 ; -C 163 ; WX 556 ; N sterling ; B 28 -16 541 718 ; -C 164 ; WX 167 ; N fraction ; B -170 -19 336 710 ; -C 165 ; WX 556 ; N yen ; B -9 0 565 698 ; -C 166 ; WX 556 ; N florin ; B -10 -210 516 737 ; -C 167 ; WX 556 ; N section ; B 34 -184 522 727 ; -C 168 ; WX 556 ; N currency ; B -3 76 559 636 ; -C 169 ; WX 238 ; N quotesingle ; B 70 447 168 718 ; -C 170 ; WX 500 ; N quotedblleft ; B 64 454 436 727 ; -C 171 ; WX 556 ; N guillemotleft ; B 88 76 468 484 ; -C 172 ; WX 333 ; N guilsinglleft ; B 83 76 250 484 ; -C 173 ; WX 333 ; N guilsinglright ; B 83 76 250 484 ; -C 174 ; WX 611 ; N fi ; B 10 0 542 727 ; -C 175 ; WX 611 ; N fl ; B 10 0 542 727 ; -C 177 ; WX 556 ; N endash ; B 0 227 556 333 ; -C 178 ; WX 556 ; N dagger ; B 36 -171 520 718 ; -C 179 ; WX 556 ; N daggerdbl ; B 36 -171 520 718 ; -C 180 ; WX 278 ; N periodcentered ; B 58 172 220 334 ; -C 182 ; WX 556 ; N paragraph ; B -8 -191 539 700 ; -C 183 ; WX 350 ; N bullet ; B 10 194 340 524 ; -C 184 ; WX 278 ; N quotesinglbase ; B 69 -146 209 127 ; -C 185 ; WX 500 ; N quotedblbase ; B 64 -146 436 127 ; -C 186 ; WX 500 ; N quotedblright ; B 64 445 436 718 ; -C 187 ; WX 556 ; N guillemotright ; B 88 76 468 484 ; -C 188 ; WX 1000 ; N ellipsis ; B 92 0 908 146 ; -C 189 ; WX 1000 ; N perthousand ; B -3 -19 1003 710 ; -C 191 ; WX 611 ; N questiondown ; B 55 -195 551 532 ; -C 193 ; WX 333 ; N grave ; B -23 604 225 750 ; -C 194 ; WX 333 ; N acute ; B 108 604 356 750 ; -C 195 ; WX 333 ; N circumflex ; B -10 604 343 750 ; -C 196 ; WX 333 ; N tilde ; B -17 610 350 737 ; -C 197 ; WX 333 ; N macron ; B -6 604 339 678 ; -C 198 ; WX 333 ; N breve ; B -2 604 335 750 ; -C 199 ; WX 333 ; N dotaccent ; B 104 614 230 729 ; -C 200 ; WX 333 ; N dieresis ; B 6 614 327 729 ; -C 202 ; WX 333 ; N ring ; B 59 568 275 776 ; -C 203 ; WX 333 ; N cedilla ; B 6 -228 245 0 ; -C 205 ; WX 333 ; N hungarumlaut ; B 9 604 486 750 ; -C 206 ; WX 333 ; N ogonek ; B 71 -228 304 0 ; -C 207 ; WX 333 ; N caron ; B -10 604 343 750 ; -C 208 ; WX 1000 ; N emdash ; B 0 227 1000 333 ; -C 225 ; WX 1000 ; N AE ; B 5 0 954 718 ; -C 227 ; WX 370 ; N ordfeminine ; B 22 276 347 737 ; -C 232 ; WX 611 ; N Lslash ; B -20 0 583 718 ; -C 233 ; WX 778 ; N Oslash ; B 33 -27 744 745 ; -C 234 ; WX 1000 ; N OE ; B 37 -19 961 737 ; -C 235 ; WX 365 ; N ordmasculine ; B 6 276 360 737 ; -C 241 ; WX 889 ; N ae ; B 29 -14 858 546 ; -C 245 ; WX 278 ; N dotlessi ; B 69 0 209 532 ; -C 248 ; WX 278 ; N lslash ; B -18 0 296 718 ; -C 249 ; WX 611 ; N oslash ; B 22 -29 589 560 ; -C 250 ; WX 944 ; N oe ; B 34 -14 912 546 ; -C 251 ; WX 611 ; N germandbls ; B 69 -14 579 731 ; -C -1 ; WX 611 ; N Zcaron ; B 25 0 586 936 ; -C -1 ; WX 556 ; N ccedilla ; B 34 -228 524 546 ; -C -1 ; WX 556 ; N ydieresis ; B 10 -214 539 729 ; -C -1 ; WX 556 ; N atilde ; B 29 -14 527 737 ; -C -1 ; WX 278 ; N icircumflex ; B -37 0 316 750 ; -C -1 ; WX 333 ; N threesuperior ; B 8 271 326 710 ; -C -1 ; WX 556 ; N ecircumflex ; B 23 -14 528 750 ; -C -1 ; WX 611 ; N thorn ; B 62 -208 578 718 ; -C -1 ; WX 556 ; N egrave ; B 23 -14 528 750 ; -C -1 ; WX 333 ; N twosuperior ; B 9 283 324 710 ; -C -1 ; WX 556 ; N eacute ; B 23 -14 528 750 ; -C -1 ; WX 611 ; N otilde ; B 34 -14 578 737 ; -C -1 ; WX 722 ; N Aacute ; B 20 0 702 936 ; -C -1 ; WX 611 ; N ocircumflex ; B 34 -14 578 750 ; -C -1 ; WX 556 ; N yacute ; B 10 -214 539 750 ; -C -1 ; WX 611 ; N udieresis ; B 66 -14 545 729 ; -C -1 ; WX 834 ; N threequarters ; B 16 -19 799 710 ; -C -1 ; WX 556 ; N acircumflex ; B 29 -14 527 750 ; -C -1 ; WX 722 ; N Eth ; B -5 0 685 718 ; -C -1 ; WX 556 ; N edieresis ; B 23 -14 528 729 ; -C -1 ; WX 611 ; N ugrave ; B 66 -14 545 750 ; -C -1 ; WX 1000 ; N trademark ; B 44 306 956 718 ; -C -1 ; WX 611 ; N ograve ; B 34 -14 578 750 ; -C -1 ; WX 556 ; N scaron ; B 30 -14 519 750 ; -C -1 ; WX 278 ; N Idieresis ; B -21 0 300 915 ; -C -1 ; WX 611 ; N uacute ; B 66 -14 545 750 ; -C -1 ; WX 556 ; N agrave ; B 29 -14 527 750 ; -C -1 ; WX 611 ; N ntilde ; B 65 0 546 737 ; -C -1 ; WX 556 ; N aring ; B 29 -14 527 776 ; -C -1 ; WX 500 ; N zcaron ; B 20 0 480 750 ; -C -1 ; WX 278 ; N Icircumflex ; B -37 0 316 936 ; -C -1 ; WX 722 ; N Ntilde ; B 69 0 654 923 ; -C -1 ; WX 611 ; N ucircumflex ; B 66 -14 545 750 ; -C -1 ; WX 667 ; N Ecircumflex ; B 76 0 621 936 ; -C -1 ; WX 278 ; N Iacute ; B 64 0 329 936 ; -C -1 ; WX 722 ; N Ccedilla ; B 44 -228 684 737 ; -C -1 ; WX 778 ; N Odieresis ; B 44 -19 734 915 ; -C -1 ; WX 667 ; N Scaron ; B 39 -19 629 936 ; -C -1 ; WX 667 ; N Edieresis ; B 76 0 621 915 ; -C -1 ; WX 278 ; N Igrave ; B -50 0 214 936 ; -C -1 ; WX 556 ; N adieresis ; B 29 -14 527 729 ; -C -1 ; WX 778 ; N Ograve ; B 44 -19 734 936 ; -C -1 ; WX 667 ; N Egrave ; B 76 0 621 936 ; -C -1 ; WX 667 ; N Ydieresis ; B 15 0 653 915 ; -C -1 ; WX 737 ; N registered ; B -11 -19 748 737 ; -C -1 ; WX 778 ; N Otilde ; B 44 -19 734 923 ; -C -1 ; WX 834 ; N onequarter ; B 26 -19 766 710 ; -C -1 ; WX 722 ; N Ugrave ; B 72 -19 651 936 ; -C -1 ; WX 722 ; N Ucircumflex ; B 72 -19 651 936 ; -C -1 ; WX 667 ; N Thorn ; B 76 0 627 718 ; -C -1 ; WX 584 ; N divide ; B 40 -42 544 548 ; -C -1 ; WX 722 ; N Atilde ; B 20 0 702 923 ; -C -1 ; WX 722 ; N Uacute ; B 72 -19 651 936 ; -C -1 ; WX 778 ; N Ocircumflex ; B 44 -19 734 936 ; -C -1 ; WX 584 ; N logicalnot ; B 40 108 544 419 ; -C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ; -C -1 ; WX 278 ; N idieresis ; B -21 0 300 729 ; -C -1 ; WX 278 ; N iacute ; B 69 0 329 750 ; -C -1 ; WX 556 ; N aacute ; B 29 -14 527 750 ; -C -1 ; WX 584 ; N plusminus ; B 40 0 544 506 ; -C -1 ; WX 584 ; N multiply ; B 40 1 545 505 ; -C -1 ; WX 722 ; N Udieresis ; B 72 -19 651 915 ; -C -1 ; WX 584 ; N minus ; B 40 197 544 309 ; -C -1 ; WX 333 ; N onesuperior ; B 26 283 237 710 ; -C -1 ; WX 667 ; N Eacute ; B 76 0 621 936 ; -C -1 ; WX 722 ; N Acircumflex ; B 20 0 702 936 ; -C -1 ; WX 737 ; N copyright ; B -11 -19 749 737 ; -C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ; -C -1 ; WX 611 ; N odieresis ; B 34 -14 578 729 ; -C -1 ; WX 611 ; N oacute ; B 34 -14 578 750 ; -C -1 ; WX 400 ; N degree ; B 57 426 343 712 ; -C -1 ; WX 278 ; N igrave ; B -50 0 209 750 ; -C -1 ; WX 611 ; N mu ; B 66 -207 545 532 ; -C -1 ; WX 778 ; N Oacute ; B 44 -19 734 936 ; -C -1 ; WX 611 ; N eth ; B 34 -14 578 737 ; -C -1 ; WX 722 ; N Adieresis ; B 20 0 702 915 ; -C -1 ; WX 667 ; N Yacute ; B 15 0 653 936 ; -C -1 ; WX 280 ; N brokenbar ; B 84 -19 196 737 ; -C -1 ; WX 834 ; N onehalf ; B 26 -19 794 710 ; -EndCharMetrics -StartKernData -StartKernPairs 209 - -KPX A y -30 -KPX A w -30 -KPX A v -40 -KPX A u -30 -KPX A Y -110 -KPX A W -60 -KPX A V -80 -KPX A U -50 -KPX A T -90 -KPX A Q -40 -KPX A O -40 -KPX A G -50 -KPX A C -40 - -KPX B U -10 -KPX B A -30 - -KPX D period -30 -KPX D comma -30 -KPX D Y -70 -KPX D W -40 -KPX D V -40 -KPX D A -40 - -KPX F period -100 -KPX F comma -100 -KPX F a -20 -KPX F A -80 - -KPX J u -20 -KPX J period -20 -KPX J comma -20 -KPX J A -20 - -KPX K y -40 -KPX K u -30 -KPX K o -35 -KPX K e -15 -KPX K O -30 - -KPX L y -30 -KPX L quoteright -140 -KPX L quotedblright -140 -KPX L Y -120 -KPX L W -80 -KPX L V -110 -KPX L T -90 - -KPX O period -40 -KPX O comma -40 -KPX O Y -70 -KPX O X -50 -KPX O W -50 -KPX O V -50 -KPX O T -40 -KPX O A -50 - -KPX P period -120 -KPX P o -40 -KPX P e -30 -KPX P comma -120 -KPX P a -30 -KPX P A -100 - -KPX Q period 20 -KPX Q comma 20 -KPX Q U -10 - -KPX R Y -50 -KPX R W -40 -KPX R V -50 -KPX R U -20 -KPX R T -20 -KPX R O -20 - -KPX T y -60 -KPX T w -60 -KPX T u -90 -KPX T semicolon -40 -KPX T r -80 -KPX T period -80 -KPX T o -80 -KPX T hyphen -120 -KPX T e -60 -KPX T comma -80 -KPX T colon -40 -KPX T a -80 -KPX T O -40 -KPX T A -90 - -KPX U period -30 -KPX U comma -30 -KPX U A -50 - -KPX V u -60 -KPX V semicolon -40 -KPX V period -120 -KPX V o -90 -KPX V hyphen -80 -KPX V e -50 -KPX V comma -120 -KPX V colon -40 -KPX V a -60 -KPX V O -50 -KPX V G -50 -KPX V A -80 - -KPX W y -20 -KPX W u -45 -KPX W semicolon -10 -KPX W period -80 -KPX W o -60 -KPX W hyphen -40 -KPX W e -35 -KPX W comma -80 -KPX W colon -10 -KPX W a -40 -KPX W O -20 -KPX W A -60 - -KPX Y u -100 -KPX Y semicolon -50 -KPX Y period -100 -KPX Y o -100 -KPX Y e -80 -KPX Y comma -100 -KPX Y colon -50 -KPX Y a -90 -KPX Y O -70 -KPX Y A -110 - -KPX a y -20 -KPX a w -15 -KPX a v -15 -KPX a g -10 - -KPX b y -20 -KPX b v -20 -KPX b u -20 -KPX b l -10 - -KPX c y -10 -KPX c l -20 -KPX c k -20 -KPX c h -10 - -KPX colon space -40 - -KPX comma space -40 -KPX comma quoteright -120 -KPX comma quotedblright -120 - -KPX d y -15 -KPX d w -15 -KPX d v -15 -KPX d d -10 - -KPX e y -15 -KPX e x -15 -KPX e w -15 -KPX e v -15 -KPX e period 20 -KPX e comma 10 - -KPX f quoteright 30 -KPX f quotedblright 30 -KPX f period -10 -KPX f o -20 -KPX f e -10 -KPX f comma -10 - -KPX g g -10 -KPX g e 10 - -KPX h y -20 - -KPX k o -15 - -KPX l y -15 -KPX l w -15 - -KPX m y -30 -KPX m u -20 - -KPX n y -20 -KPX n v -40 -KPX n u -10 - -KPX o y -20 -KPX o x -30 -KPX o w -15 -KPX o v -20 - -KPX p y -15 - -KPX period space -40 -KPX period quoteright -120 -KPX period quotedblright -120 - -KPX quotedblright space -80 - -KPX quoteleft quoteleft -46 - -KPX quoteright v -20 -KPX quoteright space -80 -KPX quoteright s -60 -KPX quoteright r -40 -KPX quoteright quoteright -46 -KPX quoteright l -20 -KPX quoteright d -80 - -KPX r y 10 -KPX r v 10 -KPX r t 20 -KPX r s -15 -KPX r q -20 -KPX r period -60 -KPX r o -20 -KPX r hyphen -20 -KPX r g -15 -KPX r d -20 -KPX r comma -60 -KPX r c -20 - -KPX s w -15 - -KPX semicolon space -40 - -KPX space quoteleft -60 -KPX space quotedblleft -80 -KPX space Y -120 -KPX space W -80 -KPX space V -80 -KPX space T -100 - -KPX v period -80 -KPX v o -30 -KPX v comma -80 -KPX v a -20 - -KPX w period -40 -KPX w o -20 -KPX w comma -40 - -KPX x e -10 - -KPX y period -80 -KPX y o -25 -KPX y e -10 -KPX y comma -80 -KPX y a -30 - -KPX z e 10 -EndKernPairs -EndKernData -StartComposites 58 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 195 186 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 195 186 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 195 186 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave 195 186 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring 195 186 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde 195 186 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 215 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 167 186 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 167 186 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 167 186 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 167 186 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute -27 186 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -27 186 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -27 186 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave -27 186 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 195 186 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 223 186 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 223 186 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 223 186 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 223 186 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 223 186 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 167 186 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 195 186 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 195 186 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 195 186 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave 195 186 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 167 186 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 167 186 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 139 186 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 112 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 112 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 112 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave 112 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 112 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 112 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 132 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 112 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 112 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 112 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 112 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 139 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 139 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 139 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 139 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 139 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 139 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 112 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute 139 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 139 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 139 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave 139 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute 112 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 112 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 84 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Helvetica-BoldOblique.afm b/config/psfonts/Helvetica-BoldOblique.afm deleted file mode 100644 index b6cff415..00000000 --- a/config/psfonts/Helvetica-BoldOblique.afm +++ /dev/null @@ -1,570 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved. -Comment Creation Date: Thu Mar 15 10:44:33 1990 -Comment UniqueID 28371 -Comment VMusage 7614 43068 -FontName Helvetica-BoldOblique -FullName Helvetica Bold Oblique -FamilyName Helvetica -Weight Bold -ItalicAngle -12 -IsFixedPitch false -FontBBox -174 -228 1114 962 -UnderlinePosition -100 -UnderlineThickness 50 -Version 001.007 -Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries. -EncodingScheme AdobeStandardEncoding -CapHeight 718 -XHeight 532 -Ascender 718 -Descender -207 -StartCharMetrics 228 -C 32 ; WX 278 ; N space ; B 0 0 0 0 ; -C 33 ; WX 333 ; N exclam ; B 94 0 397 718 ; -C 34 ; WX 474 ; N quotedbl ; B 193 447 529 718 ; -C 35 ; WX 556 ; N numbersign ; B 60 0 644 698 ; -C 36 ; WX 556 ; N dollar ; B 67 -115 622 775 ; -C 37 ; WX 889 ; N percent ; B 136 -19 901 710 ; -C 38 ; WX 722 ; N ampersand ; B 89 -19 732 718 ; -C 39 ; WX 278 ; N quoteright ; B 167 445 362 718 ; -C 40 ; WX 333 ; N parenleft ; B 76 -208 470 734 ; -C 41 ; WX 333 ; N parenright ; B -25 -208 369 734 ; -C 42 ; WX 389 ; N asterisk ; B 146 387 481 718 ; -C 43 ; WX 584 ; N plus ; B 82 0 610 506 ; -C 44 ; WX 278 ; N comma ; B 28 -168 245 146 ; -C 45 ; WX 333 ; N hyphen ; B 73 215 379 345 ; -C 46 ; WX 278 ; N period ; B 64 0 245 146 ; -C 47 ; WX 278 ; N slash ; B -37 -19 468 737 ; -C 48 ; WX 556 ; N zero ; B 86 -19 617 710 ; -C 49 ; WX 556 ; N one ; B 173 0 529 710 ; -C 50 ; WX 556 ; N two ; B 26 0 619 710 ; -C 51 ; WX 556 ; N three ; B 65 -19 608 710 ; -C 52 ; WX 556 ; N four ; B 60 0 598 710 ; -C 53 ; WX 556 ; N five ; B 64 -19 636 698 ; -C 54 ; WX 556 ; N six ; B 85 -19 619 710 ; -C 55 ; WX 556 ; N seven ; B 125 0 676 698 ; -C 56 ; WX 556 ; N eight ; B 69 -19 616 710 ; -C 57 ; WX 556 ; N nine ; B 78 -19 615 710 ; -C 58 ; WX 333 ; N colon ; B 92 0 351 512 ; -C 59 ; WX 333 ; N semicolon ; B 56 -168 351 512 ; -C 60 ; WX 584 ; N less ; B 82 -8 655 514 ; -C 61 ; WX 584 ; N equal ; B 58 87 633 419 ; -C 62 ; WX 584 ; N greater ; B 36 -8 609 514 ; -C 63 ; WX 611 ; N question ; B 165 0 671 727 ; -C 64 ; WX 975 ; N at ; B 186 -19 954 737 ; -C 65 ; WX 722 ; N A ; B 20 0 702 718 ; -C 66 ; WX 722 ; N B ; B 76 0 764 718 ; -C 67 ; WX 722 ; N C ; B 107 -19 789 737 ; -C 68 ; WX 722 ; N D ; B 76 0 777 718 ; -C 69 ; WX 667 ; N E ; B 76 0 757 718 ; -C 70 ; WX 611 ; N F ; B 76 0 740 718 ; -C 71 ; WX 778 ; N G ; B 108 -19 817 737 ; -C 72 ; WX 722 ; N H ; B 71 0 804 718 ; -C 73 ; WX 278 ; N I ; B 64 0 367 718 ; -C 74 ; WX 556 ; N J ; B 60 -18 637 718 ; -C 75 ; WX 722 ; N K ; B 87 0 858 718 ; -C 76 ; WX 611 ; N L ; B 76 0 611 718 ; -C 77 ; WX 833 ; N M ; B 69 0 918 718 ; -C 78 ; WX 722 ; N N ; B 69 0 807 718 ; -C 79 ; WX 778 ; N O ; B 107 -19 823 737 ; -C 80 ; WX 667 ; N P ; B 76 0 738 718 ; -C 81 ; WX 778 ; N Q ; B 107 -52 823 737 ; -C 82 ; WX 722 ; N R ; B 76 0 778 718 ; -C 83 ; WX 667 ; N S ; B 81 -19 718 737 ; -C 84 ; WX 611 ; N T ; B 140 0 751 718 ; -C 85 ; WX 722 ; N U ; B 116 -19 804 718 ; -C 86 ; WX 667 ; N V ; B 172 0 801 718 ; -C 87 ; WX 944 ; N W ; B 169 0 1082 718 ; -C 88 ; WX 667 ; N X ; B 14 0 791 718 ; -C 89 ; WX 667 ; N Y ; B 168 0 806 718 ; -C 90 ; WX 611 ; N Z ; B 25 0 737 718 ; -C 91 ; WX 333 ; N bracketleft ; B 21 -196 462 722 ; -C 92 ; WX 278 ; N backslash ; B 124 -19 307 737 ; -C 93 ; WX 333 ; N bracketright ; B -18 -196 423 722 ; -C 94 ; WX 584 ; N asciicircum ; B 131 323 591 698 ; -C 95 ; WX 556 ; N underscore ; B -27 -125 540 -75 ; -C 96 ; WX 278 ; N quoteleft ; B 165 454 361 727 ; -C 97 ; WX 556 ; N a ; B 55 -14 583 546 ; -C 98 ; WX 611 ; N b ; B 61 -14 645 718 ; -C 99 ; WX 556 ; N c ; B 79 -14 599 546 ; -C 100 ; WX 611 ; N d ; B 82 -14 704 718 ; -C 101 ; WX 556 ; N e ; B 70 -14 593 546 ; -C 102 ; WX 333 ; N f ; B 87 0 469 727 ; L i fi ; L l fl ; -C 103 ; WX 611 ; N g ; B 38 -217 666 546 ; -C 104 ; WX 611 ; N h ; B 65 0 629 718 ; -C 105 ; WX 278 ; N i ; B 69 0 363 725 ; -C 106 ; WX 278 ; N j ; B -42 -214 363 725 ; -C 107 ; WX 556 ; N k ; B 69 0 670 718 ; -C 108 ; WX 278 ; N l ; B 69 0 362 718 ; -C 109 ; WX 889 ; N m ; B 64 0 909 546 ; -C 110 ; WX 611 ; N n ; B 65 0 629 546 ; -C 111 ; WX 611 ; N o ; B 82 -14 643 546 ; -C 112 ; WX 611 ; N p ; B 18 -207 645 546 ; -C 113 ; WX 611 ; N q ; B 80 -207 665 546 ; -C 114 ; WX 389 ; N r ; B 64 0 489 546 ; -C 115 ; WX 556 ; N s ; B 63 -14 584 546 ; -C 116 ; WX 333 ; N t ; B 100 -6 422 676 ; -C 117 ; WX 611 ; N u ; B 98 -14 658 532 ; -C 118 ; WX 556 ; N v ; B 126 0 656 532 ; -C 119 ; WX 778 ; N w ; B 123 0 882 532 ; -C 120 ; WX 556 ; N x ; B 15 0 648 532 ; -C 121 ; WX 556 ; N y ; B 42 -214 652 532 ; -C 122 ; WX 500 ; N z ; B 20 0 583 532 ; -C 123 ; WX 389 ; N braceleft ; B 94 -196 518 722 ; -C 124 ; WX 280 ; N bar ; B 80 -19 353 737 ; -C 125 ; WX 389 ; N braceright ; B -18 -196 407 722 ; -C 126 ; WX 584 ; N asciitilde ; B 115 163 577 343 ; -C 161 ; WX 333 ; N exclamdown ; B 50 -186 353 532 ; -C 162 ; WX 556 ; N cent ; B 79 -118 599 628 ; -C 163 ; WX 556 ; N sterling ; B 50 -16 635 718 ; -C 164 ; WX 167 ; N fraction ; B -174 -19 487 710 ; -C 165 ; WX 556 ; N yen ; B 60 0 713 698 ; -C 166 ; WX 556 ; N florin ; B -50 -210 669 737 ; -C 167 ; WX 556 ; N section ; B 61 -184 598 727 ; -C 168 ; WX 556 ; N currency ; B 27 76 680 636 ; -C 169 ; WX 238 ; N quotesingle ; B 165 447 321 718 ; -C 170 ; WX 500 ; N quotedblleft ; B 160 454 588 727 ; -C 171 ; WX 556 ; N guillemotleft ; B 135 76 571 484 ; -C 172 ; WX 333 ; N guilsinglleft ; B 130 76 353 484 ; -C 173 ; WX 333 ; N guilsinglright ; B 99 76 322 484 ; -C 174 ; WX 611 ; N fi ; B 87 0 696 727 ; -C 175 ; WX 611 ; N fl ; B 87 0 695 727 ; -C 177 ; WX 556 ; N endash ; B 48 227 627 333 ; -C 178 ; WX 556 ; N dagger ; B 118 -171 626 718 ; -C 179 ; WX 556 ; N daggerdbl ; B 46 -171 628 718 ; -C 180 ; WX 278 ; N periodcentered ; B 110 172 276 334 ; -C 182 ; WX 556 ; N paragraph ; B 98 -191 688 700 ; -C 183 ; WX 350 ; N bullet ; B 83 194 420 524 ; -C 184 ; WX 278 ; N quotesinglbase ; B 41 -146 236 127 ; -C 185 ; WX 500 ; N quotedblbase ; B 36 -146 463 127 ; -C 186 ; WX 500 ; N quotedblright ; B 162 445 589 718 ; -C 187 ; WX 556 ; N guillemotright ; B 104 76 540 484 ; -C 188 ; WX 1000 ; N ellipsis ; B 92 0 939 146 ; -C 189 ; WX 1000 ; N perthousand ; B 76 -19 1038 710 ; -C 191 ; WX 611 ; N questiondown ; B 53 -195 559 532 ; -C 193 ; WX 333 ; N grave ; B 136 604 353 750 ; -C 194 ; WX 333 ; N acute ; B 236 604 515 750 ; -C 195 ; WX 333 ; N circumflex ; B 118 604 471 750 ; -C 196 ; WX 333 ; N tilde ; B 113 610 507 737 ; -C 197 ; WX 333 ; N macron ; B 122 604 483 678 ; -C 198 ; WX 333 ; N breve ; B 156 604 494 750 ; -C 199 ; WX 333 ; N dotaccent ; B 235 614 385 729 ; -C 200 ; WX 333 ; N dieresis ; B 137 614 482 729 ; -C 202 ; WX 333 ; N ring ; B 200 568 420 776 ; -C 203 ; WX 333 ; N cedilla ; B -37 -228 220 0 ; -C 205 ; WX 333 ; N hungarumlaut ; B 137 604 645 750 ; -C 206 ; WX 333 ; N ogonek ; B 41 -228 264 0 ; -C 207 ; WX 333 ; N caron ; B 149 604 502 750 ; -C 208 ; WX 1000 ; N emdash ; B 48 227 1071 333 ; -C 225 ; WX 1000 ; N AE ; B 5 0 1100 718 ; -C 227 ; WX 370 ; N ordfeminine ; B 92 276 465 737 ; -C 232 ; WX 611 ; N Lslash ; B 34 0 611 718 ; -C 233 ; WX 778 ; N Oslash ; B 35 -27 894 745 ; -C 234 ; WX 1000 ; N OE ; B 99 -19 1114 737 ; -C 235 ; WX 365 ; N ordmasculine ; B 92 276 485 737 ; -C 241 ; WX 889 ; N ae ; B 56 -14 923 546 ; -C 245 ; WX 278 ; N dotlessi ; B 69 0 322 532 ; -C 248 ; WX 278 ; N lslash ; B 40 0 407 718 ; -C 249 ; WX 611 ; N oslash ; B 22 -29 701 560 ; -C 250 ; WX 944 ; N oe ; B 82 -14 977 546 ; -C 251 ; WX 611 ; N germandbls ; B 69 -14 657 731 ; -C -1 ; WX 611 ; N Zcaron ; B 25 0 737 936 ; -C -1 ; WX 556 ; N ccedilla ; B 79 -228 599 546 ; -C -1 ; WX 556 ; N ydieresis ; B 42 -214 652 729 ; -C -1 ; WX 556 ; N atilde ; B 55 -14 619 737 ; -C -1 ; WX 278 ; N icircumflex ; B 69 0 444 750 ; -C -1 ; WX 333 ; N threesuperior ; B 91 271 441 710 ; -C -1 ; WX 556 ; N ecircumflex ; B 70 -14 593 750 ; -C -1 ; WX 611 ; N thorn ; B 18 -208 645 718 ; -C -1 ; WX 556 ; N egrave ; B 70 -14 593 750 ; -C -1 ; WX 333 ; N twosuperior ; B 69 283 449 710 ; -C -1 ; WX 556 ; N eacute ; B 70 -14 627 750 ; -C -1 ; WX 611 ; N otilde ; B 82 -14 646 737 ; -C -1 ; WX 722 ; N Aacute ; B 20 0 750 936 ; -C -1 ; WX 611 ; N ocircumflex ; B 82 -14 643 750 ; -C -1 ; WX 556 ; N yacute ; B 42 -214 652 750 ; -C -1 ; WX 611 ; N udieresis ; B 98 -14 658 729 ; -C -1 ; WX 834 ; N threequarters ; B 99 -19 839 710 ; -C -1 ; WX 556 ; N acircumflex ; B 55 -14 583 750 ; -C -1 ; WX 722 ; N Eth ; B 62 0 777 718 ; -C -1 ; WX 556 ; N edieresis ; B 70 -14 594 729 ; -C -1 ; WX 611 ; N ugrave ; B 98 -14 658 750 ; -C -1 ; WX 1000 ; N trademark ; B 179 306 1109 718 ; -C -1 ; WX 611 ; N ograve ; B 82 -14 643 750 ; -C -1 ; WX 556 ; N scaron ; B 63 -14 614 750 ; -C -1 ; WX 278 ; N Idieresis ; B 64 0 494 915 ; -C -1 ; WX 611 ; N uacute ; B 98 -14 658 750 ; -C -1 ; WX 556 ; N agrave ; B 55 -14 583 750 ; -C -1 ; WX 611 ; N ntilde ; B 65 0 646 737 ; -C -1 ; WX 556 ; N aring ; B 55 -14 583 776 ; -C -1 ; WX 500 ; N zcaron ; B 20 0 586 750 ; -C -1 ; WX 278 ; N Icircumflex ; B 64 0 484 936 ; -C -1 ; WX 722 ; N Ntilde ; B 69 0 807 923 ; -C -1 ; WX 611 ; N ucircumflex ; B 98 -14 658 750 ; -C -1 ; WX 667 ; N Ecircumflex ; B 76 0 757 936 ; -C -1 ; WX 278 ; N Iacute ; B 64 0 528 936 ; -C -1 ; WX 722 ; N Ccedilla ; B 107 -228 789 737 ; -C -1 ; WX 778 ; N Odieresis ; B 107 -19 823 915 ; -C -1 ; WX 667 ; N Scaron ; B 81 -19 718 936 ; -C -1 ; WX 667 ; N Edieresis ; B 76 0 757 915 ; -C -1 ; WX 278 ; N Igrave ; B 64 0 367 936 ; -C -1 ; WX 556 ; N adieresis ; B 55 -14 594 729 ; -C -1 ; WX 778 ; N Ograve ; B 107 -19 823 936 ; -C -1 ; WX 667 ; N Egrave ; B 76 0 757 936 ; -C -1 ; WX 667 ; N Ydieresis ; B 168 0 806 915 ; -C -1 ; WX 737 ; N registered ; B 55 -19 834 737 ; -C -1 ; WX 778 ; N Otilde ; B 107 -19 823 923 ; -C -1 ; WX 834 ; N onequarter ; B 132 -19 806 710 ; -C -1 ; WX 722 ; N Ugrave ; B 116 -19 804 936 ; -C -1 ; WX 722 ; N Ucircumflex ; B 116 -19 804 936 ; -C -1 ; WX 667 ; N Thorn ; B 76 0 716 718 ; -C -1 ; WX 584 ; N divide ; B 82 -42 610 548 ; -C -1 ; WX 722 ; N Atilde ; B 20 0 741 923 ; -C -1 ; WX 722 ; N Uacute ; B 116 -19 804 936 ; -C -1 ; WX 778 ; N Ocircumflex ; B 107 -19 823 936 ; -C -1 ; WX 584 ; N logicalnot ; B 105 108 633 419 ; -C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ; -C -1 ; WX 278 ; N idieresis ; B 69 0 455 729 ; -C -1 ; WX 278 ; N iacute ; B 69 0 488 750 ; -C -1 ; WX 556 ; N aacute ; B 55 -14 627 750 ; -C -1 ; WX 584 ; N plusminus ; B 40 0 625 506 ; -C -1 ; WX 584 ; N multiply ; B 57 1 635 505 ; -C -1 ; WX 722 ; N Udieresis ; B 116 -19 804 915 ; -C -1 ; WX 584 ; N minus ; B 82 197 610 309 ; -C -1 ; WX 333 ; N onesuperior ; B 148 283 388 710 ; -C -1 ; WX 667 ; N Eacute ; B 76 0 757 936 ; -C -1 ; WX 722 ; N Acircumflex ; B 20 0 706 936 ; -C -1 ; WX 737 ; N copyright ; B 56 -19 835 737 ; -C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ; -C -1 ; WX 611 ; N odieresis ; B 82 -14 643 729 ; -C -1 ; WX 611 ; N oacute ; B 82 -14 654 750 ; -C -1 ; WX 400 ; N degree ; B 175 426 467 712 ; -C -1 ; WX 278 ; N igrave ; B 69 0 326 750 ; -C -1 ; WX 611 ; N mu ; B 22 -207 658 532 ; -C -1 ; WX 778 ; N Oacute ; B 107 -19 823 936 ; -C -1 ; WX 611 ; N eth ; B 82 -14 670 737 ; -C -1 ; WX 722 ; N Adieresis ; B 20 0 716 915 ; -C -1 ; WX 667 ; N Yacute ; B 168 0 806 936 ; -C -1 ; WX 280 ; N brokenbar ; B 80 -19 353 737 ; -C -1 ; WX 834 ; N onehalf ; B 132 -19 858 710 ; -EndCharMetrics -StartKernData -StartKernPairs 209 - -KPX A y -30 -KPX A w -30 -KPX A v -40 -KPX A u -30 -KPX A Y -110 -KPX A W -60 -KPX A V -80 -KPX A U -50 -KPX A T -90 -KPX A Q -40 -KPX A O -40 -KPX A G -50 -KPX A C -40 - -KPX B U -10 -KPX B A -30 - -KPX D period -30 -KPX D comma -30 -KPX D Y -70 -KPX D W -40 -KPX D V -40 -KPX D A -40 - -KPX F period -100 -KPX F comma -100 -KPX F a -20 -KPX F A -80 - -KPX J u -20 -KPX J period -20 -KPX J comma -20 -KPX J A -20 - -KPX K y -40 -KPX K u -30 -KPX K o -35 -KPX K e -15 -KPX K O -30 - -KPX L y -30 -KPX L quoteright -140 -KPX L quotedblright -140 -KPX L Y -120 -KPX L W -80 -KPX L V -110 -KPX L T -90 - -KPX O period -40 -KPX O comma -40 -KPX O Y -70 -KPX O X -50 -KPX O W -50 -KPX O V -50 -KPX O T -40 -KPX O A -50 - -KPX P period -120 -KPX P o -40 -KPX P e -30 -KPX P comma -120 -KPX P a -30 -KPX P A -100 - -KPX Q period 20 -KPX Q comma 20 -KPX Q U -10 - -KPX R Y -50 -KPX R W -40 -KPX R V -50 -KPX R U -20 -KPX R T -20 -KPX R O -20 - -KPX T y -60 -KPX T w -60 -KPX T u -90 -KPX T semicolon -40 -KPX T r -80 -KPX T period -80 -KPX T o -80 -KPX T hyphen -120 -KPX T e -60 -KPX T comma -80 -KPX T colon -40 -KPX T a -80 -KPX T O -40 -KPX T A -90 - -KPX U period -30 -KPX U comma -30 -KPX U A -50 - -KPX V u -60 -KPX V semicolon -40 -KPX V period -120 -KPX V o -90 -KPX V hyphen -80 -KPX V e -50 -KPX V comma -120 -KPX V colon -40 -KPX V a -60 -KPX V O -50 -KPX V G -50 -KPX V A -80 - -KPX W y -20 -KPX W u -45 -KPX W semicolon -10 -KPX W period -80 -KPX W o -60 -KPX W hyphen -40 -KPX W e -35 -KPX W comma -80 -KPX W colon -10 -KPX W a -40 -KPX W O -20 -KPX W A -60 - -KPX Y u -100 -KPX Y semicolon -50 -KPX Y period -100 -KPX Y o -100 -KPX Y e -80 -KPX Y comma -100 -KPX Y colon -50 -KPX Y a -90 -KPX Y O -70 -KPX Y A -110 - -KPX a y -20 -KPX a w -15 -KPX a v -15 -KPX a g -10 - -KPX b y -20 -KPX b v -20 -KPX b u -20 -KPX b l -10 - -KPX c y -10 -KPX c l -20 -KPX c k -20 -KPX c h -10 - -KPX colon space -40 - -KPX comma space -40 -KPX comma quoteright -120 -KPX comma quotedblright -120 - -KPX d y -15 -KPX d w -15 -KPX d v -15 -KPX d d -10 - -KPX e y -15 -KPX e x -15 -KPX e w -15 -KPX e v -15 -KPX e period 20 -KPX e comma 10 - -KPX f quoteright 30 -KPX f quotedblright 30 -KPX f period -10 -KPX f o -20 -KPX f e -10 -KPX f comma -10 - -KPX g g -10 -KPX g e 10 - -KPX h y -20 - -KPX k o -15 - -KPX l y -15 -KPX l w -15 - -KPX m y -30 -KPX m u -20 - -KPX n y -20 -KPX n v -40 -KPX n u -10 - -KPX o y -20 -KPX o x -30 -KPX o w -15 -KPX o v -20 - -KPX p y -15 - -KPX period space -40 -KPX period quoteright -120 -KPX period quotedblright -120 - -KPX quotedblright space -80 - -KPX quoteleft quoteleft -46 - -KPX quoteright v -20 -KPX quoteright space -80 -KPX quoteright s -60 -KPX quoteright r -40 -KPX quoteright quoteright -46 -KPX quoteright l -20 -KPX quoteright d -80 - -KPX r y 10 -KPX r v 10 -KPX r t 20 -KPX r s -15 -KPX r q -20 -KPX r period -60 -KPX r o -20 -KPX r hyphen -20 -KPX r g -15 -KPX r d -20 -KPX r comma -60 -KPX r c -20 - -KPX s w -15 - -KPX semicolon space -40 - -KPX space quoteleft -60 -KPX space quotedblleft -80 -KPX space Y -120 -KPX space W -80 -KPX space V -80 -KPX space T -100 - -KPX v period -80 -KPX v o -30 -KPX v comma -80 -KPX v a -20 - -KPX w period -40 -KPX w o -20 -KPX w comma -40 - -KPX x e -10 - -KPX y period -80 -KPX y o -25 -KPX y e -10 -KPX y comma -80 -KPX y a -30 - -KPX z e 10 -EndKernPairs -EndKernData -StartComposites 58 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 235 186 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 235 186 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 235 186 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave 235 186 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring 235 186 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde 235 186 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 215 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 207 186 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 207 186 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 207 186 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 207 186 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute 13 186 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 13 186 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 13 186 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave 13 186 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 235 186 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 263 186 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 263 186 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 263 186 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 263 186 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 263 186 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 207 186 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 235 186 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 235 186 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 235 186 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave 235 186 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 207 186 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 207 186 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 179 186 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 112 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 112 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 112 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave 112 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 112 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 112 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 132 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 112 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 112 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 112 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 112 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 139 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 139 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 139 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 139 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 139 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 139 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 112 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute 139 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 139 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 139 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave 139 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute 112 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 112 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 84 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Helvetica-Oblique.afm b/config/psfonts/Helvetica-Oblique.afm deleted file mode 100644 index 3d69eb7c..00000000 --- a/config/psfonts/Helvetica-Oblique.afm +++ /dev/null @@ -1,612 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved. -Comment Creation Date: Thu Mar 15 10:24:18 1990 -Comment UniqueID 28362 -Comment VMusage 7572 42473 -FontName Helvetica-Oblique -FullName Helvetica Oblique -FamilyName Helvetica -Weight Medium -ItalicAngle -12 -IsFixedPitch false -FontBBox -170 -225 1116 931 -UnderlinePosition -100 -UnderlineThickness 50 -Version 001.006 -Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries. -EncodingScheme AdobeStandardEncoding -CapHeight 718 -XHeight 523 -Ascender 718 -Descender -207 -StartCharMetrics 228 -C 32 ; WX 278 ; N space ; B 0 0 0 0 ; -C 33 ; WX 278 ; N exclam ; B 90 0 340 718 ; -C 34 ; WX 355 ; N quotedbl ; B 168 463 438 718 ; -C 35 ; WX 556 ; N numbersign ; B 73 0 631 688 ; -C 36 ; WX 556 ; N dollar ; B 69 -115 617 775 ; -C 37 ; WX 889 ; N percent ; B 147 -19 889 703 ; -C 38 ; WX 667 ; N ampersand ; B 77 -15 647 718 ; -C 39 ; WX 222 ; N quoteright ; B 151 463 310 718 ; -C 40 ; WX 333 ; N parenleft ; B 108 -207 454 733 ; -C 41 ; WX 333 ; N parenright ; B -9 -207 337 733 ; -C 42 ; WX 389 ; N asterisk ; B 165 431 475 718 ; -C 43 ; WX 584 ; N plus ; B 85 0 606 505 ; -C 44 ; WX 278 ; N comma ; B 56 -147 214 106 ; -C 45 ; WX 333 ; N hyphen ; B 93 232 357 322 ; -C 46 ; WX 278 ; N period ; B 87 0 214 106 ; -C 47 ; WX 278 ; N slash ; B -21 -19 452 737 ; -C 48 ; WX 556 ; N zero ; B 93 -19 608 703 ; -C 49 ; WX 556 ; N one ; B 207 0 508 703 ; -C 50 ; WX 556 ; N two ; B 26 0 617 703 ; -C 51 ; WX 556 ; N three ; B 75 -19 610 703 ; -C 52 ; WX 556 ; N four ; B 61 0 576 703 ; -C 53 ; WX 556 ; N five ; B 68 -19 621 688 ; -C 54 ; WX 556 ; N six ; B 91 -19 615 703 ; -C 55 ; WX 556 ; N seven ; B 137 0 669 688 ; -C 56 ; WX 556 ; N eight ; B 74 -19 607 703 ; -C 57 ; WX 556 ; N nine ; B 82 -19 609 703 ; -C 58 ; WX 278 ; N colon ; B 87 0 301 516 ; -C 59 ; WX 278 ; N semicolon ; B 56 -147 301 516 ; -C 60 ; WX 584 ; N less ; B 94 11 641 495 ; -C 61 ; WX 584 ; N equal ; B 63 115 628 390 ; -C 62 ; WX 584 ; N greater ; B 50 11 597 495 ; -C 63 ; WX 556 ; N question ; B 161 0 610 727 ; -C 64 ; WX 1015 ; N at ; B 215 -19 965 737 ; -C 65 ; WX 667 ; N A ; B 14 0 654 718 ; -C 66 ; WX 667 ; N B ; B 74 0 712 718 ; -C 67 ; WX 722 ; N C ; B 108 -19 782 737 ; -C 68 ; WX 722 ; N D ; B 81 0 764 718 ; -C 69 ; WX 667 ; N E ; B 86 0 762 718 ; -C 70 ; WX 611 ; N F ; B 86 0 736 718 ; -C 71 ; WX 778 ; N G ; B 111 -19 799 737 ; -C 72 ; WX 722 ; N H ; B 77 0 799 718 ; -C 73 ; WX 278 ; N I ; B 91 0 341 718 ; -C 74 ; WX 500 ; N J ; B 47 -19 581 718 ; -C 75 ; WX 667 ; N K ; B 76 0 808 718 ; -C 76 ; WX 556 ; N L ; B 76 0 555 718 ; -C 77 ; WX 833 ; N M ; B 73 0 914 718 ; -C 78 ; WX 722 ; N N ; B 76 0 799 718 ; -C 79 ; WX 778 ; N O ; B 105 -19 826 737 ; -C 80 ; WX 667 ; N P ; B 86 0 737 718 ; -C 81 ; WX 778 ; N Q ; B 105 -56 826 737 ; -C 82 ; WX 722 ; N R ; B 88 0 773 718 ; -C 83 ; WX 667 ; N S ; B 90 -19 713 737 ; -C 84 ; WX 611 ; N T ; B 148 0 750 718 ; -C 85 ; WX 722 ; N U ; B 123 -19 797 718 ; -C 86 ; WX 667 ; N V ; B 173 0 800 718 ; -C 87 ; WX 944 ; N W ; B 169 0 1081 718 ; -C 88 ; WX 667 ; N X ; B 19 0 790 718 ; -C 89 ; WX 667 ; N Y ; B 167 0 806 718 ; -C 90 ; WX 611 ; N Z ; B 23 0 741 718 ; -C 91 ; WX 278 ; N bracketleft ; B 21 -196 403 722 ; -C 92 ; WX 278 ; N backslash ; B 140 -19 291 737 ; -C 93 ; WX 278 ; N bracketright ; B -14 -196 368 722 ; -C 94 ; WX 469 ; N asciicircum ; B 42 264 539 688 ; -C 95 ; WX 556 ; N underscore ; B -27 -125 540 -75 ; -C 96 ; WX 222 ; N quoteleft ; B 165 470 323 725 ; -C 97 ; WX 556 ; N a ; B 61 -15 559 538 ; -C 98 ; WX 556 ; N b ; B 58 -15 584 718 ; -C 99 ; WX 500 ; N c ; B 74 -15 553 538 ; -C 100 ; WX 556 ; N d ; B 84 -15 652 718 ; -C 101 ; WX 556 ; N e ; B 84 -15 578 538 ; -C 102 ; WX 278 ; N f ; B 86 0 416 728 ; L i fi ; L l fl ; -C 103 ; WX 556 ; N g ; B 42 -220 610 538 ; -C 104 ; WX 556 ; N h ; B 65 0 573 718 ; -C 105 ; WX 222 ; N i ; B 67 0 308 718 ; -C 106 ; WX 222 ; N j ; B -60 -210 308 718 ; -C 107 ; WX 500 ; N k ; B 67 0 600 718 ; -C 108 ; WX 222 ; N l ; B 67 0 308 718 ; -C 109 ; WX 833 ; N m ; B 65 0 852 538 ; -C 110 ; WX 556 ; N n ; B 65 0 573 538 ; -C 111 ; WX 556 ; N o ; B 83 -14 585 538 ; -C 112 ; WX 556 ; N p ; B 14 -207 584 538 ; -C 113 ; WX 556 ; N q ; B 84 -207 605 538 ; -C 114 ; WX 333 ; N r ; B 77 0 446 538 ; -C 115 ; WX 500 ; N s ; B 63 -15 529 538 ; -C 116 ; WX 278 ; N t ; B 102 -7 368 669 ; -C 117 ; WX 556 ; N u ; B 94 -15 600 523 ; -C 118 ; WX 500 ; N v ; B 119 0 603 523 ; -C 119 ; WX 722 ; N w ; B 125 0 820 523 ; -C 120 ; WX 500 ; N x ; B 11 0 594 523 ; -C 121 ; WX 500 ; N y ; B 15 -214 600 523 ; -C 122 ; WX 500 ; N z ; B 31 0 571 523 ; -C 123 ; WX 334 ; N braceleft ; B 92 -196 445 722 ; -C 124 ; WX 260 ; N bar ; B 90 -19 324 737 ; -C 125 ; WX 334 ; N braceright ; B 0 -196 354 722 ; -C 126 ; WX 584 ; N asciitilde ; B 111 180 580 326 ; -C 161 ; WX 333 ; N exclamdown ; B 77 -195 326 523 ; -C 162 ; WX 556 ; N cent ; B 95 -115 584 623 ; -C 163 ; WX 556 ; N sterling ; B 49 -16 634 718 ; -C 164 ; WX 167 ; N fraction ; B -170 -19 482 703 ; -C 165 ; WX 556 ; N yen ; B 81 0 699 688 ; -C 166 ; WX 556 ; N florin ; B -52 -207 654 737 ; -C 167 ; WX 556 ; N section ; B 76 -191 584 737 ; -C 168 ; WX 556 ; N currency ; B 60 99 646 603 ; -C 169 ; WX 191 ; N quotesingle ; B 157 463 285 718 ; -C 170 ; WX 333 ; N quotedblleft ; B 138 470 461 725 ; -C 171 ; WX 556 ; N guillemotleft ; B 146 108 554 446 ; -C 172 ; WX 333 ; N guilsinglleft ; B 137 108 340 446 ; -C 173 ; WX 333 ; N guilsinglright ; B 111 108 314 446 ; -C 174 ; WX 500 ; N fi ; B 86 0 587 728 ; -C 175 ; WX 500 ; N fl ; B 86 0 585 728 ; -C 177 ; WX 556 ; N endash ; B 51 240 623 313 ; -C 178 ; WX 556 ; N dagger ; B 135 -159 622 718 ; -C 179 ; WX 556 ; N daggerdbl ; B 52 -159 623 718 ; -C 180 ; WX 278 ; N periodcentered ; B 129 190 257 315 ; -C 182 ; WX 537 ; N paragraph ; B 126 -173 650 718 ; -C 183 ; WX 350 ; N bullet ; B 91 202 413 517 ; -C 184 ; WX 222 ; N quotesinglbase ; B 21 -149 180 106 ; -C 185 ; WX 333 ; N quotedblbase ; B -6 -149 318 106 ; -C 186 ; WX 333 ; N quotedblright ; B 124 463 448 718 ; -C 187 ; WX 556 ; N guillemotright ; B 120 108 528 446 ; -C 188 ; WX 1000 ; N ellipsis ; B 115 0 908 106 ; -C 189 ; WX 1000 ; N perthousand ; B 88 -19 1029 703 ; -C 191 ; WX 611 ; N questiondown ; B 85 -201 534 525 ; -C 193 ; WX 333 ; N grave ; B 170 593 337 734 ; -C 194 ; WX 333 ; N acute ; B 248 593 475 734 ; -C 195 ; WX 333 ; N circumflex ; B 147 593 438 734 ; -C 196 ; WX 333 ; N tilde ; B 125 606 490 722 ; -C 197 ; WX 333 ; N macron ; B 143 627 468 684 ; -C 198 ; WX 333 ; N breve ; B 167 595 476 731 ; -C 199 ; WX 333 ; N dotaccent ; B 249 604 362 706 ; -C 200 ; WX 333 ; N dieresis ; B 168 604 443 706 ; -C 202 ; WX 333 ; N ring ; B 214 572 402 756 ; -C 203 ; WX 333 ; N cedilla ; B 2 -225 232 0 ; -C 205 ; WX 333 ; N hungarumlaut ; B 157 593 565 734 ; -C 206 ; WX 333 ; N ogonek ; B 43 -225 249 0 ; -C 207 ; WX 333 ; N caron ; B 177 593 468 734 ; -C 208 ; WX 1000 ; N emdash ; B 51 240 1067 313 ; -C 225 ; WX 1000 ; N AE ; B 8 0 1097 718 ; -C 227 ; WX 370 ; N ordfeminine ; B 100 304 449 737 ; -C 232 ; WX 556 ; N Lslash ; B 41 0 555 718 ; -C 233 ; WX 778 ; N Oslash ; B 43 -19 890 737 ; -C 234 ; WX 1000 ; N OE ; B 98 -19 1116 737 ; -C 235 ; WX 365 ; N ordmasculine ; B 100 304 468 737 ; -C 241 ; WX 889 ; N ae ; B 61 -15 909 538 ; -C 245 ; WX 278 ; N dotlessi ; B 95 0 294 523 ; -C 248 ; WX 222 ; N lslash ; B 41 0 347 718 ; -C 249 ; WX 611 ; N oslash ; B 29 -22 647 545 ; -C 250 ; WX 944 ; N oe ; B 83 -15 964 538 ; -C 251 ; WX 611 ; N germandbls ; B 67 -15 658 728 ; -C -1 ; WX 611 ; N Zcaron ; B 23 0 741 929 ; -C -1 ; WX 500 ; N ccedilla ; B 74 -225 553 538 ; -C -1 ; WX 500 ; N ydieresis ; B 15 -214 600 706 ; -C -1 ; WX 556 ; N atilde ; B 61 -15 592 722 ; -C -1 ; WX 278 ; N icircumflex ; B 95 0 411 734 ; -C -1 ; WX 333 ; N threesuperior ; B 90 270 436 703 ; -C -1 ; WX 556 ; N ecircumflex ; B 84 -15 578 734 ; -C -1 ; WX 556 ; N thorn ; B 14 -207 584 718 ; -C -1 ; WX 556 ; N egrave ; B 84 -15 578 734 ; -C -1 ; WX 333 ; N twosuperior ; B 64 281 449 703 ; -C -1 ; WX 556 ; N eacute ; B 84 -15 587 734 ; -C -1 ; WX 556 ; N otilde ; B 83 -14 602 722 ; -C -1 ; WX 667 ; N Aacute ; B 14 0 683 929 ; -C -1 ; WX 556 ; N ocircumflex ; B 83 -14 585 734 ; -C -1 ; WX 500 ; N yacute ; B 15 -214 600 734 ; -C -1 ; WX 556 ; N udieresis ; B 94 -15 600 706 ; -C -1 ; WX 834 ; N threequarters ; B 130 -19 861 703 ; -C -1 ; WX 556 ; N acircumflex ; B 61 -15 559 734 ; -C -1 ; WX 722 ; N Eth ; B 69 0 764 718 ; -C -1 ; WX 556 ; N edieresis ; B 84 -15 578 706 ; -C -1 ; WX 556 ; N ugrave ; B 94 -15 600 734 ; -C -1 ; WX 1000 ; N trademark ; B 186 306 1056 718 ; -C -1 ; WX 556 ; N ograve ; B 83 -14 585 734 ; -C -1 ; WX 500 ; N scaron ; B 63 -15 552 734 ; -C -1 ; WX 278 ; N Idieresis ; B 91 0 458 901 ; -C -1 ; WX 556 ; N uacute ; B 94 -15 600 734 ; -C -1 ; WX 556 ; N agrave ; B 61 -15 559 734 ; -C -1 ; WX 556 ; N ntilde ; B 65 0 592 722 ; -C -1 ; WX 556 ; N aring ; B 61 -15 559 756 ; -C -1 ; WX 500 ; N zcaron ; B 31 0 571 734 ; -C -1 ; WX 278 ; N Icircumflex ; B 91 0 452 929 ; -C -1 ; WX 722 ; N Ntilde ; B 76 0 799 917 ; -C -1 ; WX 556 ; N ucircumflex ; B 94 -15 600 734 ; -C -1 ; WX 667 ; N Ecircumflex ; B 86 0 762 929 ; -C -1 ; WX 278 ; N Iacute ; B 91 0 489 929 ; -C -1 ; WX 722 ; N Ccedilla ; B 108 -225 782 737 ; -C -1 ; WX 778 ; N Odieresis ; B 105 -19 826 901 ; -C -1 ; WX 667 ; N Scaron ; B 90 -19 713 929 ; -C -1 ; WX 667 ; N Edieresis ; B 86 0 762 901 ; -C -1 ; WX 278 ; N Igrave ; B 91 0 351 929 ; -C -1 ; WX 556 ; N adieresis ; B 61 -15 559 706 ; -C -1 ; WX 778 ; N Ograve ; B 105 -19 826 929 ; -C -1 ; WX 667 ; N Egrave ; B 86 0 762 929 ; -C -1 ; WX 667 ; N Ydieresis ; B 167 0 806 901 ; -C -1 ; WX 737 ; N registered ; B 54 -19 837 737 ; -C -1 ; WX 778 ; N Otilde ; B 105 -19 826 917 ; -C -1 ; WX 834 ; N onequarter ; B 150 -19 802 703 ; -C -1 ; WX 722 ; N Ugrave ; B 123 -19 797 929 ; -C -1 ; WX 722 ; N Ucircumflex ; B 123 -19 797 929 ; -C -1 ; WX 667 ; N Thorn ; B 86 0 712 718 ; -C -1 ; WX 584 ; N divide ; B 85 -19 606 524 ; -C -1 ; WX 667 ; N Atilde ; B 14 0 699 917 ; -C -1 ; WX 722 ; N Uacute ; B 123 -19 797 929 ; -C -1 ; WX 778 ; N Ocircumflex ; B 105 -19 826 929 ; -C -1 ; WX 584 ; N logicalnot ; B 106 108 628 390 ; -C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ; -C -1 ; WX 278 ; N idieresis ; B 95 0 416 706 ; -C -1 ; WX 278 ; N iacute ; B 95 0 448 734 ; -C -1 ; WX 556 ; N aacute ; B 61 -15 587 734 ; -C -1 ; WX 584 ; N plusminus ; B 39 0 618 506 ; -C -1 ; WX 584 ; N multiply ; B 50 0 642 506 ; -C -1 ; WX 722 ; N Udieresis ; B 123 -19 797 901 ; -C -1 ; WX 584 ; N minus ; B 85 216 606 289 ; -C -1 ; WX 333 ; N onesuperior ; B 166 281 371 703 ; -C -1 ; WX 667 ; N Eacute ; B 86 0 762 929 ; -C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ; -C -1 ; WX 737 ; N copyright ; B 54 -19 837 737 ; -C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ; -C -1 ; WX 556 ; N odieresis ; B 83 -14 585 706 ; -C -1 ; WX 556 ; N oacute ; B 83 -14 587 734 ; -C -1 ; WX 400 ; N degree ; B 169 411 468 703 ; -C -1 ; WX 278 ; N igrave ; B 95 0 310 734 ; -C -1 ; WX 556 ; N mu ; B 24 -207 600 523 ; -C -1 ; WX 778 ; N Oacute ; B 105 -19 826 929 ; -C -1 ; WX 556 ; N eth ; B 81 -15 617 737 ; -C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ; -C -1 ; WX 667 ; N Yacute ; B 167 0 806 929 ; -C -1 ; WX 260 ; N brokenbar ; B 90 -19 324 737 ; -C -1 ; WX 834 ; N onehalf ; B 114 -19 839 703 ; -EndCharMetrics -StartKernData -StartKernPairs 250 - -KPX A y -40 -KPX A w -40 -KPX A v -40 -KPX A u -30 -KPX A Y -100 -KPX A W -50 -KPX A V -70 -KPX A U -50 -KPX A T -120 -KPX A Q -30 -KPX A O -30 -KPX A G -30 -KPX A C -30 - -KPX B period -20 -KPX B comma -20 -KPX B U -10 - -KPX C period -30 -KPX C comma -30 - -KPX D period -70 -KPX D comma -70 -KPX D Y -90 -KPX D W -40 -KPX D V -70 -KPX D A -40 - -KPX F r -45 -KPX F period -150 -KPX F o -30 -KPX F e -30 -KPX F comma -150 -KPX F a -50 -KPX F A -80 - -KPX J u -20 -KPX J period -30 -KPX J comma -30 -KPX J a -20 -KPX J A -20 - -KPX K y -50 -KPX K u -30 -KPX K o -40 -KPX K e -40 -KPX K O -50 - -KPX L y -30 -KPX L quoteright -160 -KPX L quotedblright -140 -KPX L Y -140 -KPX L W -70 -KPX L V -110 -KPX L T -110 - -KPX O period -40 -KPX O comma -40 -KPX O Y -70 -KPX O X -60 -KPX O W -30 -KPX O V -50 -KPX O T -40 -KPX O A -20 - -KPX P period -180 -KPX P o -50 -KPX P e -50 -KPX P comma -180 -KPX P a -40 -KPX P A -120 - -KPX Q U -10 - -KPX R Y -50 -KPX R W -30 -KPX R V -50 -KPX R U -40 -KPX R T -30 -KPX R O -20 - -KPX S period -20 -KPX S comma -20 - -KPX T y -120 -KPX T w -120 -KPX T u -120 -KPX T semicolon -20 -KPX T r -120 -KPX T period -120 -KPX T o -120 -KPX T hyphen -140 -KPX T e -120 -KPX T comma -120 -KPX T colon -20 -KPX T a -120 -KPX T O -40 -KPX T A -120 - -KPX U period -40 -KPX U comma -40 -KPX U A -40 - -KPX V u -70 -KPX V semicolon -40 -KPX V period -125 -KPX V o -80 -KPX V hyphen -80 -KPX V e -80 -KPX V comma -125 -KPX V colon -40 -KPX V a -70 -KPX V O -40 -KPX V G -40 -KPX V A -80 - -KPX W y -20 -KPX W u -30 -KPX W period -80 -KPX W o -30 -KPX W hyphen -40 -KPX W e -30 -KPX W comma -80 -KPX W a -40 -KPX W O -20 -KPX W A -50 - -KPX Y u -110 -KPX Y semicolon -60 -KPX Y period -140 -KPX Y o -140 -KPX Y i -20 -KPX Y hyphen -140 -KPX Y e -140 -KPX Y comma -140 -KPX Y colon -60 -KPX Y a -140 -KPX Y O -85 -KPX Y A -110 - -KPX a y -30 -KPX a w -20 -KPX a v -20 - -KPX b y -20 -KPX b v -20 -KPX b u -20 -KPX b period -40 -KPX b l -20 -KPX b comma -40 -KPX b b -10 - -KPX c k -20 -KPX c comma -15 - -KPX colon space -50 - -KPX comma quoteright -100 -KPX comma quotedblright -100 - -KPX e y -20 -KPX e x -30 -KPX e w -20 -KPX e v -30 -KPX e period -15 -KPX e comma -15 - -KPX f quoteright 50 -KPX f quotedblright 60 -KPX f period -30 -KPX f o -30 -KPX f e -30 -KPX f dotlessi -28 -KPX f comma -30 -KPX f a -30 - -KPX g r -10 - -KPX h y -30 - -KPX k o -20 -KPX k e -20 - -KPX m y -15 -KPX m u -10 - -KPX n y -15 -KPX n v -20 -KPX n u -10 - -KPX o y -30 -KPX o x -30 -KPX o w -15 -KPX o v -15 -KPX o period -40 -KPX o comma -40 - -KPX oslash z -55 -KPX oslash y -70 -KPX oslash x -85 -KPX oslash w -70 -KPX oslash v -70 -KPX oslash u -55 -KPX oslash t -55 -KPX oslash s -55 -KPX oslash r -55 -KPX oslash q -55 -KPX oslash period -95 -KPX oslash p -55 -KPX oslash o -55 -KPX oslash n -55 -KPX oslash m -55 -KPX oslash l -55 -KPX oslash k -55 -KPX oslash j -55 -KPX oslash i -55 -KPX oslash h -55 -KPX oslash g -55 -KPX oslash f -55 -KPX oslash e -55 -KPX oslash d -55 -KPX oslash comma -95 -KPX oslash c -55 -KPX oslash b -55 -KPX oslash a -55 - -KPX p y -30 -KPX p period -35 -KPX p comma -35 - -KPX period space -60 -KPX period quoteright -100 -KPX period quotedblright -100 - -KPX quotedblright space -40 - -KPX quoteleft quoteleft -57 - -KPX quoteright space -70 -KPX quoteright s -50 -KPX quoteright r -50 -KPX quoteright quoteright -57 -KPX quoteright d -50 - -KPX r y 30 -KPX r v 30 -KPX r u 15 -KPX r t 40 -KPX r semicolon 30 -KPX r period -50 -KPX r p 30 -KPX r n 25 -KPX r m 25 -KPX r l 15 -KPX r k 15 -KPX r i 15 -KPX r comma -50 -KPX r colon 30 -KPX r a -10 - -KPX s w -30 -KPX s period -15 -KPX s comma -15 - -KPX semicolon space -50 - -KPX space quoteleft -60 -KPX space quotedblleft -30 -KPX space Y -90 -KPX space W -40 -KPX space V -50 -KPX space T -50 - -KPX v period -80 -KPX v o -25 -KPX v e -25 -KPX v comma -80 -KPX v a -25 - -KPX w period -60 -KPX w o -10 -KPX w e -10 -KPX w comma -60 -KPX w a -15 - -KPX x e -30 - -KPX y period -100 -KPX y o -20 -KPX y e -20 -KPX y comma -100 -KPX y a -20 - -KPX z o -15 -KPX z e -15 -EndKernPairs -EndKernData -StartComposites 58 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 208 195 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 208 195 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 208 195 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave 208 195 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring 204 175 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde 208 195 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 195 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 208 195 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 208 195 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 208 195 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 208 195 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute 14 195 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 14 195 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 14 195 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave 14 195 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 246 195 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 264 195 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 264 195 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 264 195 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 264 195 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 264 195 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 208 195 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 236 195 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 236 195 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 236 195 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave 236 195 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 208 195 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 208 195 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 180 195 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 112 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 112 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 112 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave 112 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 112 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 102 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 84 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 112 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 112 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 112 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 112 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 102 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 112 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 112 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 112 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 112 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 112 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 84 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute 112 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 112 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 112 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave 112 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute 84 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 84 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Helvetica.afm b/config/psfonts/Helvetica.afm deleted file mode 100644 index 1eb3b448..00000000 --- a/config/psfonts/Helvetica.afm +++ /dev/null @@ -1,612 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved. -Comment Creation Date: Thu Mar 15 08:58:00 1990 -Comment UniqueID 28352 -Comment VMusage 26389 33281 -FontName Helvetica -FullName Helvetica -FamilyName Helvetica -Weight Medium -ItalicAngle 0 -IsFixedPitch false -FontBBox -166 -225 1000 931 -UnderlinePosition -100 -UnderlineThickness 50 -Version 001.006 -Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries. -EncodingScheme AdobeStandardEncoding -CapHeight 718 -XHeight 523 -Ascender 718 -Descender -207 -StartCharMetrics 228 -C 32 ; WX 278 ; N space ; B 0 0 0 0 ; -C 33 ; WX 278 ; N exclam ; B 90 0 187 718 ; -C 34 ; WX 355 ; N quotedbl ; B 70 463 285 718 ; -C 35 ; WX 556 ; N numbersign ; B 28 0 529 688 ; -C 36 ; WX 556 ; N dollar ; B 32 -115 520 775 ; -C 37 ; WX 889 ; N percent ; B 39 -19 850 703 ; -C 38 ; WX 667 ; N ampersand ; B 44 -15 645 718 ; -C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ; -C 40 ; WX 333 ; N parenleft ; B 68 -207 299 733 ; -C 41 ; WX 333 ; N parenright ; B 34 -207 265 733 ; -C 42 ; WX 389 ; N asterisk ; B 39 431 349 718 ; -C 43 ; WX 584 ; N plus ; B 39 0 545 505 ; -C 44 ; WX 278 ; N comma ; B 87 -147 191 106 ; -C 45 ; WX 333 ; N hyphen ; B 44 232 289 322 ; -C 46 ; WX 278 ; N period ; B 87 0 191 106 ; -C 47 ; WX 278 ; N slash ; B -17 -19 295 737 ; -C 48 ; WX 556 ; N zero ; B 37 -19 519 703 ; -C 49 ; WX 556 ; N one ; B 101 0 359 703 ; -C 50 ; WX 556 ; N two ; B 26 0 507 703 ; -C 51 ; WX 556 ; N three ; B 34 -19 522 703 ; -C 52 ; WX 556 ; N four ; B 25 0 523 703 ; -C 53 ; WX 556 ; N five ; B 32 -19 514 688 ; -C 54 ; WX 556 ; N six ; B 38 -19 518 703 ; -C 55 ; WX 556 ; N seven ; B 37 0 523 688 ; -C 56 ; WX 556 ; N eight ; B 38 -19 517 703 ; -C 57 ; WX 556 ; N nine ; B 42 -19 514 703 ; -C 58 ; WX 278 ; N colon ; B 87 0 191 516 ; -C 59 ; WX 278 ; N semicolon ; B 87 -147 191 516 ; -C 60 ; WX 584 ; N less ; B 48 11 536 495 ; -C 61 ; WX 584 ; N equal ; B 39 115 545 390 ; -C 62 ; WX 584 ; N greater ; B 48 11 536 495 ; -C 63 ; WX 556 ; N question ; B 56 0 492 727 ; -C 64 ; WX 1015 ; N at ; B 147 -19 868 737 ; -C 65 ; WX 667 ; N A ; B 14 0 654 718 ; -C 66 ; WX 667 ; N B ; B 74 0 627 718 ; -C 67 ; WX 722 ; N C ; B 44 -19 681 737 ; -C 68 ; WX 722 ; N D ; B 81 0 674 718 ; -C 69 ; WX 667 ; N E ; B 86 0 616 718 ; -C 70 ; WX 611 ; N F ; B 86 0 583 718 ; -C 71 ; WX 778 ; N G ; B 48 -19 704 737 ; -C 72 ; WX 722 ; N H ; B 77 0 646 718 ; -C 73 ; WX 278 ; N I ; B 91 0 188 718 ; -C 74 ; WX 500 ; N J ; B 17 -19 428 718 ; -C 75 ; WX 667 ; N K ; B 76 0 663 718 ; -C 76 ; WX 556 ; N L ; B 76 0 537 718 ; -C 77 ; WX 833 ; N M ; B 73 0 761 718 ; -C 78 ; WX 722 ; N N ; B 76 0 646 718 ; -C 79 ; WX 778 ; N O ; B 39 -19 739 737 ; -C 80 ; WX 667 ; N P ; B 86 0 622 718 ; -C 81 ; WX 778 ; N Q ; B 39 -56 739 737 ; -C 82 ; WX 722 ; N R ; B 88 0 684 718 ; -C 83 ; WX 667 ; N S ; B 49 -19 620 737 ; -C 84 ; WX 611 ; N T ; B 14 0 597 718 ; -C 85 ; WX 722 ; N U ; B 79 -19 644 718 ; -C 86 ; WX 667 ; N V ; B 20 0 647 718 ; -C 87 ; WX 944 ; N W ; B 16 0 928 718 ; -C 88 ; WX 667 ; N X ; B 19 0 648 718 ; -C 89 ; WX 667 ; N Y ; B 14 0 653 718 ; -C 90 ; WX 611 ; N Z ; B 23 0 588 718 ; -C 91 ; WX 278 ; N bracketleft ; B 63 -196 250 722 ; -C 92 ; WX 278 ; N backslash ; B -17 -19 295 737 ; -C 93 ; WX 278 ; N bracketright ; B 28 -196 215 722 ; -C 94 ; WX 469 ; N asciicircum ; B -14 264 483 688 ; -C 95 ; WX 556 ; N underscore ; B 0 -125 556 -75 ; -C 96 ; WX 222 ; N quoteleft ; B 65 470 169 725 ; -C 97 ; WX 556 ; N a ; B 36 -15 530 538 ; -C 98 ; WX 556 ; N b ; B 58 -15 517 718 ; -C 99 ; WX 500 ; N c ; B 30 -15 477 538 ; -C 100 ; WX 556 ; N d ; B 35 -15 499 718 ; -C 101 ; WX 556 ; N e ; B 40 -15 516 538 ; -C 102 ; WX 278 ; N f ; B 14 0 262 728 ; L i fi ; L l fl ; -C 103 ; WX 556 ; N g ; B 40 -220 499 538 ; -C 104 ; WX 556 ; N h ; B 65 0 491 718 ; -C 105 ; WX 222 ; N i ; B 67 0 155 718 ; -C 106 ; WX 222 ; N j ; B -16 -210 155 718 ; -C 107 ; WX 500 ; N k ; B 67 0 501 718 ; -C 108 ; WX 222 ; N l ; B 67 0 155 718 ; -C 109 ; WX 833 ; N m ; B 65 0 769 538 ; -C 110 ; WX 556 ; N n ; B 65 0 491 538 ; -C 111 ; WX 556 ; N o ; B 35 -14 521 538 ; -C 112 ; WX 556 ; N p ; B 58 -207 517 538 ; -C 113 ; WX 556 ; N q ; B 35 -207 494 538 ; -C 114 ; WX 333 ; N r ; B 77 0 332 538 ; -C 115 ; WX 500 ; N s ; B 32 -15 464 538 ; -C 116 ; WX 278 ; N t ; B 14 -7 257 669 ; -C 117 ; WX 556 ; N u ; B 68 -15 489 523 ; -C 118 ; WX 500 ; N v ; B 8 0 492 523 ; -C 119 ; WX 722 ; N w ; B 14 0 709 523 ; -C 120 ; WX 500 ; N x ; B 11 0 490 523 ; -C 121 ; WX 500 ; N y ; B 11 -214 489 523 ; -C 122 ; WX 500 ; N z ; B 31 0 469 523 ; -C 123 ; WX 334 ; N braceleft ; B 42 -196 292 722 ; -C 124 ; WX 260 ; N bar ; B 94 -19 167 737 ; -C 125 ; WX 334 ; N braceright ; B 42 -196 292 722 ; -C 126 ; WX 584 ; N asciitilde ; B 61 180 523 326 ; -C 161 ; WX 333 ; N exclamdown ; B 118 -195 215 523 ; -C 162 ; WX 556 ; N cent ; B 51 -115 513 623 ; -C 163 ; WX 556 ; N sterling ; B 33 -16 539 718 ; -C 164 ; WX 167 ; N fraction ; B -166 -19 333 703 ; -C 165 ; WX 556 ; N yen ; B 3 0 553 688 ; -C 166 ; WX 556 ; N florin ; B -11 -207 501 737 ; -C 167 ; WX 556 ; N section ; B 43 -191 512 737 ; -C 168 ; WX 556 ; N currency ; B 28 99 528 603 ; -C 169 ; WX 191 ; N quotesingle ; B 59 463 132 718 ; -C 170 ; WX 333 ; N quotedblleft ; B 38 470 307 725 ; -C 171 ; WX 556 ; N guillemotleft ; B 97 108 459 446 ; -C 172 ; WX 333 ; N guilsinglleft ; B 88 108 245 446 ; -C 173 ; WX 333 ; N guilsinglright ; B 88 108 245 446 ; -C 174 ; WX 500 ; N fi ; B 14 0 434 728 ; -C 175 ; WX 500 ; N fl ; B 14 0 432 728 ; -C 177 ; WX 556 ; N endash ; B 0 240 556 313 ; -C 178 ; WX 556 ; N dagger ; B 43 -159 514 718 ; -C 179 ; WX 556 ; N daggerdbl ; B 43 -159 514 718 ; -C 180 ; WX 278 ; N periodcentered ; B 77 190 202 315 ; -C 182 ; WX 537 ; N paragraph ; B 18 -173 497 718 ; -C 183 ; WX 350 ; N bullet ; B 18 202 333 517 ; -C 184 ; WX 222 ; N quotesinglbase ; B 53 -149 157 106 ; -C 185 ; WX 333 ; N quotedblbase ; B 26 -149 295 106 ; -C 186 ; WX 333 ; N quotedblright ; B 26 463 295 718 ; -C 187 ; WX 556 ; N guillemotright ; B 97 108 459 446 ; -C 188 ; WX 1000 ; N ellipsis ; B 115 0 885 106 ; -C 189 ; WX 1000 ; N perthousand ; B 7 -19 994 703 ; -C 191 ; WX 611 ; N questiondown ; B 91 -201 527 525 ; -C 193 ; WX 333 ; N grave ; B 14 593 211 734 ; -C 194 ; WX 333 ; N acute ; B 122 593 319 734 ; -C 195 ; WX 333 ; N circumflex ; B 21 593 312 734 ; -C 196 ; WX 333 ; N tilde ; B -4 606 337 722 ; -C 197 ; WX 333 ; N macron ; B 10 627 323 684 ; -C 198 ; WX 333 ; N breve ; B 13 595 321 731 ; -C 199 ; WX 333 ; N dotaccent ; B 121 604 212 706 ; -C 200 ; WX 333 ; N dieresis ; B 40 604 293 706 ; -C 202 ; WX 333 ; N ring ; B 75 572 259 756 ; -C 203 ; WX 333 ; N cedilla ; B 45 -225 259 0 ; -C 205 ; WX 333 ; N hungarumlaut ; B 31 593 409 734 ; -C 206 ; WX 333 ; N ogonek ; B 73 -225 287 0 ; -C 207 ; WX 333 ; N caron ; B 21 593 312 734 ; -C 208 ; WX 1000 ; N emdash ; B 0 240 1000 313 ; -C 225 ; WX 1000 ; N AE ; B 8 0 951 718 ; -C 227 ; WX 370 ; N ordfeminine ; B 24 304 346 737 ; -C 232 ; WX 556 ; N Lslash ; B -20 0 537 718 ; -C 233 ; WX 778 ; N Oslash ; B 39 -19 740 737 ; -C 234 ; WX 1000 ; N OE ; B 36 -19 965 737 ; -C 235 ; WX 365 ; N ordmasculine ; B 25 304 341 737 ; -C 241 ; WX 889 ; N ae ; B 36 -15 847 538 ; -C 245 ; WX 278 ; N dotlessi ; B 95 0 183 523 ; -C 248 ; WX 222 ; N lslash ; B -20 0 242 718 ; -C 249 ; WX 611 ; N oslash ; B 28 -22 537 545 ; -C 250 ; WX 944 ; N oe ; B 35 -15 902 538 ; -C 251 ; WX 611 ; N germandbls ; B 67 -15 571 728 ; -C -1 ; WX 611 ; N Zcaron ; B 23 0 588 929 ; -C -1 ; WX 500 ; N ccedilla ; B 30 -225 477 538 ; -C -1 ; WX 500 ; N ydieresis ; B 11 -214 489 706 ; -C -1 ; WX 556 ; N atilde ; B 36 -15 530 722 ; -C -1 ; WX 278 ; N icircumflex ; B -6 0 285 734 ; -C -1 ; WX 333 ; N threesuperior ; B 5 270 325 703 ; -C -1 ; WX 556 ; N ecircumflex ; B 40 -15 516 734 ; -C -1 ; WX 556 ; N thorn ; B 58 -207 517 718 ; -C -1 ; WX 556 ; N egrave ; B 40 -15 516 734 ; -C -1 ; WX 333 ; N twosuperior ; B 4 281 323 703 ; -C -1 ; WX 556 ; N eacute ; B 40 -15 516 734 ; -C -1 ; WX 556 ; N otilde ; B 35 -14 521 722 ; -C -1 ; WX 667 ; N Aacute ; B 14 0 654 929 ; -C -1 ; WX 556 ; N ocircumflex ; B 35 -14 521 734 ; -C -1 ; WX 500 ; N yacute ; B 11 -214 489 734 ; -C -1 ; WX 556 ; N udieresis ; B 68 -15 489 706 ; -C -1 ; WX 834 ; N threequarters ; B 45 -19 810 703 ; -C -1 ; WX 556 ; N acircumflex ; B 36 -15 530 734 ; -C -1 ; WX 722 ; N Eth ; B 0 0 674 718 ; -C -1 ; WX 556 ; N edieresis ; B 40 -15 516 706 ; -C -1 ; WX 556 ; N ugrave ; B 68 -15 489 734 ; -C -1 ; WX 1000 ; N trademark ; B 46 306 903 718 ; -C -1 ; WX 556 ; N ograve ; B 35 -14 521 734 ; -C -1 ; WX 500 ; N scaron ; B 32 -15 464 734 ; -C -1 ; WX 278 ; N Idieresis ; B 13 0 266 901 ; -C -1 ; WX 556 ; N uacute ; B 68 -15 489 734 ; -C -1 ; WX 556 ; N agrave ; B 36 -15 530 734 ; -C -1 ; WX 556 ; N ntilde ; B 65 0 491 722 ; -C -1 ; WX 556 ; N aring ; B 36 -15 530 756 ; -C -1 ; WX 500 ; N zcaron ; B 31 0 469 734 ; -C -1 ; WX 278 ; N Icircumflex ; B -6 0 285 929 ; -C -1 ; WX 722 ; N Ntilde ; B 76 0 646 917 ; -C -1 ; WX 556 ; N ucircumflex ; B 68 -15 489 734 ; -C -1 ; WX 667 ; N Ecircumflex ; B 86 0 616 929 ; -C -1 ; WX 278 ; N Iacute ; B 91 0 292 929 ; -C -1 ; WX 722 ; N Ccedilla ; B 44 -225 681 737 ; -C -1 ; WX 778 ; N Odieresis ; B 39 -19 739 901 ; -C -1 ; WX 667 ; N Scaron ; B 49 -19 620 929 ; -C -1 ; WX 667 ; N Edieresis ; B 86 0 616 901 ; -C -1 ; WX 278 ; N Igrave ; B -13 0 188 929 ; -C -1 ; WX 556 ; N adieresis ; B 36 -15 530 706 ; -C -1 ; WX 778 ; N Ograve ; B 39 -19 739 929 ; -C -1 ; WX 667 ; N Egrave ; B 86 0 616 929 ; -C -1 ; WX 667 ; N Ydieresis ; B 14 0 653 901 ; -C -1 ; WX 737 ; N registered ; B -14 -19 752 737 ; -C -1 ; WX 778 ; N Otilde ; B 39 -19 739 917 ; -C -1 ; WX 834 ; N onequarter ; B 73 -19 756 703 ; -C -1 ; WX 722 ; N Ugrave ; B 79 -19 644 929 ; -C -1 ; WX 722 ; N Ucircumflex ; B 79 -19 644 929 ; -C -1 ; WX 667 ; N Thorn ; B 86 0 622 718 ; -C -1 ; WX 584 ; N divide ; B 39 -19 545 524 ; -C -1 ; WX 667 ; N Atilde ; B 14 0 654 917 ; -C -1 ; WX 722 ; N Uacute ; B 79 -19 644 929 ; -C -1 ; WX 778 ; N Ocircumflex ; B 39 -19 739 929 ; -C -1 ; WX 584 ; N logicalnot ; B 39 108 545 390 ; -C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ; -C -1 ; WX 278 ; N idieresis ; B 13 0 266 706 ; -C -1 ; WX 278 ; N iacute ; B 95 0 292 734 ; -C -1 ; WX 556 ; N aacute ; B 36 -15 530 734 ; -C -1 ; WX 584 ; N plusminus ; B 39 0 545 506 ; -C -1 ; WX 584 ; N multiply ; B 39 0 545 506 ; -C -1 ; WX 722 ; N Udieresis ; B 79 -19 644 901 ; -C -1 ; WX 584 ; N minus ; B 39 216 545 289 ; -C -1 ; WX 333 ; N onesuperior ; B 43 281 222 703 ; -C -1 ; WX 667 ; N Eacute ; B 86 0 616 929 ; -C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ; -C -1 ; WX 737 ; N copyright ; B -14 -19 752 737 ; -C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ; -C -1 ; WX 556 ; N odieresis ; B 35 -14 521 706 ; -C -1 ; WX 556 ; N oacute ; B 35 -14 521 734 ; -C -1 ; WX 400 ; N degree ; B 54 411 346 703 ; -C -1 ; WX 278 ; N igrave ; B -13 0 184 734 ; -C -1 ; WX 556 ; N mu ; B 68 -207 489 523 ; -C -1 ; WX 778 ; N Oacute ; B 39 -19 739 929 ; -C -1 ; WX 556 ; N eth ; B 35 -15 522 737 ; -C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ; -C -1 ; WX 667 ; N Yacute ; B 14 0 653 929 ; -C -1 ; WX 260 ; N brokenbar ; B 94 -19 167 737 ; -C -1 ; WX 834 ; N onehalf ; B 43 -19 773 703 ; -EndCharMetrics -StartKernData -StartKernPairs 250 - -KPX A y -40 -KPX A w -40 -KPX A v -40 -KPX A u -30 -KPX A Y -100 -KPX A W -50 -KPX A V -70 -KPX A U -50 -KPX A T -120 -KPX A Q -30 -KPX A O -30 -KPX A G -30 -KPX A C -30 - -KPX B period -20 -KPX B comma -20 -KPX B U -10 - -KPX C period -30 -KPX C comma -30 - -KPX D period -70 -KPX D comma -70 -KPX D Y -90 -KPX D W -40 -KPX D V -70 -KPX D A -40 - -KPX F r -45 -KPX F period -150 -KPX F o -30 -KPX F e -30 -KPX F comma -150 -KPX F a -50 -KPX F A -80 - -KPX J u -20 -KPX J period -30 -KPX J comma -30 -KPX J a -20 -KPX J A -20 - -KPX K y -50 -KPX K u -30 -KPX K o -40 -KPX K e -40 -KPX K O -50 - -KPX L y -30 -KPX L quoteright -160 -KPX L quotedblright -140 -KPX L Y -140 -KPX L W -70 -KPX L V -110 -KPX L T -110 - -KPX O period -40 -KPX O comma -40 -KPX O Y -70 -KPX O X -60 -KPX O W -30 -KPX O V -50 -KPX O T -40 -KPX O A -20 - -KPX P period -180 -KPX P o -50 -KPX P e -50 -KPX P comma -180 -KPX P a -40 -KPX P A -120 - -KPX Q U -10 - -KPX R Y -50 -KPX R W -30 -KPX R V -50 -KPX R U -40 -KPX R T -30 -KPX R O -20 - -KPX S period -20 -KPX S comma -20 - -KPX T y -120 -KPX T w -120 -KPX T u -120 -KPX T semicolon -20 -KPX T r -120 -KPX T period -120 -KPX T o -120 -KPX T hyphen -140 -KPX T e -120 -KPX T comma -120 -KPX T colon -20 -KPX T a -120 -KPX T O -40 -KPX T A -120 - -KPX U period -40 -KPX U comma -40 -KPX U A -40 - -KPX V u -70 -KPX V semicolon -40 -KPX V period -125 -KPX V o -80 -KPX V hyphen -80 -KPX V e -80 -KPX V comma -125 -KPX V colon -40 -KPX V a -70 -KPX V O -40 -KPX V G -40 -KPX V A -80 - -KPX W y -20 -KPX W u -30 -KPX W period -80 -KPX W o -30 -KPX W hyphen -40 -KPX W e -30 -KPX W comma -80 -KPX W a -40 -KPX W O -20 -KPX W A -50 - -KPX Y u -110 -KPX Y semicolon -60 -KPX Y period -140 -KPX Y o -140 -KPX Y i -20 -KPX Y hyphen -140 -KPX Y e -140 -KPX Y comma -140 -KPX Y colon -60 -KPX Y a -140 -KPX Y O -85 -KPX Y A -110 - -KPX a y -30 -KPX a w -20 -KPX a v -20 - -KPX b y -20 -KPX b v -20 -KPX b u -20 -KPX b period -40 -KPX b l -20 -KPX b comma -40 -KPX b b -10 - -KPX c k -20 -KPX c comma -15 - -KPX colon space -50 - -KPX comma quoteright -100 -KPX comma quotedblright -100 - -KPX e y -20 -KPX e x -30 -KPX e w -20 -KPX e v -30 -KPX e period -15 -KPX e comma -15 - -KPX f quoteright 50 -KPX f quotedblright 60 -KPX f period -30 -KPX f o -30 -KPX f e -30 -KPX f dotlessi -28 -KPX f comma -30 -KPX f a -30 - -KPX g r -10 - -KPX h y -30 - -KPX k o -20 -KPX k e -20 - -KPX m y -15 -KPX m u -10 - -KPX n y -15 -KPX n v -20 -KPX n u -10 - -KPX o y -30 -KPX o x -30 -KPX o w -15 -KPX o v -15 -KPX o period -40 -KPX o comma -40 - -KPX oslash z -55 -KPX oslash y -70 -KPX oslash x -85 -KPX oslash w -70 -KPX oslash v -70 -KPX oslash u -55 -KPX oslash t -55 -KPX oslash s -55 -KPX oslash r -55 -KPX oslash q -55 -KPX oslash period -95 -KPX oslash p -55 -KPX oslash o -55 -KPX oslash n -55 -KPX oslash m -55 -KPX oslash l -55 -KPX oslash k -55 -KPX oslash j -55 -KPX oslash i -55 -KPX oslash h -55 -KPX oslash g -55 -KPX oslash f -55 -KPX oslash e -55 -KPX oslash d -55 -KPX oslash comma -95 -KPX oslash c -55 -KPX oslash b -55 -KPX oslash a -55 - -KPX p y -30 -KPX p period -35 -KPX p comma -35 - -KPX period space -60 -KPX period quoteright -100 -KPX period quotedblright -100 - -KPX quotedblright space -40 - -KPX quoteleft quoteleft -57 - -KPX quoteright space -70 -KPX quoteright s -50 -KPX quoteright r -50 -KPX quoteright quoteright -57 -KPX quoteright d -50 - -KPX r y 30 -KPX r v 30 -KPX r u 15 -KPX r t 40 -KPX r semicolon 30 -KPX r period -50 -KPX r p 30 -KPX r n 25 -KPX r m 25 -KPX r l 15 -KPX r k 15 -KPX r i 15 -KPX r comma -50 -KPX r colon 30 -KPX r a -10 - -KPX s w -30 -KPX s period -15 -KPX s comma -15 - -KPX semicolon space -50 - -KPX space quoteleft -60 -KPX space quotedblleft -30 -KPX space Y -90 -KPX space W -40 -KPX space V -50 -KPX space T -50 - -KPX v period -80 -KPX v o -25 -KPX v e -25 -KPX v comma -80 -KPX v a -25 - -KPX w period -60 -KPX w o -10 -KPX w e -10 -KPX w comma -60 -KPX w a -15 - -KPX x e -30 - -KPX y period -100 -KPX y o -20 -KPX y e -20 -KPX y comma -100 -KPX y a -20 - -KPX z o -15 -KPX z e -15 -EndKernPairs -EndKernData -StartComposites 58 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 167 195 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 167 195 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 167 195 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave 167 195 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring 167 175 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde 167 195 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 195 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 167 195 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 167 195 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 167 195 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 167 195 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute -27 195 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -27 195 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -27 195 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave -27 195 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 205 195 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 223 195 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 223 195 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 223 195 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 223 195 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 223 195 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 167 195 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 195 195 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 195 195 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 195 195 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave 195 195 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 167 195 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 167 195 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 139 195 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 112 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 112 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 112 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave 112 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 112 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 102 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 84 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 112 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 112 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 112 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 112 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 102 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 112 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 112 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 112 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 112 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 112 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 84 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute 112 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 112 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 112 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave 112 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute 84 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 84 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Times-Bold.afm b/config/psfonts/Times-Bold.afm deleted file mode 100644 index 55207f94..00000000 --- a/config/psfonts/Times-Bold.afm +++ /dev/null @@ -1,648 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved. -Comment Creation Date: Tue Mar 20 12:17:14 1990 -Comment UniqueID 28417 -Comment VMusage 30458 37350 -FontName Times-Bold -FullName Times Bold -FamilyName Times -Weight Bold -ItalicAngle 0 -IsFixedPitch false -FontBBox -168 -218 1000 935 -UnderlinePosition -100 -UnderlineThickness 50 -Version 001.007 -Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype AG and/or its subsidiaries. -EncodingScheme AdobeStandardEncoding -CapHeight 676 -XHeight 461 -Ascender 676 -Descender -205 -StartCharMetrics 228 -C 32 ; WX 250 ; N space ; B 0 0 0 0 ; -C 33 ; WX 333 ; N exclam ; B 81 -13 251 691 ; -C 34 ; WX 555 ; N quotedbl ; B 83 404 472 691 ; -C 35 ; WX 500 ; N numbersign ; B 4 0 496 700 ; -C 36 ; WX 500 ; N dollar ; B 29 -99 472 750 ; -C 37 ; WX 1000 ; N percent ; B 124 -14 877 692 ; -C 38 ; WX 833 ; N ampersand ; B 62 -16 787 691 ; -C 39 ; WX 333 ; N quoteright ; B 79 356 263 691 ; -C 40 ; WX 333 ; N parenleft ; B 46 -168 306 694 ; -C 41 ; WX 333 ; N parenright ; B 27 -168 287 694 ; -C 42 ; WX 500 ; N asterisk ; B 56 255 447 691 ; -C 43 ; WX 570 ; N plus ; B 33 0 537 506 ; -C 44 ; WX 250 ; N comma ; B 39 -180 223 155 ; -C 45 ; WX 333 ; N hyphen ; B 44 171 287 287 ; -C 46 ; WX 250 ; N period ; B 41 -13 210 156 ; -C 47 ; WX 278 ; N slash ; B -24 -19 302 691 ; -C 48 ; WX 500 ; N zero ; B 24 -13 476 688 ; -C 49 ; WX 500 ; N one ; B 65 0 442 688 ; -C 50 ; WX 500 ; N two ; B 17 0 478 688 ; -C 51 ; WX 500 ; N three ; B 16 -14 468 688 ; -C 52 ; WX 500 ; N four ; B 19 0 475 688 ; -C 53 ; WX 500 ; N five ; B 22 -8 470 676 ; -C 54 ; WX 500 ; N six ; B 28 -13 475 688 ; -C 55 ; WX 500 ; N seven ; B 17 0 477 676 ; -C 56 ; WX 500 ; N eight ; B 28 -13 472 688 ; -C 57 ; WX 500 ; N nine ; B 26 -13 473 688 ; -C 58 ; WX 333 ; N colon ; B 82 -13 251 472 ; -C 59 ; WX 333 ; N semicolon ; B 82 -180 266 472 ; -C 60 ; WX 570 ; N less ; B 31 -8 539 514 ; -C 61 ; WX 570 ; N equal ; B 33 107 537 399 ; -C 62 ; WX 570 ; N greater ; B 31 -8 539 514 ; -C 63 ; WX 500 ; N question ; B 57 -13 445 689 ; -C 64 ; WX 930 ; N at ; B 108 -19 822 691 ; -C 65 ; WX 722 ; N A ; B 9 0 689 690 ; -C 66 ; WX 667 ; N B ; B 16 0 619 676 ; -C 67 ; WX 722 ; N C ; B 49 -19 687 691 ; -C 68 ; WX 722 ; N D ; B 14 0 690 676 ; -C 69 ; WX 667 ; N E ; B 16 0 641 676 ; -C 70 ; WX 611 ; N F ; B 16 0 583 676 ; -C 71 ; WX 778 ; N G ; B 37 -19 755 691 ; -C 72 ; WX 778 ; N H ; B 21 0 759 676 ; -C 73 ; WX 389 ; N I ; B 20 0 370 676 ; -C 74 ; WX 500 ; N J ; B 3 -96 479 676 ; -C 75 ; WX 778 ; N K ; B 30 0 769 676 ; -C 76 ; WX 667 ; N L ; B 19 0 638 676 ; -C 77 ; WX 944 ; N M ; B 14 0 921 676 ; -C 78 ; WX 722 ; N N ; B 16 -18 701 676 ; -C 79 ; WX 778 ; N O ; B 35 -19 743 691 ; -C 80 ; WX 611 ; N P ; B 16 0 600 676 ; -C 81 ; WX 778 ; N Q ; B 35 -176 743 691 ; -C 82 ; WX 722 ; N R ; B 26 0 715 676 ; -C 83 ; WX 556 ; N S ; B 35 -19 513 692 ; -C 84 ; WX 667 ; N T ; B 31 0 636 676 ; -C 85 ; WX 722 ; N U ; B 16 -19 701 676 ; -C 86 ; WX 722 ; N V ; B 16 -18 701 676 ; -C 87 ; WX 1000 ; N W ; B 19 -15 981 676 ; -C 88 ; WX 722 ; N X ; B 16 0 699 676 ; -C 89 ; WX 722 ; N Y ; B 15 0 699 676 ; -C 90 ; WX 667 ; N Z ; B 28 0 634 676 ; -C 91 ; WX 333 ; N bracketleft ; B 67 -149 301 678 ; -C 92 ; WX 278 ; N backslash ; B -25 -19 303 691 ; -C 93 ; WX 333 ; N bracketright ; B 32 -149 266 678 ; -C 94 ; WX 581 ; N asciicircum ; B 73 311 509 676 ; -C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ; -C 96 ; WX 333 ; N quoteleft ; B 70 356 254 691 ; -C 97 ; WX 500 ; N a ; B 25 -14 488 473 ; -C 98 ; WX 556 ; N b ; B 17 -14 521 676 ; -C 99 ; WX 444 ; N c ; B 25 -14 430 473 ; -C 100 ; WX 556 ; N d ; B 25 -14 534 676 ; -C 101 ; WX 444 ; N e ; B 25 -14 426 473 ; -C 102 ; WX 333 ; N f ; B 14 0 389 691 ; L i fi ; L l fl ; -C 103 ; WX 500 ; N g ; B 28 -206 483 473 ; -C 104 ; WX 556 ; N h ; B 16 0 534 676 ; -C 105 ; WX 278 ; N i ; B 16 0 255 691 ; -C 106 ; WX 333 ; N j ; B -57 -203 263 691 ; -C 107 ; WX 556 ; N k ; B 22 0 543 676 ; -C 108 ; WX 278 ; N l ; B 16 0 255 676 ; -C 109 ; WX 833 ; N m ; B 16 0 814 473 ; -C 110 ; WX 556 ; N n ; B 21 0 539 473 ; -C 111 ; WX 500 ; N o ; B 25 -14 476 473 ; -C 112 ; WX 556 ; N p ; B 19 -205 524 473 ; -C 113 ; WX 556 ; N q ; B 34 -205 536 473 ; -C 114 ; WX 444 ; N r ; B 29 0 434 473 ; -C 115 ; WX 389 ; N s ; B 25 -14 361 473 ; -C 116 ; WX 333 ; N t ; B 20 -12 332 630 ; -C 117 ; WX 556 ; N u ; B 16 -14 537 461 ; -C 118 ; WX 500 ; N v ; B 21 -14 485 461 ; -C 119 ; WX 722 ; N w ; B 23 -14 707 461 ; -C 120 ; WX 500 ; N x ; B 12 0 484 461 ; -C 121 ; WX 500 ; N y ; B 16 -205 480 461 ; -C 122 ; WX 444 ; N z ; B 21 0 420 461 ; -C 123 ; WX 394 ; N braceleft ; B 22 -175 340 698 ; -C 124 ; WX 220 ; N bar ; B 66 -19 154 691 ; -C 125 ; WX 394 ; N braceright ; B 54 -175 372 698 ; -C 126 ; WX 520 ; N asciitilde ; B 29 173 491 333 ; -C 161 ; WX 333 ; N exclamdown ; B 82 -203 252 501 ; -C 162 ; WX 500 ; N cent ; B 53 -140 458 588 ; -C 163 ; WX 500 ; N sterling ; B 21 -14 477 684 ; -C 164 ; WX 167 ; N fraction ; B -168 -12 329 688 ; -C 165 ; WX 500 ; N yen ; B -64 0 547 676 ; -C 166 ; WX 500 ; N florin ; B 0 -155 498 706 ; -C 167 ; WX 500 ; N section ; B 57 -132 443 691 ; -C 168 ; WX 500 ; N currency ; B -26 61 526 613 ; -C 169 ; WX 278 ; N quotesingle ; B 75 404 204 691 ; -C 170 ; WX 500 ; N quotedblleft ; B 32 356 486 691 ; -C 171 ; WX 500 ; N guillemotleft ; B 23 36 473 415 ; -C 172 ; WX 333 ; N guilsinglleft ; B 51 36 305 415 ; -C 173 ; WX 333 ; N guilsinglright ; B 28 36 282 415 ; -C 174 ; WX 556 ; N fi ; B 14 0 536 691 ; -C 175 ; WX 556 ; N fl ; B 14 0 536 691 ; -C 177 ; WX 500 ; N endash ; B 0 181 500 271 ; -C 178 ; WX 500 ; N dagger ; B 47 -134 453 691 ; -C 179 ; WX 500 ; N daggerdbl ; B 45 -132 456 691 ; -C 180 ; WX 250 ; N periodcentered ; B 41 248 210 417 ; -C 182 ; WX 540 ; N paragraph ; B 0 -186 519 676 ; -C 183 ; WX 350 ; N bullet ; B 35 198 315 478 ; -C 184 ; WX 333 ; N quotesinglbase ; B 79 -180 263 155 ; -C 185 ; WX 500 ; N quotedblbase ; B 14 -180 468 155 ; -C 186 ; WX 500 ; N quotedblright ; B 14 356 468 691 ; -C 187 ; WX 500 ; N guillemotright ; B 27 36 477 415 ; -C 188 ; WX 1000 ; N ellipsis ; B 82 -13 917 156 ; -C 189 ; WX 1000 ; N perthousand ; B 7 -29 995 706 ; -C 191 ; WX 500 ; N questiondown ; B 55 -201 443 501 ; -C 193 ; WX 333 ; N grave ; B 8 528 246 713 ; -C 194 ; WX 333 ; N acute ; B 86 528 324 713 ; -C 195 ; WX 333 ; N circumflex ; B -2 528 335 704 ; -C 196 ; WX 333 ; N tilde ; B -16 547 349 674 ; -C 197 ; WX 333 ; N macron ; B 1 565 331 637 ; -C 198 ; WX 333 ; N breve ; B 15 528 318 691 ; -C 199 ; WX 333 ; N dotaccent ; B 103 537 230 667 ; -C 200 ; WX 333 ; N dieresis ; B -2 537 335 667 ; -C 202 ; WX 333 ; N ring ; B 60 527 273 740 ; -C 203 ; WX 333 ; N cedilla ; B 68 -218 294 0 ; -C 205 ; WX 333 ; N hungarumlaut ; B -13 528 425 713 ; -C 206 ; WX 333 ; N ogonek ; B 90 -173 319 44 ; -C 207 ; WX 333 ; N caron ; B -2 528 335 704 ; -C 208 ; WX 1000 ; N emdash ; B 0 181 1000 271 ; -C 225 ; WX 1000 ; N AE ; B 4 0 951 676 ; -C 227 ; WX 300 ; N ordfeminine ; B -1 397 301 688 ; -C 232 ; WX 667 ; N Lslash ; B 19 0 638 676 ; -C 233 ; WX 778 ; N Oslash ; B 35 -74 743 737 ; -C 234 ; WX 1000 ; N OE ; B 22 -5 981 684 ; -C 235 ; WX 330 ; N ordmasculine ; B 18 397 312 688 ; -C 241 ; WX 722 ; N ae ; B 33 -14 693 473 ; -C 245 ; WX 278 ; N dotlessi ; B 16 0 255 461 ; -C 248 ; WX 278 ; N lslash ; B -22 0 303 676 ; -C 249 ; WX 500 ; N oslash ; B 25 -92 476 549 ; -C 250 ; WX 722 ; N oe ; B 22 -14 696 473 ; -C 251 ; WX 556 ; N germandbls ; B 19 -12 517 691 ; -C -1 ; WX 667 ; N Zcaron ; B 28 0 634 914 ; -C -1 ; WX 444 ; N ccedilla ; B 25 -218 430 473 ; -C -1 ; WX 500 ; N ydieresis ; B 16 -205 480 667 ; -C -1 ; WX 500 ; N atilde ; B 25 -14 488 674 ; -C -1 ; WX 278 ; N icircumflex ; B -36 0 301 704 ; -C -1 ; WX 300 ; N threesuperior ; B 3 268 297 688 ; -C -1 ; WX 444 ; N ecircumflex ; B 25 -14 426 704 ; -C -1 ; WX 556 ; N thorn ; B 19 -205 524 676 ; -C -1 ; WX 444 ; N egrave ; B 25 -14 426 713 ; -C -1 ; WX 300 ; N twosuperior ; B 0 275 300 688 ; -C -1 ; WX 444 ; N eacute ; B 25 -14 426 713 ; -C -1 ; WX 500 ; N otilde ; B 25 -14 476 674 ; -C -1 ; WX 722 ; N Aacute ; B 9 0 689 923 ; -C -1 ; WX 500 ; N ocircumflex ; B 25 -14 476 704 ; -C -1 ; WX 500 ; N yacute ; B 16 -205 480 713 ; -C -1 ; WX 556 ; N udieresis ; B 16 -14 537 667 ; -C -1 ; WX 750 ; N threequarters ; B 23 -12 733 688 ; -C -1 ; WX 500 ; N acircumflex ; B 25 -14 488 704 ; -C -1 ; WX 722 ; N Eth ; B 6 0 690 676 ; -C -1 ; WX 444 ; N edieresis ; B 25 -14 426 667 ; -C -1 ; WX 556 ; N ugrave ; B 16 -14 537 713 ; -C -1 ; WX 1000 ; N trademark ; B 24 271 977 676 ; -C -1 ; WX 500 ; N ograve ; B 25 -14 476 713 ; -C -1 ; WX 389 ; N scaron ; B 25 -14 363 704 ; -C -1 ; WX 389 ; N Idieresis ; B 20 0 370 877 ; -C -1 ; WX 556 ; N uacute ; B 16 -14 537 713 ; -C -1 ; WX 500 ; N agrave ; B 25 -14 488 713 ; -C -1 ; WX 556 ; N ntilde ; B 21 0 539 674 ; -C -1 ; WX 500 ; N aring ; B 25 -14 488 740 ; -C -1 ; WX 444 ; N zcaron ; B 21 0 420 704 ; -C -1 ; WX 389 ; N Icircumflex ; B 20 0 370 914 ; -C -1 ; WX 722 ; N Ntilde ; B 16 -18 701 884 ; -C -1 ; WX 556 ; N ucircumflex ; B 16 -14 537 704 ; -C -1 ; WX 667 ; N Ecircumflex ; B 16 0 641 914 ; -C -1 ; WX 389 ; N Iacute ; B 20 0 370 923 ; -C -1 ; WX 722 ; N Ccedilla ; B 49 -218 687 691 ; -C -1 ; WX 778 ; N Odieresis ; B 35 -19 743 877 ; -C -1 ; WX 556 ; N Scaron ; B 35 -19 513 914 ; -C -1 ; WX 667 ; N Edieresis ; B 16 0 641 877 ; -C -1 ; WX 389 ; N Igrave ; B 20 0 370 923 ; -C -1 ; WX 500 ; N adieresis ; B 25 -14 488 667 ; -C -1 ; WX 778 ; N Ograve ; B 35 -19 743 923 ; -C -1 ; WX 667 ; N Egrave ; B 16 0 641 923 ; -C -1 ; WX 722 ; N Ydieresis ; B 15 0 699 877 ; -C -1 ; WX 747 ; N registered ; B 26 -19 721 691 ; -C -1 ; WX 778 ; N Otilde ; B 35 -19 743 884 ; -C -1 ; WX 750 ; N onequarter ; B 28 -12 743 688 ; -C -1 ; WX 722 ; N Ugrave ; B 16 -19 701 923 ; -C -1 ; WX 722 ; N Ucircumflex ; B 16 -19 701 914 ; -C -1 ; WX 611 ; N Thorn ; B 16 0 600 676 ; -C -1 ; WX 570 ; N divide ; B 33 -31 537 537 ; -C -1 ; WX 722 ; N Atilde ; B 9 0 689 884 ; -C -1 ; WX 722 ; N Uacute ; B 16 -19 701 923 ; -C -1 ; WX 778 ; N Ocircumflex ; B 35 -19 743 914 ; -C -1 ; WX 570 ; N logicalnot ; B 33 108 537 399 ; -C -1 ; WX 722 ; N Aring ; B 9 0 689 935 ; -C -1 ; WX 278 ; N idieresis ; B -36 0 301 667 ; -C -1 ; WX 278 ; N iacute ; B 16 0 290 713 ; -C -1 ; WX 500 ; N aacute ; B 25 -14 488 713 ; -C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ; -C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ; -C -1 ; WX 722 ; N Udieresis ; B 16 -19 701 877 ; -C -1 ; WX 570 ; N minus ; B 33 209 537 297 ; -C -1 ; WX 300 ; N onesuperior ; B 28 275 273 688 ; -C -1 ; WX 667 ; N Eacute ; B 16 0 641 923 ; -C -1 ; WX 722 ; N Acircumflex ; B 9 0 689 914 ; -C -1 ; WX 747 ; N copyright ; B 26 -19 721 691 ; -C -1 ; WX 722 ; N Agrave ; B 9 0 689 923 ; -C -1 ; WX 500 ; N odieresis ; B 25 -14 476 667 ; -C -1 ; WX 500 ; N oacute ; B 25 -14 476 713 ; -C -1 ; WX 400 ; N degree ; B 57 402 343 688 ; -C -1 ; WX 278 ; N igrave ; B -26 0 255 713 ; -C -1 ; WX 556 ; N mu ; B 33 -206 536 461 ; -C -1 ; WX 778 ; N Oacute ; B 35 -19 743 923 ; -C -1 ; WX 500 ; N eth ; B 25 -14 476 691 ; -C -1 ; WX 722 ; N Adieresis ; B 9 0 689 877 ; -C -1 ; WX 722 ; N Yacute ; B 15 0 699 928 ; -C -1 ; WX 220 ; N brokenbar ; B 66 -19 154 691 ; -C -1 ; WX 750 ; N onehalf ; B -7 -12 775 688 ; -EndCharMetrics -StartKernData -StartKernPairs 283 - -KPX A y -74 -KPX A w -90 -KPX A v -100 -KPX A u -50 -KPX A quoteright -74 -KPX A quotedblright 0 -KPX A p -25 -KPX A Y -100 -KPX A W -130 -KPX A V -145 -KPX A U -50 -KPX A T -95 -KPX A Q -45 -KPX A O -45 -KPX A G -55 -KPX A C -55 - -KPX B period 0 -KPX B comma 0 -KPX B U -10 -KPX B A -30 - -KPX D period -20 -KPX D comma 0 -KPX D Y -40 -KPX D W -40 -KPX D V -40 -KPX D A -35 - -KPX F r 0 -KPX F period -110 -KPX F o -25 -KPX F i 0 -KPX F e -25 -KPX F comma -92 -KPX F a -25 -KPX F A -90 - -KPX G period 0 -KPX G comma 0 - -KPX J u -15 -KPX J period -20 -KPX J o -15 -KPX J e -15 -KPX J comma 0 -KPX J a -15 -KPX J A -30 - -KPX K y -45 -KPX K u -15 -KPX K o -25 -KPX K e -25 -KPX K O -30 - -KPX L y -55 -KPX L quoteright -110 -KPX L quotedblright -20 -KPX L Y -92 -KPX L W -92 -KPX L V -92 -KPX L T -92 - -KPX N period 0 -KPX N comma 0 -KPX N A -20 - -KPX O period 0 -KPX O comma 0 -KPX O Y -50 -KPX O X -40 -KPX O W -50 -KPX O V -50 -KPX O T -40 -KPX O A -40 - -KPX P period -110 -KPX P o -20 -KPX P e -20 -KPX P comma -92 -KPX P a -10 -KPX P A -74 - -KPX Q period -20 -KPX Q comma 0 -KPX Q U -10 - -KPX R Y -35 -KPX R W -35 -KPX R V -55 -KPX R U -30 -KPX R T -40 -KPX R O -30 - -KPX S period 0 -KPX S comma 0 - -KPX T y -74 -KPX T w -74 -KPX T u -92 -KPX T semicolon -74 -KPX T r -74 -KPX T period -90 -KPX T o -92 -KPX T i -18 -KPX T hyphen -92 -KPX T h 0 -KPX T e -92 -KPX T comma -74 -KPX T colon -74 -KPX T a -92 -KPX T O -18 -KPX T A -90 - -KPX U period -50 -KPX U comma -50 -KPX U A -60 - -KPX V u -92 -KPX V semicolon -92 -KPX V period -145 -KPX V o -100 -KPX V i -37 -KPX V hyphen -74 -KPX V e -100 -KPX V comma -129 -KPX V colon -92 -KPX V a -92 -KPX V O -45 -KPX V G -30 -KPX V A -135 - -KPX W y -60 -KPX W u -50 -KPX W semicolon -55 -KPX W period -92 -KPX W o -75 -KPX W i -18 -KPX W hyphen -37 -KPX W h 0 -KPX W e -65 -KPX W comma -92 -KPX W colon -55 -KPX W a -65 -KPX W O -10 -KPX W A -120 - -KPX Y u -92 -KPX Y semicolon -92 -KPX Y period -92 -KPX Y o -111 -KPX Y i -37 -KPX Y hyphen -92 -KPX Y e -111 -KPX Y comma -92 -KPX Y colon -92 -KPX Y a -85 -KPX Y O -35 -KPX Y A -110 - -KPX a y 0 -KPX a w 0 -KPX a v -25 -KPX a t 0 -KPX a p 0 -KPX a g 0 -KPX a b 0 - -KPX b y 0 -KPX b v -15 -KPX b u -20 -KPX b period -40 -KPX b l 0 -KPX b comma 0 -KPX b b -10 - -KPX c y 0 -KPX c period 0 -KPX c l 0 -KPX c k 0 -KPX c h 0 -KPX c comma 0 - -KPX colon space 0 - -KPX comma space 0 -KPX comma quoteright -55 -KPX comma quotedblright -45 - -KPX d y 0 -KPX d w -15 -KPX d v 0 -KPX d period 0 -KPX d d 0 -KPX d comma 0 - -KPX e y 0 -KPX e x 0 -KPX e w 0 -KPX e v -15 -KPX e period 0 -KPX e p 0 -KPX e g 0 -KPX e comma 0 -KPX e b 0 - -KPX f quoteright 55 -KPX f quotedblright 50 -KPX f period -15 -KPX f o -25 -KPX f l 0 -KPX f i -25 -KPX f f 0 -KPX f e 0 -KPX f dotlessi -35 -KPX f comma -15 -KPX f a 0 - -KPX g y 0 -KPX g r 0 -KPX g period -15 -KPX g o 0 -KPX g i 0 -KPX g g 0 -KPX g e 0 -KPX g comma 0 -KPX g a 0 - -KPX h y -15 - -KPX i v -10 - -KPX k y -15 -KPX k o -15 -KPX k e -10 - -KPX l y 0 -KPX l w 0 - -KPX m y 0 -KPX m u 0 - -KPX n y 0 -KPX n v -40 -KPX n u 0 - -KPX o y 0 -KPX o x 0 -KPX o w -10 -KPX o v -10 -KPX o g 0 - -KPX p y 0 - -KPX period quoteright -55 -KPX period quotedblright -55 - -KPX quotedblleft quoteleft 0 -KPX quotedblleft A -10 - -KPX quotedblright space 0 - -KPX quoteleft quoteleft -63 -KPX quoteleft A -10 - -KPX quoteright v -20 -KPX quoteright t 0 -KPX quoteright space -74 -KPX quoteright s -37 -KPX quoteright r -20 -KPX quoteright quoteright -63 -KPX quoteright quotedblright 0 -KPX quoteright l 0 -KPX quoteright d -20 - -KPX r y 0 -KPX r v -10 -KPX r u 0 -KPX r t 0 -KPX r s 0 -KPX r r 0 -KPX r q -18 -KPX r period -100 -KPX r p -10 -KPX r o -18 -KPX r n -15 -KPX r m 0 -KPX r l 0 -KPX r k 0 -KPX r i 0 -KPX r hyphen -37 -KPX r g -10 -KPX r e -18 -KPX r d 0 -KPX r comma -92 -KPX r c -18 -KPX r a 0 - -KPX s w 0 - -KPX space quoteleft 0 -KPX space quotedblleft 0 -KPX space Y -55 -KPX space W -30 -KPX space V -45 -KPX space T -30 -KPX space A -55 - -KPX v period -70 -KPX v o -10 -KPX v e -10 -KPX v comma -55 -KPX v a -10 - -KPX w period -70 -KPX w o -10 -KPX w h 0 -KPX w e 0 -KPX w comma -55 -KPX w a 0 - -KPX x e 0 - -KPX y period -70 -KPX y o -25 -KPX y e -10 -KPX y comma -55 -KPX y a 0 - -KPX z o 0 -KPX z e 0 -EndKernPairs -EndKernData -StartComposites 58 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 188 210 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 188 210 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 188 210 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave 188 210 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring 180 195 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde 188 210 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 208 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 174 210 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 174 210 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 174 210 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 174 210 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute 28 210 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 28 210 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 28 210 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave 28 210 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 195 210 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 223 210 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 223 210 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 223 210 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 223 210 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 223 210 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 112 210 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 222 210 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 222 210 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 222 210 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave 222 210 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 210 215 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 215 210 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 167 210 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 77 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 77 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 77 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave 77 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 77 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 77 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 69 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 62 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 62 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 62 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 62 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -34 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -34 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -34 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -34 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 112 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 28 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute 105 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 105 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 105 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave 105 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute 84 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 56 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Times-BoldItalic.afm b/config/psfonts/Times-BoldItalic.afm deleted file mode 100644 index 25ab54ea..00000000 --- a/config/psfonts/Times-BoldItalic.afm +++ /dev/null @@ -1,648 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved. -Comment Creation Date: Tue Mar 20 13:14:55 1990 -Comment UniqueID 28425 -Comment VMusage 32721 39613 -FontName Times-BoldItalic -FullName Times Bold Italic -FamilyName Times -Weight Bold -ItalicAngle -15 -IsFixedPitch false -FontBBox -200 -218 996 921 -UnderlinePosition -100 -UnderlineThickness 50 -Version 001.009 -Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype AG and/or its subsidiaries. -EncodingScheme AdobeStandardEncoding -CapHeight 669 -XHeight 462 -Ascender 699 -Descender -205 -StartCharMetrics 228 -C 32 ; WX 250 ; N space ; B 0 0 0 0 ; -C 33 ; WX 389 ; N exclam ; B 67 -13 370 684 ; -C 34 ; WX 555 ; N quotedbl ; B 136 398 536 685 ; -C 35 ; WX 500 ; N numbersign ; B -33 0 533 700 ; -C 36 ; WX 500 ; N dollar ; B -20 -100 497 733 ; -C 37 ; WX 833 ; N percent ; B 39 -10 793 692 ; -C 38 ; WX 778 ; N ampersand ; B 5 -19 699 682 ; -C 39 ; WX 333 ; N quoteright ; B 98 369 302 685 ; -C 40 ; WX 333 ; N parenleft ; B 28 -179 344 685 ; -C 41 ; WX 333 ; N parenright ; B -44 -179 271 685 ; -C 42 ; WX 500 ; N asterisk ; B 65 249 456 685 ; -C 43 ; WX 570 ; N plus ; B 33 0 537 506 ; -C 44 ; WX 250 ; N comma ; B -60 -182 144 134 ; -C 45 ; WX 333 ; N hyphen ; B 2 166 271 282 ; -C 46 ; WX 250 ; N period ; B -9 -13 139 135 ; -C 47 ; WX 278 ; N slash ; B -64 -18 342 685 ; -C 48 ; WX 500 ; N zero ; B 17 -14 477 683 ; -C 49 ; WX 500 ; N one ; B 5 0 419 683 ; -C 50 ; WX 500 ; N two ; B -27 0 446 683 ; -C 51 ; WX 500 ; N three ; B -15 -13 450 683 ; -C 52 ; WX 500 ; N four ; B -15 0 503 683 ; -C 53 ; WX 500 ; N five ; B -11 -13 487 669 ; -C 54 ; WX 500 ; N six ; B 23 -15 509 679 ; -C 55 ; WX 500 ; N seven ; B 52 0 525 669 ; -C 56 ; WX 500 ; N eight ; B 3 -13 476 683 ; -C 57 ; WX 500 ; N nine ; B -12 -10 475 683 ; -C 58 ; WX 333 ; N colon ; B 23 -13 264 459 ; -C 59 ; WX 333 ; N semicolon ; B -25 -183 264 459 ; -C 60 ; WX 570 ; N less ; B 31 -8 539 514 ; -C 61 ; WX 570 ; N equal ; B 33 107 537 399 ; -C 62 ; WX 570 ; N greater ; B 31 -8 539 514 ; -C 63 ; WX 500 ; N question ; B 79 -13 470 684 ; -C 64 ; WX 832 ; N at ; B 63 -18 770 685 ; -C 65 ; WX 667 ; N A ; B -67 0 593 683 ; -C 66 ; WX 667 ; N B ; B -24 0 624 669 ; -C 67 ; WX 667 ; N C ; B 32 -18 677 685 ; -C 68 ; WX 722 ; N D ; B -46 0 685 669 ; -C 69 ; WX 667 ; N E ; B -27 0 653 669 ; -C 70 ; WX 667 ; N F ; B -13 0 660 669 ; -C 71 ; WX 722 ; N G ; B 21 -18 706 685 ; -C 72 ; WX 778 ; N H ; B -24 0 799 669 ; -C 73 ; WX 389 ; N I ; B -32 0 406 669 ; -C 74 ; WX 500 ; N J ; B -46 -99 524 669 ; -C 75 ; WX 667 ; N K ; B -21 0 702 669 ; -C 76 ; WX 611 ; N L ; B -22 0 590 669 ; -C 77 ; WX 889 ; N M ; B -29 -12 917 669 ; -C 78 ; WX 722 ; N N ; B -27 -15 748 669 ; -C 79 ; WX 722 ; N O ; B 27 -18 691 685 ; -C 80 ; WX 611 ; N P ; B -27 0 613 669 ; -C 81 ; WX 722 ; N Q ; B 27 -208 691 685 ; -C 82 ; WX 667 ; N R ; B -29 0 623 669 ; -C 83 ; WX 556 ; N S ; B 2 -18 526 685 ; -C 84 ; WX 611 ; N T ; B 50 0 650 669 ; -C 85 ; WX 722 ; N U ; B 67 -18 744 669 ; -C 86 ; WX 667 ; N V ; B 65 -18 715 669 ; -C 87 ; WX 889 ; N W ; B 65 -18 940 669 ; -C 88 ; WX 667 ; N X ; B -24 0 694 669 ; -C 89 ; WX 611 ; N Y ; B 73 0 659 669 ; -C 90 ; WX 611 ; N Z ; B -11 0 590 669 ; -C 91 ; WX 333 ; N bracketleft ; B -37 -159 362 674 ; -C 92 ; WX 278 ; N backslash ; B -1 -18 279 685 ; -C 93 ; WX 333 ; N bracketright ; B -56 -157 343 674 ; -C 94 ; WX 570 ; N asciicircum ; B 67 304 503 669 ; -C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ; -C 96 ; WX 333 ; N quoteleft ; B 128 369 332 685 ; -C 97 ; WX 500 ; N a ; B -21 -14 455 462 ; -C 98 ; WX 500 ; N b ; B -14 -13 444 699 ; -C 99 ; WX 444 ; N c ; B -5 -13 392 462 ; -C 100 ; WX 500 ; N d ; B -21 -13 517 699 ; -C 101 ; WX 444 ; N e ; B 5 -13 398 462 ; -C 102 ; WX 333 ; N f ; B -169 -205 446 698 ; L i fi ; L l fl ; -C 103 ; WX 500 ; N g ; B -52 -203 478 462 ; -C 104 ; WX 556 ; N h ; B -13 -9 498 699 ; -C 105 ; WX 278 ; N i ; B 2 -9 263 684 ; -C 106 ; WX 278 ; N j ; B -189 -207 279 684 ; -C 107 ; WX 500 ; N k ; B -23 -8 483 699 ; -C 108 ; WX 278 ; N l ; B 2 -9 290 699 ; -C 109 ; WX 778 ; N m ; B -14 -9 722 462 ; -C 110 ; WX 556 ; N n ; B -6 -9 493 462 ; -C 111 ; WX 500 ; N o ; B -3 -13 441 462 ; -C 112 ; WX 500 ; N p ; B -120 -205 446 462 ; -C 113 ; WX 500 ; N q ; B 1 -205 471 462 ; -C 114 ; WX 389 ; N r ; B -21 0 389 462 ; -C 115 ; WX 389 ; N s ; B -19 -13 333 462 ; -C 116 ; WX 278 ; N t ; B -11 -9 281 594 ; -C 117 ; WX 556 ; N u ; B 15 -9 492 462 ; -C 118 ; WX 444 ; N v ; B 16 -13 401 462 ; -C 119 ; WX 667 ; N w ; B 16 -13 614 462 ; -C 120 ; WX 500 ; N x ; B -46 -13 469 462 ; -C 121 ; WX 444 ; N y ; B -94 -205 392 462 ; -C 122 ; WX 389 ; N z ; B -43 -78 368 449 ; -C 123 ; WX 348 ; N braceleft ; B 5 -187 436 686 ; -C 124 ; WX 220 ; N bar ; B 66 -18 154 685 ; -C 125 ; WX 348 ; N braceright ; B -129 -187 302 686 ; -C 126 ; WX 570 ; N asciitilde ; B 54 173 516 333 ; -C 161 ; WX 389 ; N exclamdown ; B 19 -205 322 492 ; -C 162 ; WX 500 ; N cent ; B 42 -143 439 576 ; -C 163 ; WX 500 ; N sterling ; B -32 -12 510 683 ; -C 164 ; WX 167 ; N fraction ; B -169 -14 324 683 ; -C 165 ; WX 500 ; N yen ; B 33 0 628 669 ; -C 166 ; WX 500 ; N florin ; B -87 -156 537 707 ; -C 167 ; WX 500 ; N section ; B 36 -143 459 685 ; -C 168 ; WX 500 ; N currency ; B -26 34 526 586 ; -C 169 ; WX 278 ; N quotesingle ; B 128 398 268 685 ; -C 170 ; WX 500 ; N quotedblleft ; B 53 369 513 685 ; -C 171 ; WX 500 ; N guillemotleft ; B 12 32 468 415 ; -C 172 ; WX 333 ; N guilsinglleft ; B 32 32 303 415 ; -C 173 ; WX 333 ; N guilsinglright ; B 10 32 281 415 ; -C 174 ; WX 556 ; N fi ; B -188 -205 514 703 ; -C 175 ; WX 556 ; N fl ; B -186 -205 553 704 ; -C 177 ; WX 500 ; N endash ; B -40 178 477 269 ; -C 178 ; WX 500 ; N dagger ; B 91 -145 494 685 ; -C 179 ; WX 500 ; N daggerdbl ; B 10 -139 493 685 ; -C 180 ; WX 250 ; N periodcentered ; B 51 257 199 405 ; -C 182 ; WX 500 ; N paragraph ; B -57 -193 562 669 ; -C 183 ; WX 350 ; N bullet ; B 0 175 350 525 ; -C 184 ; WX 333 ; N quotesinglbase ; B -5 -182 199 134 ; -C 185 ; WX 500 ; N quotedblbase ; B -57 -182 403 134 ; -C 186 ; WX 500 ; N quotedblright ; B 53 369 513 685 ; -C 187 ; WX 500 ; N guillemotright ; B 12 32 468 415 ; -C 188 ; WX 1000 ; N ellipsis ; B 40 -13 852 135 ; -C 189 ; WX 1000 ; N perthousand ; B 7 -29 996 706 ; -C 191 ; WX 500 ; N questiondown ; B 30 -205 421 492 ; -C 193 ; WX 333 ; N grave ; B 85 516 297 697 ; -C 194 ; WX 333 ; N acute ; B 139 516 379 697 ; -C 195 ; WX 333 ; N circumflex ; B 40 516 367 690 ; -C 196 ; WX 333 ; N tilde ; B 48 536 407 655 ; -C 197 ; WX 333 ; N macron ; B 51 553 393 623 ; -C 198 ; WX 333 ; N breve ; B 71 516 387 678 ; -C 199 ; WX 333 ; N dotaccent ; B 163 525 293 655 ; -C 200 ; WX 333 ; N dieresis ; B 55 525 397 655 ; -C 202 ; WX 333 ; N ring ; B 127 516 340 729 ; -C 203 ; WX 333 ; N cedilla ; B -80 -218 156 5 ; -C 205 ; WX 333 ; N hungarumlaut ; B 69 516 498 697 ; -C 206 ; WX 333 ; N ogonek ; B -40 -173 189 44 ; -C 207 ; WX 333 ; N caron ; B 79 516 411 690 ; -C 208 ; WX 1000 ; N emdash ; B -40 178 977 269 ; -C 225 ; WX 944 ; N AE ; B -64 0 918 669 ; -C 227 ; WX 266 ; N ordfeminine ; B 16 399 330 685 ; -C 232 ; WX 611 ; N Lslash ; B -22 0 590 669 ; -C 233 ; WX 722 ; N Oslash ; B 27 -125 691 764 ; -C 234 ; WX 944 ; N OE ; B 23 -8 946 677 ; -C 235 ; WX 300 ; N ordmasculine ; B 56 400 347 685 ; -C 241 ; WX 722 ; N ae ; B -5 -13 673 462 ; -C 245 ; WX 278 ; N dotlessi ; B 2 -9 238 462 ; -C 248 ; WX 278 ; N lslash ; B -13 -9 301 699 ; -C 249 ; WX 500 ; N oslash ; B -3 -119 441 560 ; -C 250 ; WX 722 ; N oe ; B 6 -13 674 462 ; -C 251 ; WX 500 ; N germandbls ; B -200 -200 473 705 ; -C -1 ; WX 611 ; N Zcaron ; B -11 0 590 897 ; -C -1 ; WX 444 ; N ccedilla ; B -24 -218 392 462 ; -C -1 ; WX 444 ; N ydieresis ; B -94 -205 438 655 ; -C -1 ; WX 500 ; N atilde ; B -21 -14 491 655 ; -C -1 ; WX 278 ; N icircumflex ; B -2 -9 325 690 ; -C -1 ; WX 300 ; N threesuperior ; B 17 265 321 683 ; -C -1 ; WX 444 ; N ecircumflex ; B 5 -13 423 690 ; -C -1 ; WX 500 ; N thorn ; B -120 -205 446 699 ; -C -1 ; WX 444 ; N egrave ; B 5 -13 398 697 ; -C -1 ; WX 300 ; N twosuperior ; B 2 274 313 683 ; -C -1 ; WX 444 ; N eacute ; B 5 -13 435 697 ; -C -1 ; WX 500 ; N otilde ; B -3 -13 491 655 ; -C -1 ; WX 667 ; N Aacute ; B -67 0 593 904 ; -C -1 ; WX 500 ; N ocircumflex ; B -3 -13 451 690 ; -C -1 ; WX 444 ; N yacute ; B -94 -205 435 697 ; -C -1 ; WX 556 ; N udieresis ; B 15 -9 494 655 ; -C -1 ; WX 750 ; N threequarters ; B 7 -14 726 683 ; -C -1 ; WX 500 ; N acircumflex ; B -21 -14 455 690 ; -C -1 ; WX 722 ; N Eth ; B -31 0 700 669 ; -C -1 ; WX 444 ; N edieresis ; B 5 -13 443 655 ; -C -1 ; WX 556 ; N ugrave ; B 15 -9 492 697 ; -C -1 ; WX 1000 ; N trademark ; B 32 263 968 669 ; -C -1 ; WX 500 ; N ograve ; B -3 -13 441 697 ; -C -1 ; WX 389 ; N scaron ; B -19 -13 439 690 ; -C -1 ; WX 389 ; N Idieresis ; B -32 0 445 862 ; -C -1 ; WX 556 ; N uacute ; B 15 -9 492 697 ; -C -1 ; WX 500 ; N agrave ; B -21 -14 455 697 ; -C -1 ; WX 556 ; N ntilde ; B -6 -9 504 655 ; -C -1 ; WX 500 ; N aring ; B -21 -14 455 729 ; -C -1 ; WX 389 ; N zcaron ; B -43 -78 424 690 ; -C -1 ; WX 389 ; N Icircumflex ; B -32 0 420 897 ; -C -1 ; WX 722 ; N Ntilde ; B -27 -15 748 862 ; -C -1 ; WX 556 ; N ucircumflex ; B 15 -9 492 690 ; -C -1 ; WX 667 ; N Ecircumflex ; B -27 0 653 897 ; -C -1 ; WX 389 ; N Iacute ; B -32 0 412 904 ; -C -1 ; WX 667 ; N Ccedilla ; B 32 -218 677 685 ; -C -1 ; WX 722 ; N Odieresis ; B 27 -18 691 862 ; -C -1 ; WX 556 ; N Scaron ; B 2 -18 526 897 ; -C -1 ; WX 667 ; N Edieresis ; B -27 0 653 862 ; -C -1 ; WX 389 ; N Igrave ; B -32 0 406 904 ; -C -1 ; WX 500 ; N adieresis ; B -21 -14 471 655 ; -C -1 ; WX 722 ; N Ograve ; B 27 -18 691 904 ; -C -1 ; WX 667 ; N Egrave ; B -27 0 653 904 ; -C -1 ; WX 611 ; N Ydieresis ; B 73 0 659 862 ; -C -1 ; WX 747 ; N registered ; B 30 -18 718 685 ; -C -1 ; WX 722 ; N Otilde ; B 27 -18 691 862 ; -C -1 ; WX 750 ; N onequarter ; B 7 -14 721 683 ; -C -1 ; WX 722 ; N Ugrave ; B 67 -18 744 904 ; -C -1 ; WX 722 ; N Ucircumflex ; B 67 -18 744 897 ; -C -1 ; WX 611 ; N Thorn ; B -27 0 573 669 ; -C -1 ; WX 570 ; N divide ; B 33 -29 537 535 ; -C -1 ; WX 667 ; N Atilde ; B -67 0 593 862 ; -C -1 ; WX 722 ; N Uacute ; B 67 -18 744 904 ; -C -1 ; WX 722 ; N Ocircumflex ; B 27 -18 691 897 ; -C -1 ; WX 606 ; N logicalnot ; B 51 108 555 399 ; -C -1 ; WX 667 ; N Aring ; B -67 0 593 921 ; -C -1 ; WX 278 ; N idieresis ; B 2 -9 360 655 ; -C -1 ; WX 278 ; N iacute ; B 2 -9 352 697 ; -C -1 ; WX 500 ; N aacute ; B -21 -14 463 697 ; -C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ; -C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ; -C -1 ; WX 722 ; N Udieresis ; B 67 -18 744 862 ; -C -1 ; WX 606 ; N minus ; B 51 209 555 297 ; -C -1 ; WX 300 ; N onesuperior ; B 30 274 301 683 ; -C -1 ; WX 667 ; N Eacute ; B -27 0 653 904 ; -C -1 ; WX 667 ; N Acircumflex ; B -67 0 593 897 ; -C -1 ; WX 747 ; N copyright ; B 30 -18 718 685 ; -C -1 ; WX 667 ; N Agrave ; B -67 0 593 904 ; -C -1 ; WX 500 ; N odieresis ; B -3 -13 466 655 ; -C -1 ; WX 500 ; N oacute ; B -3 -13 463 697 ; -C -1 ; WX 400 ; N degree ; B 83 397 369 683 ; -C -1 ; WX 278 ; N igrave ; B 2 -9 260 697 ; -C -1 ; WX 576 ; N mu ; B -60 -207 516 449 ; -C -1 ; WX 722 ; N Oacute ; B 27 -18 691 904 ; -C -1 ; WX 500 ; N eth ; B -3 -13 454 699 ; -C -1 ; WX 667 ; N Adieresis ; B -67 0 593 862 ; -C -1 ; WX 611 ; N Yacute ; B 73 0 659 904 ; -C -1 ; WX 220 ; N brokenbar ; B 66 -18 154 685 ; -C -1 ; WX 750 ; N onehalf ; B -9 -14 723 683 ; -EndCharMetrics -StartKernData -StartKernPairs 283 - -KPX A y -74 -KPX A w -74 -KPX A v -74 -KPX A u -30 -KPX A quoteright -74 -KPX A quotedblright 0 -KPX A p 0 -KPX A Y -70 -KPX A W -100 -KPX A V -95 -KPX A U -50 -KPX A T -55 -KPX A Q -55 -KPX A O -50 -KPX A G -60 -KPX A C -65 - -KPX B period 0 -KPX B comma 0 -KPX B U -10 -KPX B A -25 - -KPX D period 0 -KPX D comma 0 -KPX D Y -50 -KPX D W -40 -KPX D V -50 -KPX D A -25 - -KPX F r -50 -KPX F period -129 -KPX F o -70 -KPX F i -40 -KPX F e -100 -KPX F comma -129 -KPX F a -95 -KPX F A -100 - -KPX G period 0 -KPX G comma 0 - -KPX J u -40 -KPX J period -10 -KPX J o -40 -KPX J e -40 -KPX J comma -10 -KPX J a -40 -KPX J A -25 - -KPX K y -20 -KPX K u -20 -KPX K o -25 -KPX K e -25 -KPX K O -30 - -KPX L y -37 -KPX L quoteright -55 -KPX L quotedblright 0 -KPX L Y -37 -KPX L W -37 -KPX L V -37 -KPX L T -18 - -KPX N period 0 -KPX N comma 0 -KPX N A -30 - -KPX O period 0 -KPX O comma 0 -KPX O Y -50 -KPX O X -40 -KPX O W -50 -KPX O V -50 -KPX O T -40 -KPX O A -40 - -KPX P period -129 -KPX P o -55 -KPX P e -50 -KPX P comma -129 -KPX P a -40 -KPX P A -85 - -KPX Q period 0 -KPX Q comma 0 -KPX Q U -10 - -KPX R Y -18 -KPX R W -18 -KPX R V -18 -KPX R U -40 -KPX R T -30 -KPX R O -40 - -KPX S period 0 -KPX S comma 0 - -KPX T y -37 -KPX T w -37 -KPX T u -37 -KPX T semicolon -74 -KPX T r -37 -KPX T period -92 -KPX T o -95 -KPX T i -37 -KPX T hyphen -92 -KPX T h 0 -KPX T e -92 -KPX T comma -92 -KPX T colon -74 -KPX T a -92 -KPX T O -18 -KPX T A -55 - -KPX U period 0 -KPX U comma 0 -KPX U A -45 - -KPX V u -55 -KPX V semicolon -74 -KPX V period -129 -KPX V o -111 -KPX V i -55 -KPX V hyphen -70 -KPX V e -111 -KPX V comma -129 -KPX V colon -74 -KPX V a -111 -KPX V O -30 -KPX V G -10 -KPX V A -85 - -KPX W y -55 -KPX W u -55 -KPX W semicolon -55 -KPX W period -74 -KPX W o -80 -KPX W i -37 -KPX W hyphen -50 -KPX W h 0 -KPX W e -90 -KPX W comma -74 -KPX W colon -55 -KPX W a -85 -KPX W O -15 -KPX W A -74 - -KPX Y u -92 -KPX Y semicolon -92 -KPX Y period -74 -KPX Y o -111 -KPX Y i -55 -KPX Y hyphen -92 -KPX Y e -111 -KPX Y comma -92 -KPX Y colon -92 -KPX Y a -92 -KPX Y O -25 -KPX Y A -74 - -KPX a y 0 -KPX a w 0 -KPX a v 0 -KPX a t 0 -KPX a p 0 -KPX a g 0 -KPX a b 0 - -KPX b y 0 -KPX b v 0 -KPX b u -20 -KPX b period -40 -KPX b l 0 -KPX b comma 0 -KPX b b -10 - -KPX c y 0 -KPX c period 0 -KPX c l 0 -KPX c k -10 -KPX c h -10 -KPX c comma 0 - -KPX colon space 0 - -KPX comma space 0 -KPX comma quoteright -95 -KPX comma quotedblright -95 - -KPX d y 0 -KPX d w 0 -KPX d v 0 -KPX d period 0 -KPX d d 0 -KPX d comma 0 - -KPX e y 0 -KPX e x 0 -KPX e w 0 -KPX e v 0 -KPX e period 0 -KPX e p 0 -KPX e g 0 -KPX e comma 0 -KPX e b -10 - -KPX f quoteright 55 -KPX f quotedblright 0 -KPX f period -10 -KPX f o -10 -KPX f l 0 -KPX f i 0 -KPX f f -18 -KPX f e -10 -KPX f dotlessi -30 -KPX f comma -10 -KPX f a 0 - -KPX g y 0 -KPX g r 0 -KPX g period 0 -KPX g o 0 -KPX g i 0 -KPX g g 0 -KPX g e 0 -KPX g comma 0 -KPX g a 0 - -KPX h y 0 - -KPX i v 0 - -KPX k y 0 -KPX k o -10 -KPX k e -30 - -KPX l y 0 -KPX l w 0 - -KPX m y 0 -KPX m u 0 - -KPX n y 0 -KPX n v -40 -KPX n u 0 - -KPX o y -10 -KPX o x -10 -KPX o w -25 -KPX o v -15 -KPX o g 0 - -KPX p y 0 - -KPX period quoteright -95 -KPX period quotedblright -95 - -KPX quotedblleft quoteleft 0 -KPX quotedblleft A 0 - -KPX quotedblright space 0 - -KPX quoteleft quoteleft -74 -KPX quoteleft A 0 - -KPX quoteright v -15 -KPX quoteright t -37 -KPX quoteright space -74 -KPX quoteright s -74 -KPX quoteright r -15 -KPX quoteright quoteright -74 -KPX quoteright quotedblright 0 -KPX quoteright l 0 -KPX quoteright d -15 - -KPX r y 0 -KPX r v 0 -KPX r u 0 -KPX r t 0 -KPX r s 0 -KPX r r 0 -KPX r q 0 -KPX r period -65 -KPX r p 0 -KPX r o 0 -KPX r n 0 -KPX r m 0 -KPX r l 0 -KPX r k 0 -KPX r i 0 -KPX r hyphen 0 -KPX r g 0 -KPX r e 0 -KPX r d 0 -KPX r comma -65 -KPX r c 0 -KPX r a 0 - -KPX s w 0 - -KPX space quoteleft 0 -KPX space quotedblleft 0 -KPX space Y -70 -KPX space W -70 -KPX space V -70 -KPX space T 0 -KPX space A -37 - -KPX v period -37 -KPX v o -15 -KPX v e -15 -KPX v comma -37 -KPX v a 0 - -KPX w period -37 -KPX w o -15 -KPX w h 0 -KPX w e -10 -KPX w comma -37 -KPX w a -10 - -KPX x e -10 - -KPX y period -37 -KPX y o 0 -KPX y e 0 -KPX y comma -37 -KPX y a 0 - -KPX z o 0 -KPX z e 0 -EndKernPairs -EndKernData -StartComposites 58 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 172 207 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 187 207 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 167 207 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave 172 207 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring 157 192 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde 167 207 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 167 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 172 207 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 187 207 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 187 207 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 172 207 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute 33 207 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 53 207 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 48 207 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave 33 207 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 210 207 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 200 207 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 230 207 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 215 207 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 200 207 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 215 207 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 112 207 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 210 207 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 230 207 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 230 207 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave 200 207 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 154 207 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 169 207 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 139 207 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 84 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 84 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 74 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave 74 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 84 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 84 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 56 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 56 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 56 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 46 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 46 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -42 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -37 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -37 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 97 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 69 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 74 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 28 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute 112 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 112 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 97 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave 102 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute 56 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 41 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 13 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Times-Italic.afm b/config/psfonts/Times-Italic.afm deleted file mode 100644 index 6d7a003b..00000000 --- a/config/psfonts/Times-Italic.afm +++ /dev/null @@ -1,648 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved. -Comment Creation Date: Tue Mar 20 13:14:56 1990 -Comment UniqueID 28427 -Comment VMusage 32912 39804 -FontName Times-Italic -FullName Times Italic -FamilyName Times -Weight Medium -ItalicAngle -15.5 -IsFixedPitch false -FontBBox -169 -217 1010 883 -UnderlinePosition -100 -UnderlineThickness 50 -Version 001.007 -Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype AG and/or its subsidiaries. -EncodingScheme AdobeStandardEncoding -CapHeight 653 -XHeight 441 -Ascender 683 -Descender -205 -StartCharMetrics 228 -C 32 ; WX 250 ; N space ; B 0 0 0 0 ; -C 33 ; WX 333 ; N exclam ; B 39 -11 302 667 ; -C 34 ; WX 420 ; N quotedbl ; B 144 421 432 666 ; -C 35 ; WX 500 ; N numbersign ; B 2 0 540 676 ; -C 36 ; WX 500 ; N dollar ; B 31 -89 497 731 ; -C 37 ; WX 833 ; N percent ; B 79 -13 790 676 ; -C 38 ; WX 778 ; N ampersand ; B 76 -18 723 666 ; -C 39 ; WX 333 ; N quoteright ; B 151 436 290 666 ; -C 40 ; WX 333 ; N parenleft ; B 42 -181 315 669 ; -C 41 ; WX 333 ; N parenright ; B 16 -180 289 669 ; -C 42 ; WX 500 ; N asterisk ; B 128 255 492 666 ; -C 43 ; WX 675 ; N plus ; B 86 0 590 506 ; -C 44 ; WX 250 ; N comma ; B -4 -129 135 101 ; -C 45 ; WX 333 ; N hyphen ; B 49 192 282 255 ; -C 46 ; WX 250 ; N period ; B 27 -11 138 100 ; -C 47 ; WX 278 ; N slash ; B -65 -18 386 666 ; -C 48 ; WX 500 ; N zero ; B 32 -7 497 676 ; -C 49 ; WX 500 ; N one ; B 49 0 409 676 ; -C 50 ; WX 500 ; N two ; B 12 0 452 676 ; -C 51 ; WX 500 ; N three ; B 15 -7 465 676 ; -C 52 ; WX 500 ; N four ; B 1 0 479 676 ; -C 53 ; WX 500 ; N five ; B 15 -7 491 666 ; -C 54 ; WX 500 ; N six ; B 30 -7 521 686 ; -C 55 ; WX 500 ; N seven ; B 75 -8 537 666 ; -C 56 ; WX 500 ; N eight ; B 30 -7 493 676 ; -C 57 ; WX 500 ; N nine ; B 23 -17 492 676 ; -C 58 ; WX 333 ; N colon ; B 50 -11 261 441 ; -C 59 ; WX 333 ; N semicolon ; B 27 -129 261 441 ; -C 60 ; WX 675 ; N less ; B 84 -8 592 514 ; -C 61 ; WX 675 ; N equal ; B 86 120 590 386 ; -C 62 ; WX 675 ; N greater ; B 84 -8 592 514 ; -C 63 ; WX 500 ; N question ; B 132 -12 472 664 ; -C 64 ; WX 920 ; N at ; B 118 -18 806 666 ; -C 65 ; WX 611 ; N A ; B -51 0 564 668 ; -C 66 ; WX 611 ; N B ; B -8 0 588 653 ; -C 67 ; WX 667 ; N C ; B 66 -18 689 666 ; -C 68 ; WX 722 ; N D ; B -8 0 700 653 ; -C 69 ; WX 611 ; N E ; B -1 0 634 653 ; -C 70 ; WX 611 ; N F ; B 8 0 645 653 ; -C 71 ; WX 722 ; N G ; B 52 -18 722 666 ; -C 72 ; WX 722 ; N H ; B -8 0 767 653 ; -C 73 ; WX 333 ; N I ; B -8 0 384 653 ; -C 74 ; WX 444 ; N J ; B -6 -18 491 653 ; -C 75 ; WX 667 ; N K ; B 7 0 722 653 ; -C 76 ; WX 556 ; N L ; B -8 0 559 653 ; -C 77 ; WX 833 ; N M ; B -18 0 873 653 ; -C 78 ; WX 667 ; N N ; B -20 -15 727 653 ; -C 79 ; WX 722 ; N O ; B 60 -18 699 666 ; -C 80 ; WX 611 ; N P ; B 0 0 605 653 ; -C 81 ; WX 722 ; N Q ; B 59 -182 699 666 ; -C 82 ; WX 611 ; N R ; B -13 0 588 653 ; -C 83 ; WX 500 ; N S ; B 17 -18 508 667 ; -C 84 ; WX 556 ; N T ; B 59 0 633 653 ; -C 85 ; WX 722 ; N U ; B 102 -18 765 653 ; -C 86 ; WX 611 ; N V ; B 76 -18 688 653 ; -C 87 ; WX 833 ; N W ; B 71 -18 906 653 ; -C 88 ; WX 611 ; N X ; B -29 0 655 653 ; -C 89 ; WX 556 ; N Y ; B 78 0 633 653 ; -C 90 ; WX 556 ; N Z ; B -6 0 606 653 ; -C 91 ; WX 389 ; N bracketleft ; B 21 -153 391 663 ; -C 92 ; WX 278 ; N backslash ; B -41 -18 319 666 ; -C 93 ; WX 389 ; N bracketright ; B 12 -153 382 663 ; -C 94 ; WX 422 ; N asciicircum ; B 0 301 422 666 ; -C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ; -C 96 ; WX 333 ; N quoteleft ; B 171 436 310 666 ; -C 97 ; WX 500 ; N a ; B 17 -11 476 441 ; -C 98 ; WX 500 ; N b ; B 23 -11 473 683 ; -C 99 ; WX 444 ; N c ; B 30 -11 425 441 ; -C 100 ; WX 500 ; N d ; B 15 -13 527 683 ; -C 101 ; WX 444 ; N e ; B 31 -11 412 441 ; -C 102 ; WX 278 ; N f ; B -147 -207 424 678 ; L i fi ; L l fl ; -C 103 ; WX 500 ; N g ; B 8 -206 472 441 ; -C 104 ; WX 500 ; N h ; B 19 -9 478 683 ; -C 105 ; WX 278 ; N i ; B 49 -11 264 654 ; -C 106 ; WX 278 ; N j ; B -124 -207 276 654 ; -C 107 ; WX 444 ; N k ; B 14 -11 461 683 ; -C 108 ; WX 278 ; N l ; B 41 -11 279 683 ; -C 109 ; WX 722 ; N m ; B 12 -9 704 441 ; -C 110 ; WX 500 ; N n ; B 14 -9 474 441 ; -C 111 ; WX 500 ; N o ; B 27 -11 468 441 ; -C 112 ; WX 500 ; N p ; B -75 -205 469 441 ; -C 113 ; WX 500 ; N q ; B 25 -209 483 441 ; -C 114 ; WX 389 ; N r ; B 45 0 412 441 ; -C 115 ; WX 389 ; N s ; B 16 -13 366 442 ; -C 116 ; WX 278 ; N t ; B 37 -11 296 546 ; -C 117 ; WX 500 ; N u ; B 42 -11 475 441 ; -C 118 ; WX 444 ; N v ; B 21 -18 426 441 ; -C 119 ; WX 667 ; N w ; B 16 -18 648 441 ; -C 120 ; WX 444 ; N x ; B -27 -11 447 441 ; -C 121 ; WX 444 ; N y ; B -24 -206 426 441 ; -C 122 ; WX 389 ; N z ; B -2 -81 380 428 ; -C 123 ; WX 400 ; N braceleft ; B 51 -177 407 687 ; -C 124 ; WX 275 ; N bar ; B 105 -18 171 666 ; -C 125 ; WX 400 ; N braceright ; B -7 -177 349 687 ; -C 126 ; WX 541 ; N asciitilde ; B 40 183 502 323 ; -C 161 ; WX 389 ; N exclamdown ; B 59 -205 322 473 ; -C 162 ; WX 500 ; N cent ; B 77 -143 472 560 ; -C 163 ; WX 500 ; N sterling ; B 10 -6 517 670 ; -C 164 ; WX 167 ; N fraction ; B -169 -10 337 676 ; -C 165 ; WX 500 ; N yen ; B 27 0 603 653 ; -C 166 ; WX 500 ; N florin ; B 25 -182 507 682 ; -C 167 ; WX 500 ; N section ; B 53 -162 461 666 ; -C 168 ; WX 500 ; N currency ; B -22 53 522 597 ; -C 169 ; WX 214 ; N quotesingle ; B 132 421 241 666 ; -C 170 ; WX 556 ; N quotedblleft ; B 166 436 514 666 ; -C 171 ; WX 500 ; N guillemotleft ; B 53 37 445 403 ; -C 172 ; WX 333 ; N guilsinglleft ; B 51 37 281 403 ; -C 173 ; WX 333 ; N guilsinglright ; B 52 37 282 403 ; -C 174 ; WX 500 ; N fi ; B -141 -207 481 681 ; -C 175 ; WX 500 ; N fl ; B -141 -204 518 682 ; -C 177 ; WX 500 ; N endash ; B -6 197 505 243 ; -C 178 ; WX 500 ; N dagger ; B 101 -159 488 666 ; -C 179 ; WX 500 ; N daggerdbl ; B 22 -143 491 666 ; -C 180 ; WX 250 ; N periodcentered ; B 70 199 181 310 ; -C 182 ; WX 523 ; N paragraph ; B 55 -123 616 653 ; -C 183 ; WX 350 ; N bullet ; B 40 191 310 461 ; -C 184 ; WX 333 ; N quotesinglbase ; B 44 -129 183 101 ; -C 185 ; WX 556 ; N quotedblbase ; B 57 -129 405 101 ; -C 186 ; WX 556 ; N quotedblright ; B 151 436 499 666 ; -C 187 ; WX 500 ; N guillemotright ; B 55 37 447 403 ; -C 188 ; WX 889 ; N ellipsis ; B 57 -11 762 100 ; -C 189 ; WX 1000 ; N perthousand ; B 25 -19 1010 706 ; -C 191 ; WX 500 ; N questiondown ; B 28 -205 368 471 ; -C 193 ; WX 333 ; N grave ; B 121 492 311 664 ; -C 194 ; WX 333 ; N acute ; B 180 494 403 664 ; -C 195 ; WX 333 ; N circumflex ; B 91 492 385 661 ; -C 196 ; WX 333 ; N tilde ; B 100 517 427 624 ; -C 197 ; WX 333 ; N macron ; B 99 532 411 583 ; -C 198 ; WX 333 ; N breve ; B 117 492 418 650 ; -C 199 ; WX 333 ; N dotaccent ; B 207 508 305 606 ; -C 200 ; WX 333 ; N dieresis ; B 107 508 405 606 ; -C 202 ; WX 333 ; N ring ; B 155 492 355 691 ; -C 203 ; WX 333 ; N cedilla ; B -30 -217 182 0 ; -C 205 ; WX 333 ; N hungarumlaut ; B 93 494 486 664 ; -C 206 ; WX 333 ; N ogonek ; B -20 -169 200 40 ; -C 207 ; WX 333 ; N caron ; B 121 492 426 661 ; -C 208 ; WX 889 ; N emdash ; B -6 197 894 243 ; -C 225 ; WX 889 ; N AE ; B -27 0 911 653 ; -C 227 ; WX 276 ; N ordfeminine ; B 42 406 352 676 ; -C 232 ; WX 556 ; N Lslash ; B -8 0 559 653 ; -C 233 ; WX 722 ; N Oslash ; B 60 -105 699 722 ; -C 234 ; WX 944 ; N OE ; B 49 -8 964 666 ; -C 235 ; WX 310 ; N ordmasculine ; B 67 406 362 676 ; -C 241 ; WX 667 ; N ae ; B 23 -11 640 441 ; -C 245 ; WX 278 ; N dotlessi ; B 49 -11 235 441 ; -C 248 ; WX 278 ; N lslash ; B 37 -11 307 683 ; -C 249 ; WX 500 ; N oslash ; B 28 -135 469 554 ; -C 250 ; WX 667 ; N oe ; B 20 -12 646 441 ; -C 251 ; WX 500 ; N germandbls ; B -168 -207 493 679 ; -C -1 ; WX 556 ; N Zcaron ; B -6 0 606 873 ; -C -1 ; WX 444 ; N ccedilla ; B 26 -217 425 441 ; -C -1 ; WX 444 ; N ydieresis ; B -24 -206 441 606 ; -C -1 ; WX 500 ; N atilde ; B 17 -11 511 624 ; -C -1 ; WX 278 ; N icircumflex ; B 34 -11 328 661 ; -C -1 ; WX 300 ; N threesuperior ; B 43 268 339 676 ; -C -1 ; WX 444 ; N ecircumflex ; B 31 -11 441 661 ; -C -1 ; WX 500 ; N thorn ; B -75 -205 469 683 ; -C -1 ; WX 444 ; N egrave ; B 31 -11 412 664 ; -C -1 ; WX 300 ; N twosuperior ; B 33 271 324 676 ; -C -1 ; WX 444 ; N eacute ; B 31 -11 459 664 ; -C -1 ; WX 500 ; N otilde ; B 27 -11 496 624 ; -C -1 ; WX 611 ; N Aacute ; B -51 0 564 876 ; -C -1 ; WX 500 ; N ocircumflex ; B 27 -11 468 661 ; -C -1 ; WX 444 ; N yacute ; B -24 -206 459 664 ; -C -1 ; WX 500 ; N udieresis ; B 42 -11 479 606 ; -C -1 ; WX 750 ; N threequarters ; B 23 -10 736 676 ; -C -1 ; WX 500 ; N acircumflex ; B 17 -11 476 661 ; -C -1 ; WX 722 ; N Eth ; B -8 0 700 653 ; -C -1 ; WX 444 ; N edieresis ; B 31 -11 451 606 ; -C -1 ; WX 500 ; N ugrave ; B 42 -11 475 664 ; -C -1 ; WX 980 ; N trademark ; B 30 247 957 653 ; -C -1 ; WX 500 ; N ograve ; B 27 -11 468 664 ; -C -1 ; WX 389 ; N scaron ; B 16 -13 454 661 ; -C -1 ; WX 333 ; N Idieresis ; B -8 0 435 818 ; -C -1 ; WX 500 ; N uacute ; B 42 -11 477 664 ; -C -1 ; WX 500 ; N agrave ; B 17 -11 476 664 ; -C -1 ; WX 500 ; N ntilde ; B 14 -9 476 624 ; -C -1 ; WX 500 ; N aring ; B 17 -11 476 691 ; -C -1 ; WX 389 ; N zcaron ; B -2 -81 434 661 ; -C -1 ; WX 333 ; N Icircumflex ; B -8 0 425 873 ; -C -1 ; WX 667 ; N Ntilde ; B -20 -15 727 836 ; -C -1 ; WX 500 ; N ucircumflex ; B 42 -11 475 661 ; -C -1 ; WX 611 ; N Ecircumflex ; B -1 0 634 873 ; -C -1 ; WX 333 ; N Iacute ; B -8 0 413 876 ; -C -1 ; WX 667 ; N Ccedilla ; B 66 -217 689 666 ; -C -1 ; WX 722 ; N Odieresis ; B 60 -18 699 818 ; -C -1 ; WX 500 ; N Scaron ; B 17 -18 520 873 ; -C -1 ; WX 611 ; N Edieresis ; B -1 0 634 818 ; -C -1 ; WX 333 ; N Igrave ; B -8 0 384 876 ; -C -1 ; WX 500 ; N adieresis ; B 17 -11 489 606 ; -C -1 ; WX 722 ; N Ograve ; B 60 -18 699 876 ; -C -1 ; WX 611 ; N Egrave ; B -1 0 634 876 ; -C -1 ; WX 556 ; N Ydieresis ; B 78 0 633 818 ; -C -1 ; WX 760 ; N registered ; B 41 -18 719 666 ; -C -1 ; WX 722 ; N Otilde ; B 60 -18 699 836 ; -C -1 ; WX 750 ; N onequarter ; B 33 -10 736 676 ; -C -1 ; WX 722 ; N Ugrave ; B 102 -18 765 876 ; -C -1 ; WX 722 ; N Ucircumflex ; B 102 -18 765 873 ; -C -1 ; WX 611 ; N Thorn ; B 0 0 569 653 ; -C -1 ; WX 675 ; N divide ; B 86 -11 590 517 ; -C -1 ; WX 611 ; N Atilde ; B -51 0 566 836 ; -C -1 ; WX 722 ; N Uacute ; B 102 -18 765 876 ; -C -1 ; WX 722 ; N Ocircumflex ; B 60 -18 699 873 ; -C -1 ; WX 675 ; N logicalnot ; B 86 108 590 386 ; -C -1 ; WX 611 ; N Aring ; B -51 0 564 883 ; -C -1 ; WX 278 ; N idieresis ; B 49 -11 353 606 ; -C -1 ; WX 278 ; N iacute ; B 49 -11 356 664 ; -C -1 ; WX 500 ; N aacute ; B 17 -11 487 664 ; -C -1 ; WX 675 ; N plusminus ; B 86 0 590 506 ; -C -1 ; WX 675 ; N multiply ; B 93 8 582 497 ; -C -1 ; WX 722 ; N Udieresis ; B 102 -18 765 818 ; -C -1 ; WX 675 ; N minus ; B 86 220 590 286 ; -C -1 ; WX 300 ; N onesuperior ; B 43 271 284 676 ; -C -1 ; WX 611 ; N Eacute ; B -1 0 634 876 ; -C -1 ; WX 611 ; N Acircumflex ; B -51 0 564 873 ; -C -1 ; WX 760 ; N copyright ; B 41 -18 719 666 ; -C -1 ; WX 611 ; N Agrave ; B -51 0 564 876 ; -C -1 ; WX 500 ; N odieresis ; B 27 -11 489 606 ; -C -1 ; WX 500 ; N oacute ; B 27 -11 487 664 ; -C -1 ; WX 400 ; N degree ; B 101 390 387 676 ; -C -1 ; WX 278 ; N igrave ; B 49 -11 284 664 ; -C -1 ; WX 500 ; N mu ; B -30 -209 497 428 ; -C -1 ; WX 722 ; N Oacute ; B 60 -18 699 876 ; -C -1 ; WX 500 ; N eth ; B 27 -11 482 683 ; -C -1 ; WX 611 ; N Adieresis ; B -51 0 564 818 ; -C -1 ; WX 556 ; N Yacute ; B 78 0 633 876 ; -C -1 ; WX 275 ; N brokenbar ; B 105 -18 171 666 ; -C -1 ; WX 750 ; N onehalf ; B 34 -10 749 676 ; -EndCharMetrics -StartKernData -StartKernPairs 283 - -KPX A y -55 -KPX A w -55 -KPX A v -55 -KPX A u -20 -KPX A quoteright -37 -KPX A quotedblright 0 -KPX A p 0 -KPX A Y -55 -KPX A W -95 -KPX A V -105 -KPX A U -50 -KPX A T -37 -KPX A Q -40 -KPX A O -40 -KPX A G -35 -KPX A C -30 - -KPX B period 0 -KPX B comma 0 -KPX B U -10 -KPX B A -25 - -KPX D period 0 -KPX D comma 0 -KPX D Y -40 -KPX D W -40 -KPX D V -40 -KPX D A -35 - -KPX F r -55 -KPX F period -135 -KPX F o -105 -KPX F i -45 -KPX F e -75 -KPX F comma -135 -KPX F a -75 -KPX F A -115 - -KPX G period 0 -KPX G comma 0 - -KPX J u -35 -KPX J period -25 -KPX J o -25 -KPX J e -25 -KPX J comma -25 -KPX J a -35 -KPX J A -40 - -KPX K y -40 -KPX K u -40 -KPX K o -40 -KPX K e -35 -KPX K O -50 - -KPX L y -30 -KPX L quoteright -37 -KPX L quotedblright 0 -KPX L Y -20 -KPX L W -55 -KPX L V -55 -KPX L T -20 - -KPX N period 0 -KPX N comma 0 -KPX N A -27 - -KPX O period 0 -KPX O comma 0 -KPX O Y -50 -KPX O X -40 -KPX O W -50 -KPX O V -50 -KPX O T -40 -KPX O A -55 - -KPX P period -135 -KPX P o -80 -KPX P e -80 -KPX P comma -135 -KPX P a -80 -KPX P A -90 - -KPX Q period 0 -KPX Q comma 0 -KPX Q U -10 - -KPX R Y -18 -KPX R W -18 -KPX R V -18 -KPX R U -40 -KPX R T 0 -KPX R O -40 - -KPX S period 0 -KPX S comma 0 - -KPX T y -74 -KPX T w -74 -KPX T u -55 -KPX T semicolon -65 -KPX T r -55 -KPX T period -74 -KPX T o -92 -KPX T i -55 -KPX T hyphen -74 -KPX T h 0 -KPX T e -92 -KPX T comma -74 -KPX T colon -55 -KPX T a -92 -KPX T O -18 -KPX T A -50 - -KPX U period -25 -KPX U comma -25 -KPX U A -40 - -KPX V u -74 -KPX V semicolon -74 -KPX V period -129 -KPX V o -111 -KPX V i -74 -KPX V hyphen -55 -KPX V e -111 -KPX V comma -129 -KPX V colon -65 -KPX V a -111 -KPX V O -30 -KPX V G 0 -KPX V A -60 - -KPX W y -70 -KPX W u -55 -KPX W semicolon -65 -KPX W period -92 -KPX W o -92 -KPX W i -55 -KPX W hyphen -37 -KPX W h 0 -KPX W e -92 -KPX W comma -92 -KPX W colon -65 -KPX W a -92 -KPX W O -25 -KPX W A -60 - -KPX Y u -92 -KPX Y semicolon -65 -KPX Y period -92 -KPX Y o -92 -KPX Y i -74 -KPX Y hyphen -74 -KPX Y e -92 -KPX Y comma -92 -KPX Y colon -65 -KPX Y a -92 -KPX Y O -15 -KPX Y A -50 - -KPX a y 0 -KPX a w 0 -KPX a v 0 -KPX a t 0 -KPX a p 0 -KPX a g -10 -KPX a b 0 - -KPX b y 0 -KPX b v 0 -KPX b u -20 -KPX b period -40 -KPX b l 0 -KPX b comma 0 -KPX b b 0 - -KPX c y 0 -KPX c period 0 -KPX c l 0 -KPX c k -20 -KPX c h -15 -KPX c comma 0 - -KPX colon space 0 - -KPX comma space 0 -KPX comma quoteright -140 -KPX comma quotedblright -140 - -KPX d y 0 -KPX d w 0 -KPX d v 0 -KPX d period 0 -KPX d d 0 -KPX d comma 0 - -KPX e y -30 -KPX e x -20 -KPX e w -15 -KPX e v -15 -KPX e period -15 -KPX e p 0 -KPX e g -40 -KPX e comma -10 -KPX e b 0 - -KPX f quoteright 92 -KPX f quotedblright 0 -KPX f period -15 -KPX f o 0 -KPX f l 0 -KPX f i -20 -KPX f f -18 -KPX f e 0 -KPX f dotlessi -60 -KPX f comma -10 -KPX f a 0 - -KPX g y 0 -KPX g r 0 -KPX g period -15 -KPX g o 0 -KPX g i 0 -KPX g g -10 -KPX g e -10 -KPX g comma -10 -KPX g a 0 - -KPX h y 0 - -KPX i v 0 - -KPX k y -10 -KPX k o -10 -KPX k e -10 - -KPX l y 0 -KPX l w 0 - -KPX m y 0 -KPX m u 0 - -KPX n y 0 -KPX n v -40 -KPX n u 0 - -KPX o y 0 -KPX o x 0 -KPX o w 0 -KPX o v -10 -KPX o g -10 - -KPX p y 0 - -KPX period quoteright -140 -KPX period quotedblright -140 - -KPX quotedblleft quoteleft 0 -KPX quotedblleft A 0 - -KPX quotedblright space 0 - -KPX quoteleft quoteleft -111 -KPX quoteleft A 0 - -KPX quoteright v -10 -KPX quoteright t -30 -KPX quoteright space -111 -KPX quoteright s -40 -KPX quoteright r -25 -KPX quoteright quoteright -111 -KPX quoteright quotedblright 0 -KPX quoteright l 0 -KPX quoteright d -25 - -KPX r y 0 -KPX r v 0 -KPX r u 0 -KPX r t 0 -KPX r s -10 -KPX r r 0 -KPX r q -37 -KPX r period -111 -KPX r p 0 -KPX r o -45 -KPX r n 0 -KPX r m 0 -KPX r l 0 -KPX r k 0 -KPX r i 0 -KPX r hyphen -20 -KPX r g -37 -KPX r e -37 -KPX r d -37 -KPX r comma -111 -KPX r c -37 -KPX r a -15 - -KPX s w 0 - -KPX space quoteleft 0 -KPX space quotedblleft 0 -KPX space Y -75 -KPX space W -40 -KPX space V -35 -KPX space T -18 -KPX space A -18 - -KPX v period -74 -KPX v o 0 -KPX v e 0 -KPX v comma -74 -KPX v a 0 - -KPX w period -74 -KPX w o 0 -KPX w h 0 -KPX w e 0 -KPX w comma -74 -KPX w a 0 - -KPX x e 0 - -KPX y period -55 -KPX y o 0 -KPX y e 0 -KPX y comma -55 -KPX y a 0 - -KPX z o 0 -KPX z e 0 -EndKernPairs -EndKernData -StartComposites 58 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 139 212 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 144 212 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 139 212 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave 149 212 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring 129 192 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde 139 212 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 167 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 149 212 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 169 212 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 159 212 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 149 212 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute 10 212 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 40 212 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 30 212 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave 10 212 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 177 212 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 195 212 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 230 212 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 230 212 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 205 212 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 215 212 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 94 212 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 195 212 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 215 212 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 225 212 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave 215 212 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 132 212 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 142 212 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 112 212 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 84 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 84 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 84 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave 84 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 84 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 84 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 56 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 56 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 56 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 46 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 56 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -47 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -57 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -52 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 49 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 74 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 69 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 28 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute 74 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 74 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 74 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave 84 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute 56 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 36 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 8 0 ; -EndComposites -EndFontMetrics diff --git a/config/psfonts/Times-Roman.afm b/config/psfonts/Times-Roman.afm deleted file mode 100644 index e5092b5c..00000000 --- a/config/psfonts/Times-Roman.afm +++ /dev/null @@ -1,648 +0,0 @@ -StartFontMetrics 2.0 -Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved. -Comment Creation Date: Tue Mar 20 12:15:44 1990 -Comment UniqueID 28416 -Comment VMusage 30487 37379 -FontName Times-Roman -FullName Times Roman -FamilyName Times -Weight Roman -ItalicAngle 0 -IsFixedPitch false -FontBBox -168 -218 1000 898 -UnderlinePosition -100 -UnderlineThickness 50 -Version 001.007 -Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype AG and/or its subsidiaries. -EncodingScheme AdobeStandardEncoding -CapHeight 662 -XHeight 450 -Ascender 683 -Descender -217 -StartCharMetrics 228 -C 32 ; WX 250 ; N space ; B 0 0 0 0 ; -C 33 ; WX 333 ; N exclam ; B 130 -9 238 676 ; -C 34 ; WX 408 ; N quotedbl ; B 77 431 331 676 ; -C 35 ; WX 500 ; N numbersign ; B 5 0 496 662 ; -C 36 ; WX 500 ; N dollar ; B 44 -87 457 727 ; -C 37 ; WX 833 ; N percent ; B 61 -13 772 676 ; -C 38 ; WX 778 ; N ampersand ; B 42 -13 750 676 ; -C 39 ; WX 333 ; N quoteright ; B 79 433 218 676 ; -C 40 ; WX 333 ; N parenleft ; B 48 -177 304 676 ; -C 41 ; WX 333 ; N parenright ; B 29 -177 285 676 ; -C 42 ; WX 500 ; N asterisk ; B 69 265 432 676 ; -C 43 ; WX 564 ; N plus ; B 30 0 534 506 ; -C 44 ; WX 250 ; N comma ; B 56 -141 195 102 ; -C 45 ; WX 333 ; N hyphen ; B 39 194 285 257 ; -C 46 ; WX 250 ; N period ; B 70 -11 181 100 ; -C 47 ; WX 278 ; N slash ; B -9 -14 287 676 ; -C 48 ; WX 500 ; N zero ; B 24 -14 476 676 ; -C 49 ; WX 500 ; N one ; B 111 0 394 676 ; -C 50 ; WX 500 ; N two ; B 30 0 475 676 ; -C 51 ; WX 500 ; N three ; B 43 -14 431 676 ; -C 52 ; WX 500 ; N four ; B 12 0 472 676 ; -C 53 ; WX 500 ; N five ; B 32 -14 438 688 ; -C 54 ; WX 500 ; N six ; B 34 -14 468 684 ; -C 55 ; WX 500 ; N seven ; B 20 -8 449 662 ; -C 56 ; WX 500 ; N eight ; B 56 -14 445 676 ; -C 57 ; WX 500 ; N nine ; B 30 -22 459 676 ; -C 58 ; WX 278 ; N colon ; B 81 -11 192 459 ; -C 59 ; WX 278 ; N semicolon ; B 80 -141 219 459 ; -C 60 ; WX 564 ; N less ; B 28 -8 536 514 ; -C 61 ; WX 564 ; N equal ; B 30 120 534 386 ; -C 62 ; WX 564 ; N greater ; B 28 -8 536 514 ; -C 63 ; WX 444 ; N question ; B 68 -8 414 676 ; -C 64 ; WX 921 ; N at ; B 116 -14 809 676 ; -C 65 ; WX 722 ; N A ; B 15 0 706 674 ; -C 66 ; WX 667 ; N B ; B 17 0 593 662 ; -C 67 ; WX 667 ; N C ; B 28 -14 633 676 ; -C 68 ; WX 722 ; N D ; B 16 0 685 662 ; -C 69 ; WX 611 ; N E ; B 12 0 597 662 ; -C 70 ; WX 556 ; N F ; B 12 0 546 662 ; -C 71 ; WX 722 ; N G ; B 32 -14 709 676 ; -C 72 ; WX 722 ; N H ; B 19 0 702 662 ; -C 73 ; WX 333 ; N I ; B 18 0 315 662 ; -C 74 ; WX 389 ; N J ; B 10 -14 370 662 ; -C 75 ; WX 722 ; N K ; B 34 0 723 662 ; -C 76 ; WX 611 ; N L ; B 12 0 598 662 ; -C 77 ; WX 889 ; N M ; B 12 0 863 662 ; -C 78 ; WX 722 ; N N ; B 12 -11 707 662 ; -C 79 ; WX 722 ; N O ; B 34 -14 688 676 ; -C 80 ; WX 556 ; N P ; B 16 0 542 662 ; -C 81 ; WX 722 ; N Q ; B 34 -178 701 676 ; -C 82 ; WX 667 ; N R ; B 17 0 659 662 ; -C 83 ; WX 556 ; N S ; B 42 -14 491 676 ; -C 84 ; WX 611 ; N T ; B 17 0 593 662 ; -C 85 ; WX 722 ; N U ; B 14 -14 705 662 ; -C 86 ; WX 722 ; N V ; B 16 -11 697 662 ; -C 87 ; WX 944 ; N W ; B 5 -11 932 662 ; -C 88 ; WX 722 ; N X ; B 10 0 704 662 ; -C 89 ; WX 722 ; N Y ; B 22 0 703 662 ; -C 90 ; WX 611 ; N Z ; B 9 0 597 662 ; -C 91 ; WX 333 ; N bracketleft ; B 88 -156 299 662 ; -C 92 ; WX 278 ; N backslash ; B -9 -14 287 676 ; -C 93 ; WX 333 ; N bracketright ; B 34 -156 245 662 ; -C 94 ; WX 469 ; N asciicircum ; B 24 297 446 662 ; -C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ; -C 96 ; WX 333 ; N quoteleft ; B 115 433 254 676 ; -C 97 ; WX 444 ; N a ; B 37 -10 442 460 ; -C 98 ; WX 500 ; N b ; B 3 -10 468 683 ; -C 99 ; WX 444 ; N c ; B 25 -10 412 460 ; -C 100 ; WX 500 ; N d ; B 27 -10 491 683 ; -C 101 ; WX 444 ; N e ; B 25 -10 424 460 ; -C 102 ; WX 333 ; N f ; B 20 0 383 683 ; L i fi ; L l fl ; -C 103 ; WX 500 ; N g ; B 28 -218 470 460 ; -C 104 ; WX 500 ; N h ; B 9 0 487 683 ; -C 105 ; WX 278 ; N i ; B 16 0 253 683 ; -C 106 ; WX 278 ; N j ; B -70 -218 194 683 ; -C 107 ; WX 500 ; N k ; B 7 0 505 683 ; -C 108 ; WX 278 ; N l ; B 19 0 257 683 ; -C 109 ; WX 778 ; N m ; B 16 0 775 460 ; -C 110 ; WX 500 ; N n ; B 16 0 485 460 ; -C 111 ; WX 500 ; N o ; B 29 -10 470 460 ; -C 112 ; WX 500 ; N p ; B 5 -217 470 460 ; -C 113 ; WX 500 ; N q ; B 24 -217 488 460 ; -C 114 ; WX 333 ; N r ; B 5 0 335 460 ; -C 115 ; WX 389 ; N s ; B 51 -10 348 460 ; -C 116 ; WX 278 ; N t ; B 13 -10 279 579 ; -C 117 ; WX 500 ; N u ; B 9 -10 479 450 ; -C 118 ; WX 500 ; N v ; B 19 -14 477 450 ; -C 119 ; WX 722 ; N w ; B 21 -14 694 450 ; -C 120 ; WX 500 ; N x ; B 17 0 479 450 ; -C 121 ; WX 500 ; N y ; B 14 -218 475 450 ; -C 122 ; WX 444 ; N z ; B 27 0 418 450 ; -C 123 ; WX 480 ; N braceleft ; B 100 -181 350 680 ; -C 124 ; WX 200 ; N bar ; B 67 -14 133 676 ; -C 125 ; WX 480 ; N braceright ; B 130 -181 380 680 ; -C 126 ; WX 541 ; N asciitilde ; B 40 183 502 323 ; -C 161 ; WX 333 ; N exclamdown ; B 97 -218 205 467 ; -C 162 ; WX 500 ; N cent ; B 53 -138 448 579 ; -C 163 ; WX 500 ; N sterling ; B 12 -8 490 676 ; -C 164 ; WX 167 ; N fraction ; B -168 -14 331 676 ; -C 165 ; WX 500 ; N yen ; B -53 0 512 662 ; -C 166 ; WX 500 ; N florin ; B 7 -189 490 676 ; -C 167 ; WX 500 ; N section ; B 70 -148 426 676 ; -C 168 ; WX 500 ; N currency ; B -22 58 522 602 ; -C 169 ; WX 180 ; N quotesingle ; B 48 431 133 676 ; -C 170 ; WX 444 ; N quotedblleft ; B 43 433 414 676 ; -C 171 ; WX 500 ; N guillemotleft ; B 42 33 456 416 ; -C 172 ; WX 333 ; N guilsinglleft ; B 63 33 285 416 ; -C 173 ; WX 333 ; N guilsinglright ; B 48 33 270 416 ; -C 174 ; WX 556 ; N fi ; B 31 0 521 683 ; -C 175 ; WX 556 ; N fl ; B 32 0 521 683 ; -C 177 ; WX 500 ; N endash ; B 0 201 500 250 ; -C 178 ; WX 500 ; N dagger ; B 59 -149 442 676 ; -C 179 ; WX 500 ; N daggerdbl ; B 58 -153 442 676 ; -C 180 ; WX 250 ; N periodcentered ; B 70 199 181 310 ; -C 182 ; WX 453 ; N paragraph ; B -22 -154 450 662 ; -C 183 ; WX 350 ; N bullet ; B 40 196 310 466 ; -C 184 ; WX 333 ; N quotesinglbase ; B 79 -141 218 102 ; -C 185 ; WX 444 ; N quotedblbase ; B 45 -141 416 102 ; -C 186 ; WX 444 ; N quotedblright ; B 30 433 401 676 ; -C 187 ; WX 500 ; N guillemotright ; B 44 33 458 416 ; -C 188 ; WX 1000 ; N ellipsis ; B 111 -11 888 100 ; -C 189 ; WX 1000 ; N perthousand ; B 7 -19 994 706 ; -C 191 ; WX 444 ; N questiondown ; B 30 -218 376 466 ; -C 193 ; WX 333 ; N grave ; B 19 507 242 678 ; -C 194 ; WX 333 ; N acute ; B 93 507 317 678 ; -C 195 ; WX 333 ; N circumflex ; B 11 507 322 674 ; -C 196 ; WX 333 ; N tilde ; B 1 532 331 638 ; -C 197 ; WX 333 ; N macron ; B 11 547 322 601 ; -C 198 ; WX 333 ; N breve ; B 26 507 307 664 ; -C 199 ; WX 333 ; N dotaccent ; B 118 523 216 623 ; -C 200 ; WX 333 ; N dieresis ; B 18 523 315 623 ; -C 202 ; WX 333 ; N ring ; B 67 512 266 711 ; -C 203 ; WX 333 ; N cedilla ; B 52 -215 261 0 ; -C 205 ; WX 333 ; N hungarumlaut ; B -3 507 377 678 ; -C 206 ; WX 333 ; N ogonek ; B 64 -165 249 0 ; -C 207 ; WX 333 ; N caron ; B 11 507 322 674 ; -C 208 ; WX 1000 ; N emdash ; B 0 201 1000 250 ; -C 225 ; WX 889 ; N AE ; B 0 0 863 662 ; -C 227 ; WX 276 ; N ordfeminine ; B 4 394 270 676 ; -C 232 ; WX 611 ; N Lslash ; B 12 0 598 662 ; -C 233 ; WX 722 ; N Oslash ; B 34 -80 688 734 ; -C 234 ; WX 889 ; N OE ; B 30 -6 885 668 ; -C 235 ; WX 310 ; N ordmasculine ; B 6 394 304 676 ; -C 241 ; WX 667 ; N ae ; B 38 -10 632 460 ; -C 245 ; WX 278 ; N dotlessi ; B 16 0 253 460 ; -C 248 ; WX 278 ; N lslash ; B 19 0 259 683 ; -C 249 ; WX 500 ; N oslash ; B 29 -112 470 551 ; -C 250 ; WX 722 ; N oe ; B 30 -10 690 460 ; -C 251 ; WX 500 ; N germandbls ; B 12 -9 468 683 ; -C -1 ; WX 611 ; N Zcaron ; B 9 0 597 886 ; -C -1 ; WX 444 ; N ccedilla ; B 25 -215 412 460 ; -C -1 ; WX 500 ; N ydieresis ; B 14 -218 475 623 ; -C -1 ; WX 444 ; N atilde ; B 37 -10 442 638 ; -C -1 ; WX 278 ; N icircumflex ; B -16 0 295 674 ; -C -1 ; WX 300 ; N threesuperior ; B 15 262 291 676 ; -C -1 ; WX 444 ; N ecircumflex ; B 25 -10 424 674 ; -C -1 ; WX 500 ; N thorn ; B 5 -217 470 683 ; -C -1 ; WX 444 ; N egrave ; B 25 -10 424 678 ; -C -1 ; WX 300 ; N twosuperior ; B 1 270 296 676 ; -C -1 ; WX 444 ; N eacute ; B 25 -10 424 678 ; -C -1 ; WX 500 ; N otilde ; B 29 -10 470 638 ; -C -1 ; WX 722 ; N Aacute ; B 15 0 706 890 ; -C -1 ; WX 500 ; N ocircumflex ; B 29 -10 470 674 ; -C -1 ; WX 500 ; N yacute ; B 14 -218 475 678 ; -C -1 ; WX 500 ; N udieresis ; B 9 -10 479 623 ; -C -1 ; WX 750 ; N threequarters ; B 15 -14 718 676 ; -C -1 ; WX 444 ; N acircumflex ; B 37 -10 442 674 ; -C -1 ; WX 722 ; N Eth ; B 16 0 685 662 ; -C -1 ; WX 444 ; N edieresis ; B 25 -10 424 623 ; -C -1 ; WX 500 ; N ugrave ; B 9 -10 479 678 ; -C -1 ; WX 980 ; N trademark ; B 30 256 957 662 ; -C -1 ; WX 500 ; N ograve ; B 29 -10 470 678 ; -C -1 ; WX 389 ; N scaron ; B 39 -10 350 674 ; -C -1 ; WX 333 ; N Idieresis ; B 18 0 315 835 ; -C -1 ; WX 500 ; N uacute ; B 9 -10 479 678 ; -C -1 ; WX 444 ; N agrave ; B 37 -10 442 678 ; -C -1 ; WX 500 ; N ntilde ; B 16 0 485 638 ; -C -1 ; WX 444 ; N aring ; B 37 -10 442 711 ; -C -1 ; WX 444 ; N zcaron ; B 27 0 418 674 ; -C -1 ; WX 333 ; N Icircumflex ; B 11 0 322 886 ; -C -1 ; WX 722 ; N Ntilde ; B 12 -11 707 850 ; -C -1 ; WX 500 ; N ucircumflex ; B 9 -10 479 674 ; -C -1 ; WX 611 ; N Ecircumflex ; B 12 0 597 886 ; -C -1 ; WX 333 ; N Iacute ; B 18 0 317 890 ; -C -1 ; WX 667 ; N Ccedilla ; B 28 -215 633 676 ; -C -1 ; WX 722 ; N Odieresis ; B 34 -14 688 835 ; -C -1 ; WX 556 ; N Scaron ; B 42 -14 491 886 ; -C -1 ; WX 611 ; N Edieresis ; B 12 0 597 835 ; -C -1 ; WX 333 ; N Igrave ; B 18 0 315 890 ; -C -1 ; WX 444 ; N adieresis ; B 37 -10 442 623 ; -C -1 ; WX 722 ; N Ograve ; B 34 -14 688 890 ; -C -1 ; WX 611 ; N Egrave ; B 12 0 597 890 ; -C -1 ; WX 722 ; N Ydieresis ; B 22 0 703 835 ; -C -1 ; WX 760 ; N registered ; B 38 -14 722 676 ; -C -1 ; WX 722 ; N Otilde ; B 34 -14 688 850 ; -C -1 ; WX 750 ; N onequarter ; B 37 -14 718 676 ; -C -1 ; WX 722 ; N Ugrave ; B 14 -14 705 890 ; -C -1 ; WX 722 ; N Ucircumflex ; B 14 -14 705 886 ; -C -1 ; WX 556 ; N Thorn ; B 16 0 542 662 ; -C -1 ; WX 564 ; N divide ; B 30 -10 534 516 ; -C -1 ; WX 722 ; N Atilde ; B 15 0 706 850 ; -C -1 ; WX 722 ; N Uacute ; B 14 -14 705 890 ; -C -1 ; WX 722 ; N Ocircumflex ; B 34 -14 688 886 ; -C -1 ; WX 564 ; N logicalnot ; B 30 108 534 386 ; -C -1 ; WX 722 ; N Aring ; B 15 0 706 898 ; -C -1 ; WX 278 ; N idieresis ; B -9 0 288 623 ; -C -1 ; WX 278 ; N iacute ; B 16 0 290 678 ; -C -1 ; WX 444 ; N aacute ; B 37 -10 442 678 ; -C -1 ; WX 564 ; N plusminus ; B 30 0 534 506 ; -C -1 ; WX 564 ; N multiply ; B 38 8 527 497 ; -C -1 ; WX 722 ; N Udieresis ; B 14 -14 705 835 ; -C -1 ; WX 564 ; N minus ; B 30 220 534 286 ; -C -1 ; WX 300 ; N onesuperior ; B 57 270 248 676 ; -C -1 ; WX 611 ; N Eacute ; B 12 0 597 890 ; -C -1 ; WX 722 ; N Acircumflex ; B 15 0 706 886 ; -C -1 ; WX 760 ; N copyright ; B 38 -14 722 676 ; -C -1 ; WX 722 ; N Agrave ; B 15 0 706 890 ; -C -1 ; WX 500 ; N odieresis ; B 29 -10 470 623 ; -C -1 ; WX 500 ; N oacute ; B 29 -10 470 678 ; -C -1 ; WX 400 ; N degree ; B 57 390 343 676 ; -C -1 ; WX 278 ; N igrave ; B -8 0 253 678 ; -C -1 ; WX 500 ; N mu ; B 36 -218 512 450 ; -C -1 ; WX 722 ; N Oacute ; B 34 -14 688 890 ; -C -1 ; WX 500 ; N eth ; B 29 -10 471 686 ; -C -1 ; WX 722 ; N Adieresis ; B 15 0 706 835 ; -C -1 ; WX 722 ; N Yacute ; B 22 0 703 890 ; -C -1 ; WX 200 ; N brokenbar ; B 67 -14 133 676 ; -C -1 ; WX 750 ; N onehalf ; B 31 -14 746 676 ; -EndCharMetrics -StartKernData -StartKernPairs 283 - -KPX A y -92 -KPX A w -92 -KPX A v -74 -KPX A u 0 -KPX A quoteright -111 -KPX A quotedblright 0 -KPX A p 0 -KPX A Y -105 -KPX A W -90 -KPX A V -135 -KPX A U -55 -KPX A T -111 -KPX A Q -55 -KPX A O -55 -KPX A G -40 -KPX A C -40 - -KPX B period 0 -KPX B comma 0 -KPX B U -10 -KPX B A -35 - -KPX D period 0 -KPX D comma 0 -KPX D Y -55 -KPX D W -30 -KPX D V -40 -KPX D A -40 - -KPX F r 0 -KPX F period -80 -KPX F o -15 -KPX F i 0 -KPX F e 0 -KPX F comma -80 -KPX F a -15 -KPX F A -74 - -KPX G period 0 -KPX G comma 0 - -KPX J u 0 -KPX J period 0 -KPX J o 0 -KPX J e 0 -KPX J comma 0 -KPX J a 0 -KPX J A -60 - -KPX K y -25 -KPX K u -15 -KPX K o -35 -KPX K e -25 -KPX K O -30 - -KPX L y -55 -KPX L quoteright -92 -KPX L quotedblright 0 -KPX L Y -100 -KPX L W -74 -KPX L V -100 -KPX L T -92 - -KPX N period 0 -KPX N comma 0 -KPX N A -35 - -KPX O period 0 -KPX O comma 0 -KPX O Y -50 -KPX O X -40 -KPX O W -35 -KPX O V -50 -KPX O T -40 -KPX O A -35 - -KPX P period -111 -KPX P o 0 -KPX P e 0 -KPX P comma -111 -KPX P a -15 -KPX P A -92 - -KPX Q period 0 -KPX Q comma 0 -KPX Q U -10 - -KPX R Y -65 -KPX R W -55 -KPX R V -80 -KPX R U -40 -KPX R T -60 -KPX R O -40 - -KPX S period 0 -KPX S comma 0 - -KPX T y -80 -KPX T w -80 -KPX T u -45 -KPX T semicolon -55 -KPX T r -35 -KPX T period -74 -KPX T o -80 -KPX T i -35 -KPX T hyphen -92 -KPX T h 0 -KPX T e -70 -KPX T comma -74 -KPX T colon -50 -KPX T a -80 -KPX T O -18 -KPX T A -93 - -KPX U period 0 -KPX U comma 0 -KPX U A -40 - -KPX V u -75 -KPX V semicolon -74 -KPX V period -129 -KPX V o -129 -KPX V i -60 -KPX V hyphen -100 -KPX V e -111 -KPX V comma -129 -KPX V colon -74 -KPX V a -111 -KPX V O -40 -KPX V G -15 -KPX V A -135 - -KPX W y -73 -KPX W u -50 -KPX W semicolon -37 -KPX W period -92 -KPX W o -80 -KPX W i -40 -KPX W hyphen -65 -KPX W h 0 -KPX W e -80 -KPX W comma -92 -KPX W colon -37 -KPX W a -80 -KPX W O -10 -KPX W A -120 - -KPX Y u -111 -KPX Y semicolon -92 -KPX Y period -129 -KPX Y o -110 -KPX Y i -55 -KPX Y hyphen -111 -KPX Y e -100 -KPX Y comma -129 -KPX Y colon -92 -KPX Y a -100 -KPX Y O -30 -KPX Y A -120 - -KPX a y 0 -KPX a w -15 -KPX a v -20 -KPX a t 0 -KPX a p 0 -KPX a g 0 -KPX a b 0 - -KPX b y 0 -KPX b v -15 -KPX b u -20 -KPX b period -40 -KPX b l 0 -KPX b comma 0 -KPX b b 0 - -KPX c y -15 -KPX c period 0 -KPX c l 0 -KPX c k 0 -KPX c h 0 -KPX c comma 0 - -KPX colon space 0 - -KPX comma space 0 -KPX comma quoteright -70 -KPX comma quotedblright -70 - -KPX d y 0 -KPX d w 0 -KPX d v 0 -KPX d period 0 -KPX d d 0 -KPX d comma 0 - -KPX e y -15 -KPX e x -15 -KPX e w -25 -KPX e v -25 -KPX e period 0 -KPX e p 0 -KPX e g -15 -KPX e comma 0 -KPX e b 0 - -KPX f quoteright 55 -KPX f quotedblright 0 -KPX f period 0 -KPX f o 0 -KPX f l 0 -KPX f i -20 -KPX f f -25 -KPX f e 0 -KPX f dotlessi -50 -KPX f comma 0 -KPX f a -10 - -KPX g y 0 -KPX g r 0 -KPX g period 0 -KPX g o 0 -KPX g i 0 -KPX g g 0 -KPX g e 0 -KPX g comma 0 -KPX g a -5 - -KPX h y -5 - -KPX i v -25 - -KPX k y -15 -KPX k o -10 -KPX k e -10 - -KPX l y 0 -KPX l w -10 - -KPX m y 0 -KPX m u 0 - -KPX n y -15 -KPX n v -40 -KPX n u 0 - -KPX o y -10 -KPX o x 0 -KPX o w -25 -KPX o v -15 -KPX o g 0 - -KPX p y -10 - -KPX period quoteright -70 -KPX period quotedblright -70 - -KPX quotedblleft quoteleft 0 -KPX quotedblleft A -80 - -KPX quotedblright space 0 - -KPX quoteleft quoteleft -74 -KPX quoteleft A -80 - -KPX quoteright v -50 -KPX quoteright t -18 -KPX quoteright space -74 -KPX quoteright s -55 -KPX quoteright r -50 -KPX quoteright quoteright -74 -KPX quoteright quotedblright 0 -KPX quoteright l -10 -KPX quoteright d -50 - -KPX r y 0 -KPX r v 0 -KPX r u 0 -KPX r t 0 -KPX r s 0 -KPX r r 0 -KPX r q 0 -KPX r period -55 -KPX r p 0 -KPX r o 0 -KPX r n 0 -KPX r m 0 -KPX r l 0 -KPX r k 0 -KPX r i 0 -KPX r hyphen -20 -KPX r g -18 -KPX r e 0 -KPX r d 0 -KPX r comma -40 -KPX r c 0 -KPX r a 0 - -KPX s w 0 - -KPX space quoteleft 0 -KPX space quotedblleft 0 -KPX space Y -90 -KPX space W -30 -KPX space V -50 -KPX space T -18 -KPX space A -55 - -KPX v period -65 -KPX v o -20 -KPX v e -15 -KPX v comma -65 -KPX v a -25 - -KPX w period -65 -KPX w o -10 -KPX w h 0 -KPX w e 0 -KPX w comma -65 -KPX w a -10 - -KPX x e -15 - -KPX y period -65 -KPX y o 0 -KPX y e 0 -KPX y comma -65 -KPX y a 0 - -KPX z o 0 -KPX z e 0 -EndKernPairs -EndKernData -StartComposites 58 -CC Aacute 2 ; PCC A 0 0 ; PCC acute 195 212 ; -CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 195 212 ; -CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 195 212 ; -CC Agrave 2 ; PCC A 0 0 ; PCC grave 195 212 ; -CC Aring 2 ; PCC A 0 0 ; PCC ring 185 187 ; -CC Atilde 2 ; PCC A 0 0 ; PCC tilde 195 212 ; -CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 167 0 ; -CC Eacute 2 ; PCC E 0 0 ; PCC acute 139 212 ; -CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 139 212 ; -CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 139 212 ; -CC Egrave 2 ; PCC E 0 0 ; PCC grave 139 212 ; -CC Iacute 2 ; PCC I 0 0 ; PCC acute 0 212 ; -CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 0 212 ; -CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 0 212 ; -CC Igrave 2 ; PCC I 0 0 ; PCC grave 0 212 ; -CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 195 212 ; -CC Oacute 2 ; PCC O 0 0 ; PCC acute 195 212 ; -CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 195 212 ; -CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 195 212 ; -CC Ograve 2 ; PCC O 0 0 ; PCC grave 195 212 ; -CC Otilde 2 ; PCC O 0 0 ; PCC tilde 195 212 ; -CC Scaron 2 ; PCC S 0 0 ; PCC caron 112 212 ; -CC Uacute 2 ; PCC U 0 0 ; PCC acute 195 212 ; -CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 195 212 ; -CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 195 212 ; -CC Ugrave 2 ; PCC U 0 0 ; PCC grave 195 212 ; -CC Yacute 2 ; PCC Y 0 0 ; PCC acute 195 212 ; -CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 195 212 ; -CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 139 212 ; -CC aacute 2 ; PCC a 0 0 ; PCC acute 56 0 ; -CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 56 0 ; -CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 56 0 ; -CC agrave 2 ; PCC a 0 0 ; PCC grave 56 0 ; -CC aring 2 ; PCC a 0 0 ; PCC ring 56 0 ; -CC atilde 2 ; PCC a 0 0 ; PCC tilde 56 0 ; -CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 56 0 ; -CC eacute 2 ; PCC e 0 0 ; PCC acute 56 0 ; -CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 56 0 ; -CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 56 0 ; -CC egrave 2 ; PCC e 0 0 ; PCC grave 56 0 ; -CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ; -CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 0 ; -CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ; -CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ; -CC ntilde 2 ; PCC n 0 0 ; PCC tilde 84 0 ; -CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ; -CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 0 ; -CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ; -CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ; -CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 0 ; -CC scaron 2 ; PCC s 0 0 ; PCC caron 28 0 ; -CC uacute 2 ; PCC u 0 0 ; PCC acute 84 0 ; -CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 84 0 ; -CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 84 0 ; -CC ugrave 2 ; PCC u 0 0 ; PCC grave 84 0 ; -CC yacute 2 ; PCC y 0 0 ; PCC acute 84 0 ; -CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ; -CC zcaron 2 ; PCC z 0 0 ; PCC caron 56 0 ; -EndComposites -EndFontMetrics diff --git a/configure.ac b/configure.ac index dad55e2c..fd60137c 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. dnl Initialize. AC_PREREQ(2.60) -AC_INIT([pspp],[0.7.2],[bug-gnu-pspp@gnu.org]) +AC_INIT([pspp],[0.7.3],[bug-gnu-pspp@gnu.org]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE @@ -41,29 +41,41 @@ dnl Checks for libraries. AC_SYS_LARGEFILE AC_SEARCH_LIBS([sin], [m]) AC_SEARCH_LIBS([dcgettext], [intl]) -PSPP_LIBPLOT PSPP_LC_PAPER -AM_CONDITIONAL(WITHCHARTS, test x"$with_libplot" != x"no") AC_ARG_VAR([PSPP_LDFLAGS], [linker flags to be used for linking the pspp binary only]) AC_ARG_VAR([PSPPIRE_LDFLAGS], [linker flags to be used for linking the psppire binary only]) - -AC_ARG_WITH( - gui, - [AS_HELP_STRING([--without-gui], [don't build the PSPPIRE gui])]) - -required_gtk_version=2.12 - -if test x"$with_gui" != x"no" ; then - PKG_CHECK_MODULES(GTK, gtk+-2.0 >= $required_gtk_version,, - [PSPP_REQUIRED_PREREQ([gtk+ 2.0 v$required_gtk_version or later (or use --without-gui)])]) +# Support for Cairo and Pango. +AC_ARG_WITH([cairo], + [AS_HELP_STRING( + [--without-cairo], + [Don't build support for charts (using Cairo and Pango); + implies --without-gui])], + [], [with_cairo=yes]) +AM_CONDITIONAL([HAVE_CAIRO], [test "$with_cairo" != no]) +if test "$with_cairo" != no; then + PKG_CHECK_MODULES([CAIRO], [cairo >= 1.5 pango >= 1.20 pangocairo], + [CPPFLAGS="$CPPFLAGS $CAIRO_CFLAGS" + AC_DEFINE([HAVE_CAIRO], 1, + [Define to 1 if Cairo and Pango are available.])], + [PSPP_REQUIRED_PREREQ([cairo 1.5 or later and pango 1.20 or later (or use --without-cairo)])]) AC_PATH_PROG([XMLLINT], [xmllint], [echo], [$PATH]) AC_SUBST(XMLLINT) fi -AM_CONDITIONAL(WITHGUI, test x"$with_gui" != x"no") +# Support for GUI. +AC_ARG_WITH([gui], + [AS_HELP_STRING([--without-gui], + [Don't build the PSPPIRE GUI (using GTK+)])], + [], [with_gui=yes]) +AM_CONDITIONAL([HAVE_GUI], + [test "$with_cairo" != no && test "$with_gui" != "no"]) +if test "$with_cairo" != no && test "$with_gui" != "no"; then + PKG_CHECK_MODULES([GTK], [gtk+-2.0 >= 2.12], [], + [PSPP_REQUIRED_PREREQ([gtk+ 2.0 version 2.12 or later (or use --without-gui)])]) +fi dnl Checks needed for psql reader diff --git a/doc/configuring.texi b/doc/configuring.texi index 164d9ab1..357388c8 100644 --- a/doc/configuring.texi +++ b/doc/configuring.texi @@ -11,7 +11,7 @@ This chapter describe how to configure PSPP for your system. * Configuration files:: How configuration files are read. * Environment variables:: All about environment variables. * Output devices:: Describing your terminal(s) and printer(s). -* PostScript driver class:: Configuration of PostScript devices. +* Cairo driver class:: Configuration of Cairo devices. * ASCII driver class:: Configuration of character-code devices. * HTML driver class:: Configuration for HTML output. * Miscellaneous configuring:: Even more configuration variables. @@ -324,7 +324,7 @@ A unique identifier, used to determine whether to enable the driver. @item class name One of the predefined driver classes supported by PSPP. The -currently supported driver classes include `postscript' and `ascii'. +currently supported driver classes include `cairo' and `ascii'. @item device type(s) Zero or more of the following keywords, delimited by spaces: @@ -540,26 +540,27 @@ interpreted; only the lower 8 bits are used. Tokens, outside of quoted strings, are delimited by white space or equals signs. -@node PostScript driver class -@section The PostScript driver class +@node Cairo driver class +@section The Cairo driver class -The @code{postscript} driver class is used to produce output that is -acceptable to PostScript printers and other interpreters. +The @code{cairo} driver class can produce output in PDF, PostScript, +and SVG formats. It has full support for international character +sets. + +The Cairo driver is only available if your copy of PSPP was built with +the Cairo library. The available options are listed below. @table @code @item output-file=@var{file-name} -File to which output should be sent. This can be an ordinary file name -(i.e., @code{"pspp.ps"}), a pipe (i.e., @code{"|lpr"}), or -stdout (@code{"-"}). Default: @code{"pspp.ps"}. +File to which output should be sent. Default: @code{"pspp.pdf"}. -@item headers=@var{boolean} +@item output-type=@var{output-type} -Controls whether the standard headers showing the time and date and -title and subtitle are printed at the top of each page. Default: -@code{on}. +Type of output to write to the output file, one of @code{pdf}, +@code{ps}, or @code{svg}. Default: @code{pdf}. @item paper-size=@var{paper-size} @@ -578,6 +579,12 @@ assumed. Either @code{portrait} or @code{landscape}. Default: @code{portrait}. +@item headers=@var{boolean} + +Controls whether the standard headers showing the time and date and +title and subtitle are printed at the top of each page. Default: +@code{on}. + @item left-margin=@var{dimension} @itemx right-margin=@var{dimension} @itemx top-margin=@var{dimension} @@ -587,29 +594,17 @@ Sets the margins around the page. The headers, if enabled, are not included in the margins; they are in addition to the margins. For a description of dimensions, see @ref{Dimensions}. Default: @code{0.5in}. -@item prop-font=@var{afm-file}[,@var{font-file}[,@var{encoding-file}]] -@itemx emph-font=@var{afm-file}[,@var{font-file}[,@var{encoding-file}]] -@itemx fixed-font=@var{afm-file}[,@var{font-file}[,@var{encoding-file}]] +@item prop-font=@var{font-name} +@itemx emph-font=@var{font-name} +@itemx fixed-font=@var{font-name} Sets the font used for proportional, emphasized, or fixed-pitch text. -The only required value is @var{afm-file}, the AFM file for the font. - -If specified, @var{font-file} will be downloaded to the printer at the -beginning of the print job. The font file may be in PFA or PFB format. - -The font is reencoded as specified in @var{encoding-file}, if specified. -Each line in @var{encoding-file} should consist of a PostScript -character name and a decimal encoding value (between 0 and 255), -separated by white space. Blank lines and comments introduced by -@samp{#} are also allowed. - -The files specified on these options are located as follows. If -the file name begins with @samp{/}, then it is taken as an absolute -path. Otherwise, PSPP searches its configuration path for the specified -name prefixed by @code{psfonts/} (@pxref{File locations}). +Most systems support CSS-like font names such as ``serif'' and +``monospace'', but a wide range of system-specific font are likely to +be supported as well. -Default: proportional font @code{Times-Roman.afm}, emphasis font -@code{Times-Italic.afm}, fixed-pitch font @code{Courier.afm}. +Default: proportional font @code{serif}, emphasis font @code{serif +italic}, fixed-pitch font @code{monospace}. @item font-size=@var{font-size} @@ -653,14 +648,11 @@ a single @samp{#}, which is replaced by the chart number. Default: @file{"pspp-#.png"}. @item chart-type=@var{type}. -Type of charts to output. Available types typically include @samp{X}, -@samp{png}, @samp{gif}, @samp{svg}, @samp{ps}, @samp{cgm}, @samp{fig}, -@samp{pcl}, @samp{hpgl}, @samp{regis}, @samp{tek}, and @samp{meta}. +Type of charts to output, either @samp{png} or @samp{none}. Default: @samp{png}. -You may specify @samp{none} to disable chart output. Charts are also -disabled if your installation of PSPP was compiled without -@code{libplot}. +Charts are always disabled if your installation of PSPP was compiled +without the @code{cairo} library. @item paginate=@var{boolean} diff --git a/lib/automake.mk b/lib/automake.mk index 6b20c674..9bde4afc 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -2,7 +2,7 @@ include $(top_srcdir)/lib/linreg/automake.mk -if WITHGUI +if HAVE_GUI include $(top_srcdir)/lib/gtk-contrib/automake.mk endif diff --git a/perl-module/lib/PSPP.pm b/perl-module/lib/PSPP.pm index 2dccd10a..fd2f5a5f 100644 --- a/perl-module/lib/PSPP.pm +++ b/perl-module/lib/PSPP.pm @@ -21,7 +21,7 @@ None by default. =cut BEGIN { - $PSPP::VERSION='0.7.2'; + $PSPP::VERSION='0.7.3'; require XSLoader; XSLoader::load('PSPP', $PSPP::VERSION); } diff --git a/src/data/automake.mk b/src/data/automake.mk index a249f5ad..ebfb680a 100644 --- a/src/data/automake.mk +++ b/src/data/automake.mk @@ -25,7 +25,9 @@ src_data_libdata_la_SOURCES = \ src/data/caseinit.c \ src/data/caseinit.h \ src/data/casereader-filter.c \ + src/data/casereader-project.c \ src/data/casereader-provider.h \ + src/data/casereader-select.c \ src/data/casereader-translator.c \ src/data/casereader.c \ src/data/casereader.h \ diff --git a/src/data/caseproto.c b/src/data/caseproto.c index 1a40213a..9837013a 100644 --- a/src/data/caseproto.c +++ b/src/data/caseproto.c @@ -320,7 +320,7 @@ caseproto_free__ (struct caseproto *proto) void caseproto_refresh_long_string_cache__ (const struct caseproto *proto_) { - struct caseproto *proto = (struct caseproto *) proto_; + struct caseproto *proto = CONST_CAST (struct caseproto *, proto_); size_t n, i; assert (proto->long_strings == NULL); diff --git a/src/data/caseproto.h b/src/data/caseproto.h index b85a9f32..b0f45c41 100644 --- a/src/data/caseproto.h +++ b/src/data/caseproto.h @@ -22,6 +22,7 @@ #include #include #include +#include #include /* Case prototype. @@ -144,7 +145,7 @@ void caseproto_free__ (struct caseproto *); static inline struct caseproto * caseproto_ref (const struct caseproto *proto_) { - struct caseproto *proto = (struct caseproto *) proto_; + struct caseproto *proto = CONST_CAST (struct caseproto *, proto_); proto->ref_cnt++; return proto; } diff --git a/src/data/casereader-project.c b/src/data/casereader-project.c new file mode 100644 index 00000000..116a3359 --- /dev/null +++ b/src/data/casereader-project.c @@ -0,0 +1,106 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include +#include + +#include "gl/xalloc.h" + +static bool +projection_is_no_op (const struct casereader *reader, const struct subcase *sc) +{ + size_t n = subcase_get_n_fields (sc); + size_t i; + + if (n != caseproto_get_n_widths (casereader_get_proto (reader))) + return false; + + for (i = 0; i < n; i++) + if (subcase_get_case_index (sc, i) != i) + return false; + + return true; +} + +struct casereader_project + { + struct subcase old_sc; + struct subcase new_sc; + }; + +static struct ccase * +project_case (struct ccase *old, casenumber idx UNUSED, const void *project_) +{ + const struct casereader_project *project = project_; + struct ccase *new = case_create (subcase_get_proto (&project->new_sc)); + subcase_copy (&project->old_sc, old, &project->new_sc, new); + case_unref (old); + return new; +} + +static bool +destroy_projection (void *project_) +{ + struct casereader_project *project = project_; + subcase_destroy (&project->old_sc); + subcase_destroy (&project->new_sc); + free (project); + return true; +} + +/* Returns a casereader in which each row is obtained by extracting the subcase + SC from the corresponding row of SUBREADER. */ +struct casereader * +casereader_project (struct casereader *subreader, const struct subcase *sc) +{ + if (projection_is_no_op (subreader, sc)) + return casereader_rename (subreader); + else + { + struct casereader_project *project = xmalloc (sizeof *project); + const struct caseproto *proto; + + subcase_clone (&project->old_sc, sc); + proto = subcase_get_proto (&project->old_sc); + + subcase_init_empty (&project->new_sc); + subcase_add_proto_always (&project->new_sc, proto); + + return casereader_translate_stateless (subreader, proto, + project_case, destroy_projection, + project); + } +} + +/* Returns a casereader in which each row is obtained by extracting the value + with index COLUMN from the corresponding row of SUBREADER. */ +struct casereader * +casereader_project_1 (struct casereader *subreader, int column) +{ + const struct caseproto *subproto = casereader_get_proto (subreader); + struct casereader *reader; + struct subcase sc; + + subcase_init (&sc, column, caseproto_get_width (subproto, column), + SC_ASCEND); + reader = casereader_project (subreader, &sc); + subcase_destroy (&sc); + + return reader; +} + diff --git a/src/data/casereader-select.c b/src/data/casereader-select.c new file mode 100644 index 00000000..a26ef674 --- /dev/null +++ b/src/data/casereader-select.c @@ -0,0 +1,81 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include "gl/xalloc.h" + +struct casereader_select + { + casenumber by; + casenumber i; + }; + +static bool +casereader_select_include (const struct ccase *c UNUSED, void *cs_) +{ + struct casereader_select *cs = cs_; + if (++cs->i >= cs->by) + { + cs->i = 0; + return true; + } + else + return false; +} + +static bool +casereader_select_destroy (void *cs_) +{ + struct casereader_select *cs = cs_; + free (cs); + return true; +} + +/* Returns a casereader that contains cases FIRST though LAST, exclusive, of + those within SUBREADER. (The first case in SUBREADER is number 0.) If BY + is greater than 1, then it specifies a step between cases, e.g. a BY value + of 2 causes the cases numbered FIRST + 1, FIRST + 3, FIRST + 5, and so on + to be omitted. + + The caller gives up ownership of SUBREADER, transferring it into this + function. */ +struct casereader * +casereader_select (struct casereader *subreader, + casenumber first, casenumber last, casenumber by) +{ + if (by == 0) + by = 1; + + casereader_advance (subreader, first); + if (last >= first) + casereader_truncate (subreader, (last - first) / by * by); + + if (by == 1) + return casereader_rename (subreader); + else + { + struct casereader_select *cs = xmalloc (sizeof *cs); + cs->by = by; + cs->i = 0; + return casereader_create_filter_func (subreader, + casereader_select_include, + casereader_select_destroy, + cs, NULL); + } +} diff --git a/src/data/casereader-translator.c b/src/data/casereader-translator.c index feffa15c..27ea4134 100644 --- a/src/data/casereader-translator.c +++ b/src/data/casereader-translator.c @@ -46,6 +46,11 @@ static const struct casereader_class casereader_translator_class; INPUT and auxiliary data AUX. TRANSLATE must destroy its input case. + TRANSLATE may be stateful, that is, the output for a given + case may depend on previous cases. If TRANSLATE is stateless, + then you may want to use casereader_translate_stateless + instead, since it sometimes performs better. + The cases returned by TRANSLATE must match OUTPUT_PROTO. When the translating casereader is destroyed, DESTROY will be @@ -106,7 +111,110 @@ static const struct casereader_class casereader_translator_class = NULL, NULL, }; + +/* Casereader that applies a user-supplied function to translate + each case into another in a stateless fashion. */ + +/* A statelessly translating casereader. */ +struct casereader_stateless_translator + { + struct casereader *subreader; /* Source of input cases. */ + + casenumber case_offset; + struct ccase *(*translate) (struct ccase *input, casenumber, + const void *aux); + bool (*destroy) (void *aux); + void *aux; + }; + +static const struct casereader_random_class +casereader_stateless_translator_class; + +/* Creates and returns a new casereader whose cases are produced by reading + from SUBREADER and passing through the TRANSLATE function. TRANSLATE must + takes ownership of its input case and returns a translated case, populating + the translated case based on INPUT and auxiliary data AUX. + + TRANSLATE must be stateless, that is, the output for a given case must not + depend on previous cases. This is because cases may be retrieved in + arbitrary order, and some cases may be retrieved multiple times, and some + cases may be skipped and never retrieved at all. If TRANSLATE is stateful, + use casereader_create_translator instead. + + The casenumber argument to the TRANSLATE function is the absolute case + number in SUBREADER, that is, 0 when the first case in SUBREADER is being + translated, 1 when the second case is being translated, and so on. + + The cases returned by TRANSLATE must match OUTPUT_PROTO. + + When the stateless translating casereader is destroyed, DESTROY will be + called to allow any auxiliary data maintained by TRANSLATE to be freed. + + After this function is called, SUBREADER must not ever again be referenced + directly. It will be destroyed automatically when the translating + casereader is destroyed. */ +struct casereader * +casereader_translate_stateless ( + struct casereader *subreader, + const struct caseproto *output_proto, + struct ccase *(*translate) (struct ccase *input, casenumber, + const void *aux), + bool (*destroy) (void *aux), + void *aux) +{ + struct casereader_stateless_translator *cst = xmalloc (sizeof *cst); + struct casereader *reader; + cst->subreader = casereader_rename (subreader); + cst->translate = translate; + cst->destroy = destroy; + cst->aux = aux; + reader = casereader_create_random ( + output_proto, casereader_get_case_cnt (cst->subreader), + &casereader_stateless_translator_class, cst); + taint_propagate (casereader_get_taint (cst->subreader), + casereader_get_taint (reader)); + return reader; +} + +/* Internal read function for stateless translating casereader. */ +static struct ccase * +casereader_stateless_translator_read (struct casereader *reader UNUSED, + void *cst_, casenumber idx) +{ + struct casereader_stateless_translator *cst = cst_; + struct ccase *tmp = casereader_peek (cst->subreader, idx); + if (tmp != NULL) + tmp = cst->translate (tmp, cst->case_offset + idx, cst->aux); + return tmp; +} + +/* Internal destroy function for translating casereader. */ +static void +casereader_stateless_translator_destroy (struct casereader *reader UNUSED, + void *cst_) +{ + struct casereader_stateless_translator *cst = cst_; + casereader_destroy (cst->subreader); + cst->destroy (cst->aux); + free (cst); +} + +static void +casereader_stateless_translator_advance (struct casereader *reader UNUSED, + void *cst_, casenumber cnt) +{ + struct casereader_stateless_translator *cst = cst_; + cst->case_offset += casereader_advance (cst->subreader, cnt); +} +/* Casereader class for stateless translating casereader. */ +static const struct casereader_random_class +casereader_stateless_translator_class = + { + casereader_stateless_translator_read, + casereader_stateless_translator_destroy, + casereader_stateless_translator_advance, + }; struct casereader_append_numeric diff --git a/src/data/casereader.c b/src/data/casereader.c index a1550ac5..57afff84 100644 --- a/src/data/casereader.c +++ b/src/data/casereader.c @@ -108,7 +108,7 @@ casereader_destroy (struct casereader *reader) struct casereader * casereader_clone (const struct casereader *reader_) { - struct casereader *reader = (struct casereader *) reader_; + struct casereader *reader = CONST_CAST (struct casereader *, reader_); struct casereader *clone; if ( reader == NULL ) return NULL; @@ -257,6 +257,19 @@ casereader_get_case_cnt (struct casereader *reader) return reader->case_cnt; } +static casenumber +casereader_count_cases__ (struct casereader *reader, casenumber max_cases) +{ + struct casereader *clone; + casenumber n_cases; + + clone = casereader_clone (reader); + n_cases = casereader_advance (clone, max_cases); + casereader_destroy (clone); + + return n_cases; +} + /* Returns the number of cases that will be read by successive calls to casereader_read for READER, assuming that no errors occur. Upon an error condition, the case count drops to 0, so @@ -270,22 +283,24 @@ casenumber casereader_count_cases (struct casereader *reader) { if (reader->case_cnt == CASENUMBER_MAX) - { - casenumber n_cases = 0; - struct ccase *c; - - struct casereader *clone = casereader_clone (reader); - - for (; (c = casereader_read (clone)) != NULL; case_unref (c)) - n_cases++; - - casereader_destroy (clone); - reader->case_cnt = n_cases; - } - + reader->case_cnt = casereader_count_cases__ (reader, CASENUMBER_MAX); return reader->case_cnt; } +/* Truncates READER to at most N cases. */ +void +casereader_truncate (struct casereader *reader, casenumber n) +{ + /* This could be optimized, if it ever becomes too expensive, by adding a + "max_cases" member to struct casereader. We could also add a "truncate" + function to the casereader implementation, to allow the casereader to + throw away data that cannot ever be read. */ + if (reader->case_cnt == CASENUMBER_MAX) + reader->case_cnt = casereader_count_cases__ (reader, n); + if (reader->case_cnt > n) + reader->case_cnt = n; +} + /* Returns the prototype for the cases in READER. The caller must not unref the returned prototype. */ const struct caseproto * @@ -294,6 +309,26 @@ casereader_get_proto (const struct casereader *reader) return reader->proto; } +/* Skips past N cases in READER, stopping when the last case in + READER has been read or on an input error. Returns the number + of cases successfully skipped. */ +casenumber +casereader_advance (struct casereader *reader, casenumber n) +{ + casenumber i; + + for (i = 0; i < n; i++) + { + struct ccase *c = casereader_read (reader); + if (c == NULL) + break; + case_unref (c); + } + + return i; +} + + /* Copies all the cases in READER to WRITER, propagating errors appropriately. */ void @@ -664,3 +699,42 @@ static const struct casereader_random_class shim_class = shim_destroy, shim_advance, }; + +static const struct casereader_class casereader_null_class; + +/* Returns a casereader with no cases. The casereader has the prototype + specified by PROTO. PROTO may be specified as a null pointer, in which case + the casereader has no variables. */ +struct casereader * +casereader_create_empty (const struct caseproto *proto_) +{ + struct casereader *reader; + struct caseproto *proto; + + proto = proto_ != NULL ? caseproto_ref (proto_) : caseproto_create (); + reader = casereader_create_sequential (NULL, proto, 0, + &casereader_null_class, NULL); + caseproto_unref (proto); + + return reader; +} + +static struct ccase * +casereader_null_read (struct casereader *reader UNUSED, void *aux UNUSED) +{ + return NULL; +} + +static void +casereader_null_destroy (struct casereader *reader UNUSED, void *aux UNUSED) +{ + /* Nothing to do. */ +} + +static const struct casereader_class casereader_null_class = + { + casereader_null_read, + casereader_null_destroy, + NULL, /* clone */ + NULL, /* peek */ + }; diff --git a/src/data/casereader.h b/src/data/casereader.h index 3b903bbf..a78afaeb 100644 --- a/src/data/casereader.h +++ b/src/data/casereader.h @@ -58,6 +58,7 @@ struct dictionary; struct casereader; struct casewriter; +struct subcase; struct ccase *casereader_read (struct casereader *); bool casereader_destroy (struct casereader *); @@ -77,10 +78,14 @@ const struct taint *casereader_get_taint (const struct casereader *); casenumber casereader_get_case_cnt (struct casereader *); casenumber casereader_count_cases (struct casereader *); +void casereader_truncate (struct casereader *, casenumber); const struct caseproto *casereader_get_proto (const struct casereader *); +casenumber casereader_advance (struct casereader *, casenumber); void casereader_transfer (struct casereader *, struct casewriter *); +struct casereader *casereader_create_empty (const struct caseproto *); + struct casereader * casereader_create_filter_func (struct casereader *, bool (*include) (const struct ccase *, @@ -112,6 +117,22 @@ casereader_create_translator (struct casereader *, bool (*destroy) (void *aux), void *aux); +struct casereader * +casereader_translate_stateless (struct casereader *, + const struct caseproto *output_proto, + struct ccase *(*translate) (struct ccase *, + casenumber idx, + const void *aux), + bool (*destroy) (void *aux), + void *aux); + +struct casereader *casereader_project (struct casereader *, + const struct subcase *); +struct casereader *casereader_project_1 (struct casereader *, int column); +struct casereader *casereader_select (struct casereader *, + casenumber first, casenumber last, + casenumber by); + /* A function which creates a numberic value from an existing case */ typedef double new_value_func (const struct ccase *, casenumber, void *); diff --git a/src/data/casewindow.c b/src/data/casewindow.c index 9b04b941..936b6aa9 100644 --- a/src/data/casewindow.c +++ b/src/data/casewindow.c @@ -168,7 +168,7 @@ casewindow_pop_tail (struct casewindow *cw, casenumber case_cnt) struct ccase * casewindow_get_case (const struct casewindow *cw_, casenumber case_idx) { - struct casewindow *cw = (struct casewindow *) cw_; + struct casewindow *cw = CONST_CAST (struct casewindow *, cw_); assert (case_idx >= 0 && case_idx < casewindow_get_case_cnt (cw)); if (casewindow_error (cw)) diff --git a/src/data/datasheet.c b/src/data/datasheet.c index fa24d8ce..4abc526f 100644 --- a/src/data/datasheet.c +++ b/src/data/datasheet.c @@ -275,7 +275,7 @@ datasheet_destroy (struct datasheet *ds) const struct caseproto * datasheet_get_proto (const struct datasheet *ds_) { - struct datasheet *ds = (struct datasheet *) ds_; + struct datasheet *ds = CONST_CAST (struct datasheet *, ds_); if (ds->proto == NULL) { size_t i; @@ -548,7 +548,7 @@ datasheet_get_row (const struct datasheet *ds, casenumber row) { size_t n_columns = datasheet_get_n_columns (ds); struct ccase *c = case_create (datasheet_get_proto (ds)); - if (rw_case ((struct datasheet *) ds, OP_READ, + if (rw_case (CONST_CAST (struct datasheet *, ds), OP_READ, row, 0, n_columns, case_data_all_rw (c))) return c; else @@ -582,7 +582,8 @@ datasheet_get_value (const struct datasheet *ds, casenumber row, size_t column, union value *value) { assert (row >= 0); - return rw_case ((struct datasheet *) ds, OP_READ, row, column, 1, value); + return rw_case (CONST_CAST (struct datasheet *, ds), OP_READ, + row, column, 1, value); } /* Stores VALUE into DS in the given ROW and COLUMN. VALUE must diff --git a/src/data/dictionary.c b/src/data/dictionary.c index ab653d87..1ddf5575 100644 --- a/src/data/dictionary.c +++ b/src/data/dictionary.c @@ -1016,7 +1016,7 @@ dict_set_case_limit (struct dictionary *d, casenumber case_limit) const struct caseproto * dict_get_proto (const struct dictionary *d_) { - struct dictionary *d = (struct dictionary *) d_; + struct dictionary *d = CONST_CAST (struct dictionary *, d_); if (d->proto == NULL) { size_t i; @@ -1375,7 +1375,7 @@ dict_clear_vectors (struct dictionary *d) struct attrset * dict_get_attributes (const struct dictionary *d) { - return (struct attrset *) &d->attributes; + return CONST_CAST (struct attrset *, &d->attributes); } /* Replaces D's attributes set by a copy of ATTRS. */ diff --git a/src/data/file-name.c b/src/data/file-name.c index 91229595..cf58b6db 100644 --- a/src/data/file-name.c +++ b/src/data/file-name.c @@ -63,13 +63,13 @@ fn_init (void) /* Functions for performing operations on file names. */ -/* Substitutes $variables in SRC, putting the result in DST, - properly handling the case where SRC is a substring of DST. - Variables are as defined by GETENV. Supports $var and ${var} - syntaxes; $$ substitutes as $. */ +/* Copies from SRC to DST, calling INSERT_VARIABLE to handle each + instance of $var or ${var} in SRC. $$ is replaced by $. */ void -fn_interp_vars (struct substring src, const char *(*getenv) (const char *), - struct string *dst_) +fn_interp_vars (struct substring src, + void (*insert_variable) (const char *var, + struct string *dst, void *aux), + void *aux, struct string *dst_) { struct string dst = DS_EMPTY_INITIALIZER; int c; @@ -84,8 +84,7 @@ fn_interp_vars (struct substring src, const char *(*getenv) (const char *), else { struct substring var_name; - size_t start; - const char *value; + char *var; if (ss_match_char (&src, '(')) ss_get_until (&src, ')', &var_name); @@ -95,12 +94,9 @@ fn_interp_vars (struct substring src, const char *(*getenv) (const char *), ss_get_chars (&src, MAX (1, ss_span (src, ss_cstr (CC_ALNUM))), &var_name); - start = ds_length (&dst); - ds_put_substring (&dst, var_name); - value = getenv (ds_cstr (&dst) + start); - ds_truncate (&dst, start); - - ds_put_cstr (&dst, value); + var = ss_xstrdup (var_name); + insert_variable (var, &dst, aux); + free (var); } } @@ -108,6 +104,14 @@ fn_interp_vars (struct substring src, const char *(*getenv) (const char *), ds_destroy (&dst); } +static void +insert_env_var (const char *var, struct string *dst, void *aux UNUSED) +{ + const char *value = fn_getenv (var); + if (value != NULL) + ds_put_cstr (dst, value); +} + /* Searches for a configuration file with name NAME in the path given by PATH, which is environment-interpolated. Directories in PATH are delimited by ':'. Returns the @@ -126,7 +130,7 @@ fn_search_path (const char *base_name, const char *path_) /* Interpolate environment variables. */ ds_init_cstr (&path, path_); - fn_interp_vars (ds_ss (&path), fn_getenv, &path); + fn_interp_vars (ds_ss (&path), insert_env_var, NULL, &path); verbose_msg (2, _("searching for \"%s\" in path \"%s\""), base_name, ds_cstr (&path)); diff --git a/src/data/file-name.h b/src/data/file-name.h index d34bd419..327d716e 100644 --- a/src/data/file-name.h +++ b/src/data/file-name.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,8 +28,9 @@ extern const char *config_path; void fn_init (void); void fn_interp_vars (struct substring src, - const char *(*getenv) (const char *), - struct string *dst); + void (*insert_variable) (const char *var, + struct string *dst, void *aux), + void *aux, struct string *dst); char *fn_search_path (const char *base_name, const char *path); char *fn_dir_name (const char *fn); char *fn_extension (const char *fn); diff --git a/src/data/procedure.c b/src/data/procedure.c index b762214d..5e013a14 100644 --- a/src/data/procedure.c +++ b/src/data/procedure.c @@ -682,7 +682,7 @@ dataset_end_of_command (struct dataset *ds) else { const struct taint *taint = casereader_get_taint (ds->source); - taint_reset_successor_taint ((struct taint *) taint); + taint_reset_successor_taint (CONST_CAST (struct taint *, taint)); assert (!taint_has_tainted_successor (taint)); } } diff --git a/src/data/subcase.c b/src/data/subcase.c index 6ffaa4c2..32056215 100644 --- a/src/data/subcase.c +++ b/src/data/subcase.c @@ -99,6 +99,27 @@ subcase_destroy (struct subcase *sc) caseproto_unref (sc->proto); } +/* Returns true if VAR already has a field in SC, + false otherwise. */ +bool +subcase_contains_var (const struct subcase *sc, const struct variable *var) +{ + return subcase_contains (sc, var_get_case_index (var)); +} + +/* Returns true if CASE_INDEX already has a field in SC, + false otherwise. */ +bool +subcase_contains (const struct subcase *sc, int case_index) +{ + size_t i; + + for (i = 0; i < sc->n_fields; i++) + if (sc->fields[i].case_index == case_index) + return true; + + return false; +} /* Add a field for VAR to SC, with DIRECTION as the sort order. Returns true if successful, false if VAR already has a field @@ -107,8 +128,13 @@ bool subcase_add_var (struct subcase *sc, const struct variable *var, enum subcase_direction direction) { - return subcase_add (sc, var_get_case_index (var), - var_get_width (var), direction); + if (!subcase_contains_var (sc, var)) + { + subcase_add_var_always (sc, var, direction); + return true; + } + else + return false; } /* Add a field for CASE_INDEX, WIDTH to SC, with DIRECTION as the sort order. @@ -116,14 +142,35 @@ subcase_add_var (struct subcase *sc, const struct variable *var, in SC. */ bool subcase_add (struct subcase *sc, int case_index, int width, - enum subcase_direction direction) + enum subcase_direction direction) { - struct subcase_field *field; - size_t i; + if (!subcase_contains (sc, case_index)) + { + subcase_add_always (sc, case_index, width, direction); + return true; + } + else + return false; +} - for (i = 0; i < sc->n_fields; i++) - if (sc->fields[i].case_index == case_index) - return false; +/* Add a field for VAR to SC, with DIRECTION as the sort order, + regardless of whether VAR already has a field in SC. */ +void +subcase_add_var_always (struct subcase *sc, const struct variable *var, + enum subcase_direction direction) +{ + return subcase_add_always (sc, var_get_case_index (var), + var_get_width (var), direction); +} + +/* Add a field for CASE_INDEX, WIDTH to SC, with DIRECTION as the + sort order, regardless of whether CASE_INDEX already has a + field in SC. */ +void +subcase_add_always (struct subcase *sc, int case_index, int width, + enum subcase_direction direction) +{ + struct subcase_field *field; sc->fields = xnrealloc (sc->fields, sc->n_fields + 1, sizeof *sc->fields); field = &sc->fields[sc->n_fields++]; @@ -131,7 +178,27 @@ subcase_add (struct subcase *sc, int case_index, int width, field->width = width; field->direction = direction; invalidate_proto (sc); - return true; +} + +/* Adds a field to SC for each column in PROTO, so that SC + contains all of the columns in PROTO in the same order as a + case conforming to PROTO. The fields are added with + ascending direction. */ +void +subcase_add_proto_always (struct subcase *sc, const struct caseproto *proto) +{ + size_t n = caseproto_get_n_widths (proto); + size_t i; + + sc->fields = xnrealloc (sc->fields, sc->n_fields + n, sizeof *sc->fields); + for (i = 0; i < n; i++) + { + struct subcase_field *field = &sc->fields[sc->n_fields++]; + field->case_index = i; + field->width = caseproto_get_width (proto, i); + field->direction = SC_ASCEND; + } + invalidate_proto (sc); } /* Obtains a caseproto for a case described by SC. The caller @@ -139,7 +206,7 @@ subcase_add (struct subcase *sc, int case_index, int width, const struct caseproto * subcase_get_proto (const struct subcase *sc_) { - struct subcase *sc = (struct subcase *) sc_; + struct subcase *sc = CONST_CAST (struct subcase *, sc_); if (sc->proto == NULL) { diff --git a/src/data/subcase.h b/src/data/subcase.h index 6e59da1d..71bf6fd7 100644 --- a/src/data/subcase.h +++ b/src/data/subcase.h @@ -60,17 +60,27 @@ void subcase_clone (struct subcase *, const struct subcase *); void subcase_clear (struct subcase *); void subcase_destroy (struct subcase *); -bool subcase_add (struct subcase *sc, int index, int width, - enum subcase_direction direction); +bool subcase_contains (const struct subcase *, int case_index); +bool subcase_contains_var (const struct subcase *, const struct variable *); +bool subcase_add (struct subcase *, int case_index, int width, + enum subcase_direction direction); bool subcase_add_var (struct subcase *, const struct variable *, enum subcase_direction); +void subcase_add_always (struct subcase *sc, int case_index, int width, + enum subcase_direction direction); +void subcase_add_var_always (struct subcase *, const struct variable *, + enum subcase_direction); +void subcase_add_proto_always (struct subcase *, const struct caseproto *); + const struct caseproto *subcase_get_proto (const struct subcase *); static inline bool subcase_is_empty (const struct subcase *); static inline size_t subcase_get_n_fields (const struct subcase *); +static inline size_t subcase_get_case_index (const struct subcase *, + size_t idx); static inline enum subcase_direction subcase_get_direction ( const struct subcase *, size_t idx); @@ -100,6 +110,12 @@ bool subcase_equal_cx (const struct subcase *, bool subcase_equal_xx (const struct subcase *, const union value *a, const union value *b); +static inline size_t +subcase_get_case_index (const struct subcase *sc, size_t idx) +{ + return sc->fields[idx].case_index; +} + static inline enum subcase_direction subcase_get_direction (const struct subcase *sc, size_t idx) { diff --git a/src/data/value-labels.c b/src/data/value-labels.c index c8061f7b..0fe829ce 100644 --- a/src/data/value-labels.c +++ b/src/data/value-labels.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -169,7 +170,7 @@ void val_labs_replace (struct val_labs *vls, const union value *value, const char *label) { - struct val_lab *vl = (struct val_lab *) val_labs_lookup (vls, value); + struct val_lab *vl = val_labs_lookup (vls, value); if (vl != NULL) { atom_destroy (vl->label); @@ -181,9 +182,8 @@ val_labs_replace (struct val_labs *vls, const union value *value, /* Removes LABEL from VLS. */ void -val_labs_remove (struct val_labs *vls, const struct val_lab *label_) +val_labs_remove (struct val_labs *vls, struct val_lab *label) { - struct val_lab *label = (struct val_lab *) label_; hmap_delete (&vls->labels, &label->node); value_destroy (&label->value, vls->width); atom_destroy (label->label); @@ -203,7 +203,7 @@ val_labs_find (const struct val_labs *vls, const union value *value) /* Searches VLS for a value label for VALUE. If successful, returns the value label; otherwise, returns a null pointer. Returns a null pointer if VLS is null. */ -const struct val_lab * +struct val_lab * val_labs_lookup (const struct val_labs *vls, const union value *value) { if (vls != NULL) diff --git a/src/data/value-labels.h b/src/data/value-labels.h index 53d13a38..460ab84c 100644 --- a/src/data/value-labels.h +++ b/src/data/value-labels.h @@ -70,7 +70,7 @@ size_t val_labs_count (const struct val_labs *); /* Looking up value labels. */ const char *val_labs_find (const struct val_labs *, const union value *); -const struct val_lab *val_labs_lookup (const struct val_labs *, +struct val_lab *val_labs_lookup (const struct val_labs *, const union value *); /* Basic properties. */ @@ -82,7 +82,7 @@ void val_labs_set_width (struct val_labs *, int new_width); /* Adding value labels. */ bool val_labs_add (struct val_labs *, const union value *, const char *); void val_labs_replace (struct val_labs *, const union value *, const char *); -void val_labs_remove (struct val_labs *, const struct val_lab *); +void val_labs_remove (struct val_labs *, struct val_lab *); /* Iterating through value labels. */ const struct val_lab *val_labs_first (const struct val_labs *); diff --git a/src/data/variable.c b/src/data/variable.c index d1e30864..05edc57e 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -957,7 +957,7 @@ void * var_attach_aux (const struct variable *v_, void *aux, void (*aux_dtor) (struct variable *)) { - struct variable *v = (struct variable *) v_ ; /* cast away const */ + struct variable *v = CONST_CAST (struct variable *, v_); assert (v->aux == NULL); assert (aux != NULL); v->aux = aux; @@ -1015,7 +1015,7 @@ var_get_obs_vals (const struct variable *v) void var_set_obs_vals (const struct variable *v_, struct cat_vals *cat_vals) { - struct variable *v = (struct variable *) v_ ; /* cast away const */ + struct variable *v = CONST_CAST (struct variable *, v_ ); cat_stored_values_destroy (v->obs_vals); v->obs_vals = cat_vals; } @@ -1035,7 +1035,7 @@ var_has_obs_vals (const struct variable *v) struct attrset * var_get_attributes (const struct variable *v) { - return (struct attrset *) &v->attributes; + return CONST_CAST (struct attrset *, &v->attributes); } /* Replaces variable V's attributes set by a copy of ATTRS. */ diff --git a/src/language/automake.mk b/src/language/automake.mk index 4210b7fc..3052b523 100644 --- a/src/language/automake.mk +++ b/src/language/automake.mk @@ -13,9 +13,6 @@ include $(top_srcdir)/src/language/expressions/automake.mk noinst_LTLIBRARIES += src/language/liblanguage.la -src_language_liblanguage_la_LIBADD = \ - src/output/charts/libcharts.la - src_language_liblanguage_la_SOURCES = \ src/language/syntax-file.c \ src/language/syntax-file.h \ diff --git a/src/language/command.c b/src/language/command.c index 32dba0b4..4c3612fb 100644 --- a/src/language/command.c +++ b/src/language/command.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #if HAVE_SYS_WAIT_H @@ -231,9 +230,9 @@ do_parse_command (struct lexer *lexer, /* Execute command. */ msg_set_command_name (command->name); - tab_set_command_name (command->name); + som_set_command_name (command->name); result = command->function (lexer, ds); - tab_set_command_name (NULL); + som_set_command_name (NULL); msg_set_command_name (NULL); assert (cmd_result_is_valid (result)); diff --git a/src/language/control/repeat.c b/src/language/control/repeat.c index 32847bb4..cb608f76 100644 --- a/src/language/control/repeat.c +++ b/src/language/control/repeat.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -512,10 +513,10 @@ find_substitution (struct repeat_block *block, struct substring name) /* Makes appropriate DO REPEAT macro substitutions within the repeated lines. */ static void -do_repeat_filter (struct getl_interface *block_, - struct string *line) +do_repeat_filter (struct getl_interface *interface, struct string *line) { - struct repeat_block *block = (struct repeat_block *) block_; + struct repeat_block *block + = UP_CAST (interface, struct repeat_block, parent); bool in_apos, in_quote, dot; struct substring input; struct string output; @@ -557,7 +558,8 @@ do_repeat_filter (struct getl_interface *block_, static struct repeat_line * current_line (const struct getl_interface *interface) { - struct repeat_block *block = (struct repeat_block *) interface; + struct repeat_block *block + = UP_CAST (interface, struct repeat_block, parent); return (block->cur_line != ll_null (&block->lines) ? ll_data (block->cur_line, struct repeat_line, ll) : NULL); @@ -570,7 +572,8 @@ static bool do_repeat_read (struct getl_interface *interface, struct string *output) { - struct repeat_block *block = (struct repeat_block *) interface; + struct repeat_block *block + = UP_CAST (interface, struct repeat_block, parent); struct repeat_line *line; block->cur_line = ll_next (block->cur_line); @@ -591,9 +594,10 @@ do_repeat_read (struct getl_interface *interface, /* Frees a DO REPEAT block. Called by getl to close out the DO REPEAT block. */ static void -do_repeat_close (struct getl_interface *block_) +do_repeat_close (struct getl_interface *interface) { - struct repeat_block *block = (struct repeat_block *) block_; + struct repeat_block *block + = UP_CAST (interface, struct repeat_block, parent); pool_destroy (block->pool); } diff --git a/src/language/data-io/data-parser.c b/src/language/data-io/data-parser.c index 020f8e4c..fe78aeb3 100644 --- a/src/language/data-io/data-parser.c +++ b/src/language/data-io/data-parser.c @@ -644,8 +644,8 @@ dump_fixed_table (const struct data_parser *parser, struct tab_table *t; size_t i; - t = tab_create (4, parser->field_cnt + 1, 0); - tab_columns (t, TAB_COL_DOWN, 1); + t = tab_create (4, parser->field_cnt + 1); + tab_columns (t, TAB_COL_DOWN); tab_headers (t, 0, 0, 1, 0); tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Variable")); tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Record")); @@ -653,7 +653,7 @@ dump_fixed_table (const struct data_parser *parser, tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Format")); tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 3, parser->field_cnt); tab_hline (t, TAL_2, 0, 3, 1); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); for (i = 0; i < parser->field_cnt; i++) { @@ -685,14 +685,14 @@ dump_delimited_table (const struct data_parser *parser, struct tab_table *t; size_t i; - t = tab_create (2, parser->field_cnt + 1, 0); - tab_columns (t, TAB_COL_DOWN, 1); + t = tab_create (2, parser->field_cnt + 1); + tab_columns (t, TAB_COL_DOWN); tab_headers (t, 0, 0, 1, 0); tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Variable")); tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Format")); tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 1, parser->field_cnt); tab_hline (t, TAL_2, 0, 1, 1); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); for (i = 0; i < parser->field_cnt; i++) { diff --git a/src/language/data-io/list.q b/src/language/data-io/list.q index c3f9b088..614fa127 100644 --- a/src/language/data-io/list.q +++ b/src/language/data-io/list.q @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -63,8 +63,10 @@ /* (functions) */ /* Layout for one output driver. */ -struct list_ext +struct list_target { + struct ll ll; + struct outp_driver *driver; int type; /* 0=Values and labels fit across the page. */ size_t n_vertical; /* Number of labels to list vertically. */ size_t header_rows; /* Number of header rows. */ @@ -84,11 +86,12 @@ static void write_line (struct outp_driver *d, const char *s); /* Other functions. */ static void list_case (const struct ccase *, casenumber case_idx, - const struct dataset *); -static void determine_layout (void); -static void clean_up (void); -static void write_header (struct outp_driver *); -static void write_all_headers (struct casereader *, const struct dataset*); + const struct dataset *, struct ll_list *targets); +static void determine_layout (struct ll_list *targets); +static void clean_up (struct ll_list *targets); +static void write_header (struct list_target *); +static void write_all_headers (struct casereader *, const struct dataset *, + struct ll_list *targets); /* Returns the number of text lines that can fit on the remainder of the page. */ @@ -136,6 +139,7 @@ cmd_list (struct lexer *lexer, struct dataset *ds) struct variable *casenum_var = NULL; struct casegrouper *grouper; struct casereader *group; + struct ll_list targets; casenumber case_idx; bool ok; @@ -229,7 +233,7 @@ cmd_list (struct lexer *lexer, struct dataset *ds) cmd.v_variables[0] = casenum_var; } - determine_layout (); + determine_layout (&targets); case_idx = 0; for (grouper = casegrouper_create_splits (proc_open (ds), dict); @@ -238,13 +242,13 @@ cmd_list (struct lexer *lexer, struct dataset *ds) { struct ccase *c; - write_all_headers (group, ds); + write_all_headers (group, ds, &targets); for (; (c = casereader_read (group)) != NULL; case_unref (c)) { case_idx++; if (case_idx >= cmd.first && case_idx <= cmd.last && (case_idx - cmd.first) % cmd.step == 0) - list_case (c, case_idx, ds); + list_case (c, case_idx, ds, &targets); } } ok = casegrouper_destroy (grouper); @@ -252,7 +256,7 @@ cmd_list (struct lexer *lexer, struct dataset *ds) ds_destroy(&line_buffer); - clean_up (); + clean_up (&targets); var_destroy (casenum_var); @@ -262,9 +266,10 @@ cmd_list (struct lexer *lexer, struct dataset *ds) /* Writes headers to all devices. This is done at the beginning of each SPLIT FILE group. */ static void -write_all_headers (struct casereader *input, const struct dataset *ds) +write_all_headers (struct casereader *input, const struct dataset *ds, + struct ll_list *targets) { - struct outp_driver *d; + struct list_target *target; struct ccase *c; c = casereader_peek (input, 0); @@ -273,12 +278,13 @@ write_all_headers (struct casereader *input, const struct dataset *ds) output_split_file_values (ds, c); case_unref (c); - for (d = outp_drivers (NULL); d; d = outp_drivers (d)) + ll_for_each (target, struct list_target, ll, targets) { + struct outp_driver *d = target->driver; if (!d->class->special) { d->cp_y += d->font_height; /* Blank line. */ - write_header (d); + write_header (target); } else if (d->class == &html_class) { @@ -304,38 +310,38 @@ write_all_headers (struct casereader *input, const struct dataset *ds) /* Writes the headers. Some of them might be vertical; most are probably horizontal. */ static void -write_header (struct outp_driver *d) +write_header (struct list_target *target) { - struct list_ext *prc = d->prc; + struct outp_driver *d = target->driver; - if (!prc->header_rows) + if (d->class->special || !target->header_rows) return; - if (n_lines_remaining (d) < prc->header_rows + 1) + if (n_lines_remaining (d) < target->header_rows + 1) { outp_eject_page (d); - assert (n_lines_remaining (d) >= prc->header_rows + 1); + assert (n_lines_remaining (d) >= target->header_rows + 1); } /* Design the header. */ - if (!prc->header) + if (!target->header) { size_t i; size_t x; /* Allocate, initialize header. */ - prc->header = xnmalloc (prc->header_rows, sizeof *prc->header); + target->header = xnmalloc (target->header_rows, sizeof *target->header); { int w = n_chars_width (d); - for (i = 0; i < prc->header_rows; i++) + for (i = 0; i < target->header_rows; i++) { - prc->header[i] = xmalloc (w + 1); - memset (prc->header[i], ' ', w); + target->header[i] = xmalloc (w + 1); + memset (target->header[i], ' ', w); } } /* Put in vertical names. */ - for (i = x = 0; i < prc->n_vertical; i++) + for (i = x = 0; i < target->n_vertical; i++) { const struct variable *v = cmd.v_variables[i]; const char *name = var_get_name (v); @@ -343,10 +349,10 @@ write_header (struct outp_driver *d) const struct fmt_spec *print = var_get_print_format (v); size_t j; - memset (&prc->header[prc->header_rows - 1][x], '-', print->w); + memset (&target->header[target->header_rows - 1][x], '-', print->w); x += print->w - 1; for (j = 0; j < name_len; j++) - prc->header[name_len - j - 1][x] = name[j]; + target->header[name_len - j - 1][x] = name[j]; x += 2; } @@ -358,21 +364,21 @@ write_header (struct outp_driver *d) size_t name_len = strlen (name); const struct fmt_spec *print = var_get_print_format (v); - memset (&prc->header[prc->header_rows - 1][x], '-', + memset (&target->header[target->header_rows - 1][x], '-', MAX (print->w, (int) name_len)); if ((int) name_len < print->w) x += print->w - name_len; - memcpy (&prc->header[0][x], name, name_len); + memcpy (&target->header[0][x], name, name_len); x += name_len + 1; } /* Add null bytes. */ - for (i = 0; i < prc->header_rows; i++) + for (i = 0; i < target->header_rows; i++) { for (x = n_chars_width (d); x >= 1; x--) - if (prc->header[i][x - 1] != ' ') + if (target->header[i][x - 1] != ' ') { - prc->header[i][x] = 0; + target->header[i][x] = 0; break; } assert (x); @@ -380,49 +386,52 @@ write_header (struct outp_driver *d) } /* Write out the header, in back-to-front order except for the last line. */ - if (prc->header_rows >= 2) + if (target->header_rows >= 2) { size_t i; - for (i = prc->header_rows - 1; i-- != 0; ) - write_line (d, prc->header[i]); + for (i = target->header_rows - 1; i-- != 0; ) + write_line (d, target->header[i]); } - write_line (d, prc->header[prc->header_rows - 1]); + write_line (d, target->header[target->header_rows - 1]); } /* Frees up all the memory we've allocated. */ static void -clean_up (void) +clean_up (struct ll_list *targets) { - struct outp_driver *d; + struct list_target *target, *next; - for (d = outp_drivers (NULL); d; d = outp_drivers (d)) - if (d->class->special == 0) - { - struct list_ext *prc = d->prc; - size_t i; - - if (prc->header) - { - for (i = 0; i < prc->header_rows; i++) - free (prc->header[i]); - free (prc->header); - } - free (prc); - } - else if (d->class == &html_class) - { - if (d->page_open) - { - struct html_driver_ext *x = d->ext; + ll_for_each_safe (target, next, struct list_target, ll, targets) + { + struct outp_driver *d = target->driver; + if (d->class->special == 0) + { + if (target->header) + { + size_t i; + for (i = 0; i < target->header_rows; i++) + free (target->header[i]); + free (target->header); + } + } + else if (d->class == &html_class) + { + if (d->page_open) + { + struct html_driver_ext *x = d->ext; - fputs ("\n", x->file); - } - } - else - NOT_REACHED (); + fputs ("\n", x->file); + } + } + else + NOT_REACHED (); + ll_remove (&target->ll); + free (target); + } + free (cmd.v_variables); } @@ -541,7 +550,7 @@ write_fallback_headers (struct outp_driver *d) This is complicated by the fact that we have to do all this for every output driver, not just once. */ static void -determine_layout (void) +determine_layout (struct ll_list *targets) { struct outp_driver *d; @@ -549,6 +558,7 @@ determine_layout (void) size buffer to allocate. */ int largest_page_width = 0; + ll_init (targets); for (d = outp_drivers (NULL); d; d = outp_drivers (d)) { size_t column; /* Current column. */ @@ -556,11 +566,17 @@ determine_layout (void) int height; /* Height of vertical names. */ int max_width; /* Page width. */ - struct list_ext *prc; + struct list_target *target; + + target = xmalloc (sizeof *target); + ll_push_tail (targets, &target->ll); + target->driver = d; + target->type = 0; + target->n_vertical = 0; + target->header = NULL; if (d->class == &html_class) continue; - assert (d->class->special == 0); outp_open_page (d); @@ -568,11 +584,6 @@ determine_layout (void) max_width = n_chars_width (d); largest_page_width = MAX (largest_page_width, max_width); - prc = d->prc = xmalloc (sizeof *prc); - prc->type = 0; - prc->n_vertical = 0; - prc->header = NULL; - /* Try layout #1. */ for (width = cmd.n_variables - 1, column = 0; column < cmd.n_variables; column++) { @@ -583,7 +594,7 @@ determine_layout (void) } if (width <= max_width) { - prc->header_rows = 2; + target->header_rows = 2; continue; } @@ -605,7 +616,7 @@ determine_layout (void) if (width <= max_width && height <= SHORT_NAME_LEN) { #ifndef NDEBUG - prc->n_vertical = SIZE_MAX; + target->n_vertical = SIZE_MAX; #endif for (column = cmd.n_variables; column-- != 0; ) { @@ -615,30 +626,30 @@ determine_layout (void) int trial_width = width - fmt_width + MAX (fmt_width, name_len); if (trial_width > max_width) { - prc->n_vertical = column + 1; + target->n_vertical = column + 1; break; } width = trial_width; } - assert (prc->n_vertical != SIZE_MAX); + assert (target->n_vertical != SIZE_MAX); - prc->n_vertical = cmd.n_variables; + target->n_vertical = cmd.n_variables; /* Finally determine the length of the headers. */ - for (prc->header_rows = 0, column = 0; - column < prc->n_vertical; + for (target->header_rows = 0, column = 0; + column < target->n_vertical; column++) { const struct variable *var = cmd.v_variables[column]; size_t name_len = strlen (var_get_name (var)); - prc->header_rows = MAX (prc->header_rows, name_len); + target->header_rows = MAX (target->header_rows, name_len); } - prc->header_rows++; + target->header_rows++; continue; } /* Otherwise use the ugly fallback listing format. */ - prc->type = 1; - prc->header_rows = 0; + target->type = 1; + target->header_rows = 0; d->cp_y += d->font_height; write_fallback_headers (d); @@ -651,122 +662,123 @@ determine_layout (void) /* Writes case C to output. */ static void list_case (const struct ccase *c, casenumber case_idx, - const struct dataset *ds) + const struct dataset *ds, struct ll_list *targets) { struct dictionary *dict = dataset_dict (ds); - struct outp_driver *d; + const char *encoding = dict_get_encoding (dict); + struct list_target *target; - for (d = outp_drivers (NULL); d; d = outp_drivers (d)) - if (d->class->special == 0) - { - const struct list_ext *prc = d->prc; - const int max_width = n_chars_width (d); - int column; - - if (!prc->header_rows) - { - ds_put_format(&line_buffer, "%8s: ", - var_get_name (cmd.v_variables[0])); - } - - - for (column = 0; column < cmd.n_variables; column++) - { - const struct variable *v = cmd.v_variables[column]; - const struct fmt_spec *print = var_get_print_format (v); - int width; - - if (prc->type == 0 && column >= prc->n_vertical) - { - int name_len = strlen (var_get_name (v)); - width = MAX (name_len, print->w); - } - else - width = print->w; - - if (width + ds_length(&line_buffer) > max_width && - ds_length(&line_buffer) != 0) - { - if (!n_lines_remaining (d)) - { - outp_eject_page (d); - write_header (d); - } + ll_for_each (target, struct list_target, ll, targets) + { + struct outp_driver *d = target->driver; - write_line (d, ds_cstr (&line_buffer)); - ds_clear(&line_buffer); + if (d->class->special == 0) + { + const int max_width = n_chars_width (d); + int column; - if (!prc->header_rows) - ds_put_format (&line_buffer, "%8s: ", var_get_name (v)); - } + if (!target->header_rows) + { + ds_put_format(&line_buffer, "%8s: ", + var_get_name (cmd.v_variables[0])); + } - if (width > print->w) - ds_put_char_multiple(&line_buffer, ' ', width - print->w); - if (fmt_is_string (print->type) - || dict_contains_var (dict, v)) - { - char *s = data_out (case_data (c, v), dict_get_encoding (dict), print); - ds_put_cstr (&line_buffer, s); - free (s); - } - else - { - char *s; - union value case_idx_value; - case_idx_value.f = case_idx; - s = data_out (&case_idx_value, dict_get_encoding (dict), print); - ds_put_cstr (&line_buffer, s); - free (s); - } - - ds_put_char (&line_buffer, ' '); - } + for (column = 0; column < cmd.n_variables; column++) + { + const struct variable *v = cmd.v_variables[column]; + const struct fmt_spec *print = var_get_print_format (v); + int width; + char *s; + + if (target->type == 0 && column >= target->n_vertical) + { + int name_len = strlen (var_get_name (v)); + width = MAX (name_len, print->w); + } + else + width = print->w; + + if (width + ds_length(&line_buffer) > max_width && + ds_length(&line_buffer) != 0) + { + if (!n_lines_remaining (d)) + { + outp_eject_page (d); + write_header (target); + } + + write_line (d, ds_cstr (&line_buffer)); + ds_clear(&line_buffer); + + if (!target->header_rows) + ds_put_format (&line_buffer, "%8s: ", var_get_name (v)); + } + + if (width > print->w) + ds_put_char_multiple(&line_buffer, ' ', width - print->w); + + if (fmt_is_string (print->type) || dict_contains_var (dict, v)) + s = data_out (case_data (c, v), encoding, print); + else + { + union value case_idx_value; + case_idx_value.f = case_idx; + s = data_out (&case_idx_value, encoding, print); + } + + ds_put_cstr (&line_buffer, s); + free (s); + ds_put_char(&line_buffer, ' '); + } - if (!n_lines_remaining (d)) - { - outp_eject_page (d); - write_header (d); - } + if (!n_lines_remaining (d)) + { + outp_eject_page (d); + write_header (target); + } - write_line (d, ds_cstr (&line_buffer)); - ds_clear(&line_buffer); - } - else if (d->class == &html_class) - { - struct html_driver_ext *x = d->ext; - int column; + write_line (d, ds_cstr (&line_buffer)); + ds_clear(&line_buffer); + } + else if (d->class == &html_class) + { + struct html_driver_ext *x = d->ext; + int column; - fputs (" \n", x->file); + fputs (" \n", x->file); - for (column = 0; column < cmd.n_variables; column++) - { - const struct variable *v = cmd.v_variables[column]; - const struct fmt_spec *print = var_get_print_format (v); - char *s = NULL; - - if (fmt_is_string (print->type) - || dict_contains_var (dict, v)) - s = data_out (case_data (c, v), dict_get_encoding (dict), print); - else - { - union value case_idx_value; - case_idx_value.f = case_idx; - s = data_out (&case_idx_value, dict_get_encoding (dict), print); - } - - fputs (" ", x->file); - html_put_cell_contents (d, TAB_FIX, ss_buffer (s, print->w)); - free (s); - fputs ("\n", x->file); - } + for (column = 0; column < cmd.n_variables; column++) + { + const struct variable *v = cmd.v_variables[column]; + const struct fmt_spec *print = var_get_print_format (v); + char *s; + + if (fmt_is_string (print->type) + || dict_contains_var (dict, v)) + s = data_out (case_data (c, v), encoding, print); + else + { + union value case_idx_value; + case_idx_value.f = case_idx; + s = data_out (&case_idx_value, encoding, print); + } + + fputs (" ", x->file); + html_put_cell_contents (d, TAB_FIX, ss_cstr (s)); + fputs ("\n", x->file); + + free (s); + } - fputs (" \n", x->file); - } - else - NOT_REACHED (); + fputs (" \n", x->file); + } + else + NOT_REACHED (); + } } + /* Local Variables: mode: c diff --git a/src/language/data-io/print.c b/src/language/data-io/print.c index 2cfa0177..9c8f56e8 100644 --- a/src/language/data-io/print.c +++ b/src/language/data-io/print.c @@ -396,8 +396,8 @@ dump_table (struct print_trns *trns, const struct file_handle *fh) int row; spec_cnt = ll_count (&trns->specs); - t = tab_create (4, spec_cnt + 1, 0); - tab_columns (t, TAB_COL_DOWN, 1); + t = tab_create (4, spec_cnt + 1); + tab_columns (t, TAB_COL_DOWN); tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 3, spec_cnt); tab_hline (t, TAL_2, 0, 3, 1); tab_headers (t, 0, 0, 1, 0); @@ -405,7 +405,7 @@ dump_table (struct print_trns *trns, const struct file_handle *fh) tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Record")); tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Columns")); tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Format")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); row = 1; ll_for_each (spec, struct prt_out_spec, ll, &trns->specs) { diff --git a/src/language/dictionary/split-file.c b/src/language/dictionary/split-file.c index 5d2b42d7..d2f59ccc 100644 --- a/src/language/dictionary/split-file.c +++ b/src/language/dictionary/split-file.c @@ -77,8 +77,8 @@ output_split_file_values (const struct dataset *ds, const struct ccase *c) if (split_cnt == 0) return; - t = tab_create (3, split_cnt + 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + t = tab_create (3, split_cnt + 1); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_vline (t, TAL_GAP, 1, 0, split_cnt); tab_vline (t, TAL_GAP, 2, 0, split_cnt); tab_text (t, 0, 0, TAB_NONE, _("Variable")); @@ -95,6 +95,7 @@ output_split_file_values (const struct dataset *ds, const struct ccase *c) tab_text_format (t, 0, i + 1, TAB_LEFT, "%s", var_get_name (v)); s = data_out (case_data (c, v), dict_get_encoding (dict), print); + tab_text_format (t, 1, i + 1, 0, "%.*s", print->w, s); free (s); diff --git a/src/language/dictionary/sys-file-info.c b/src/language/dictionary/sys-file-info.c index f68a830b..6c44a0c3 100644 --- a/src/language/dictionary/sys-file-info.c +++ b/src/language/dictionary/sys-file-info.c @@ -69,17 +69,18 @@ static int describe_variable (const struct variable *v, struct tab_table *t, /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -sysfile_info_dim (struct tab_table *t, struct outp_driver *d, void *aux UNUSED) +sysfile_info_dim (struct tab_rendering *r, void *aux UNUSED) { + const struct tab_table *t = r->table; static const int max[] = {20, 5, 35, 3, 0}; const int *p; int i; for (p = max; *p; p++) - t->w[p - max] = MIN (tab_natural_width (t, d, p - max), - *p * d->prop_em_width); - for (i = 0; i < t->nr; i++) - t->h[i] = tab_natural_height (t, d, i); + r->w[p - max] = MIN (tab_natural_width (r, p - max), + *p * r->driver->prop_em_width); + for (i = 0; i < tab_nr (t); i++) + r->h[i] = tab_natural_height (r, i); } /* SYSFILE INFO utility. */ @@ -108,7 +109,7 @@ cmd_sysfile_info (struct lexer *lexer, struct dataset *ds UNUSED) } casereader_destroy (reader); - t = tab_create (2, 11, 0); + t = tab_create (2, 11); tab_vline (t, TAL_GAP, 1, 0, 8); tab_text (t, 0, 0, TAB_LEFT, _("File:")); tab_text (t, 1, 0, TAB_LEFT, fh_get_file_name (h)); @@ -160,11 +161,11 @@ cmd_sysfile_info (struct lexer *lexer, struct dataset *ds UNUSED) dict_get_encoding(d) ? dict_get_encoding(d) : _("Unknown")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_submit (t); - t = tab_create (4, 1 + 2 * dict_get_var_cnt (d), 1); - tab_dim (t, sysfile_info_dim, NULL); + t = tab_create (4, 1 + 2 * dict_get_var_cnt (d)); + tab_dim (t, sysfile_info_dim, NULL, NULL); tab_headers (t, 0, 0, 1, 0); tab_text (t, 0, 0, TAB_LEFT | TAT_TITLE, _("Variable")); tab_joint_text (t, 1, 0, 2, 0, TAB_LEFT | TAT_TITLE, _("Description")); @@ -339,44 +340,45 @@ display_documents (const struct dictionary *dict) } } -static int _flags; +struct variables_dim_aux + { + int flags; + }; /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -variables_dim (struct tab_table *t, struct outp_driver *d, void *aux UNUSED) +variables_dim (struct tab_rendering *r, void *aux_) { - int pc; - int i; + const struct outp_driver *d = r->driver; + struct variables_dim_aux *aux = aux_; - t->w[0] = tab_natural_width (t, d, 0); - if (_flags & (DF_VALUE_LABELS | DF_VARIABLE_LABELS | DF_MISSING_VALUES - | DF_AT_ATTRIBUTES | DF_ATTRIBUTES)) + tab_natural_dimensions (r, NULL); + if (aux->flags & (DF_VALUE_LABELS | DF_VARIABLE_LABELS | DF_MISSING_VALUES + | DF_AT_ATTRIBUTES | DF_ATTRIBUTES)) { - t->w[1] = MAX (tab_natural_width (t, d, 1), d->prop_em_width * 5); - t->w[2] = MAX (tab_natural_width (t, d, 2), d->prop_em_width * 35); - pc = 3; + r->w[1] = MAX (r->w[1], d->prop_em_width * 5); + r->w[2] = MAX (r->w[2], d->prop_em_width * 35); } - else - pc = 1; - if (_flags & DF_DICT_INDEX) - t->w[pc] = tab_natural_width (t, d, pc); +} - for (i = 0; i < t->nr; i++) - t->h[i] = tab_natural_height (t, d, i); +static void +variables_dim_free (void *aux_) +{ + struct variables_dim_aux *aux = aux_; + free (aux); } static void display_variables (const struct variable **vl, size_t n, int flags) { struct tab_table *t; + struct variables_dim_aux *aux; int nc; /* Number of columns. */ int pc; /* `Position column' */ int r; /* Current row. */ size_t i; - _flags = flags; - /* One column for the name, two columns for general description, one column for dictionary index. */ @@ -387,7 +389,7 @@ display_variables (const struct variable **vl, size_t n, int flags) if (flags & DF_DICT_INDEX) nc++; - t = tab_create (nc, n + 5, 1); + t = tab_create (nc, n + 5); tab_headers (t, 0, 0, 1, 0); tab_hline (t, TAL_2, 0, nc - 1, 1); tab_text (t, 0, 0, TAB_LEFT | TAT_TITLE, _("Variable")); @@ -397,7 +399,10 @@ display_variables (const struct variable **vl, size_t n, int flags) ? _("Description") : _("Label"))); if (flags & DF_DICT_INDEX) tab_text (t, pc, 0, TAB_LEFT | TAT_TITLE, _("Position")); - tab_dim (t, variables_dim, NULL); + + aux = xmalloc (sizeof *aux); + aux->flags = flags; + tab_dim (t, variables_dim, variables_dim_free, aux); r = 1; for (i = 0; i < n; i++) @@ -413,7 +418,7 @@ display_variables (const struct variable **vl, size_t n, int flags) if (flags & ~DF_DICT_INDEX) tab_vline (t, TAL_1, nc - 1, 0, r - 1); tab_resize (t, -1, r); - tab_columns (t, TAB_COL_DOWN, 1); + tab_columns (t, TAB_COL_DOWN); tab_submit (t); } @@ -478,15 +483,15 @@ display_data_file_attributes (struct attrset *set, int flags) if (!n_attrs) return; - t = tab_create (2, n_attrs + 1, 0); + t = tab_create (2, n_attrs + 1); tab_headers (t, 0, 0, 1, 0); tab_box (t, TAL_1, TAL_1, -1, TAL_1, 0, 0, tab_nc (t) - 1, tab_nr (t) - 1); tab_hline (t, TAL_2, 0, 1, 1); tab_text (t, 0, 0, TAB_LEFT | TAT_TITLE, _("Attribute")); tab_text (t, 1, 0, TAB_LEFT | TAT_TITLE, _("Value")); display_attributes (t, set, flags, 0, 1); - tab_columns (t, TAB_COL_DOWN, 1); - tab_dim (t, tab_natural_dimensions, NULL); + tab_columns (t, TAB_COL_DOWN); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_title (t, "Custom data file attributes."); tab_submit (t); } @@ -713,10 +718,10 @@ display_vectors (const struct dictionary *dict, int sorted) if (sorted) qsort (vl, nvec, sizeof *vl, compare_vector_ptrs_by_name); - t = tab_create (4, nrow + 1, 0); + t = tab_create (4, nrow + 1); tab_headers (t, 0, 0, 1, 0); - tab_columns (t, TAB_COL_DOWN, 1); - tab_dim (t, tab_natural_dimensions, NULL); + tab_columns (t, TAB_COL_DOWN); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_1, TAL_1, -1, -1, 0, 0, 3, nrow); tab_box (t, -1, -1, -1, TAL_1, 0, 0, 3, nrow); tab_hline (t, TAL_2, 0, 3, 1); diff --git a/src/language/lexer/variable-parser.c b/src/language/lexer/variable-parser.c index 1194110e..8a39dbf0 100644 --- a/src/language/lexer/variable-parser.c +++ b/src/language/lexer/variable-parser.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -757,7 +757,7 @@ array_var_set_get_var (const struct var_set *vs, size_t idx) { struct array_var_set *avs = vs->aux; - return (struct variable *) avs->var[idx]; + return CONST_CAST (struct variable *, avs->var[idx]); } /* If VS contains a variable named NAME, sets *IDX to its index diff --git a/src/language/stats/aggregate.c b/src/language/stats/aggregate.c index 08d2f5e1..891e0cca 100644 --- a/src/language/stats/aggregate.c +++ b/src/language/stats/aggregate.c @@ -965,20 +965,20 @@ dump_aggregate_info (struct agr_proc *agr, struct casewriter *output) case MEDIAN: { struct casereader *sorted_reader; - struct order_stats *median = percentile_create (0.5, i->cc); + struct percentile *median = percentile_create (0.5, i->cc); + struct order_stats *os = &median->parent; sorted_reader = casewriter_make_reader (i->writer); - order_stats_accumulate (&median, 1, + order_stats_accumulate (&os, 1, sorted_reader, i->weight, i->subject, i->exclude); - v->f = percentile_calculate ((struct percentile *) median, - PC_HAVERAGE); + v->f = percentile_calculate (median, PC_HAVERAGE); - statistic_destroy ((struct statistic *) median); + statistic_destroy (&median->parent.parent); } break; case SD: diff --git a/src/language/stats/binomial.c b/src/language/stats/binomial.c index 26e0257c..bc87a94d 100644 --- a/src/language/stats/binomial.c +++ b/src/language/stats/binomial.c @@ -187,16 +187,16 @@ binomial_execute (const struct dataset *ds, const struct fmt_spec *wfmt = wvar ? var_get_print_format (wvar) : & F_8_0; - struct tab_table *table = tab_create (7, ost->n_vars * 3 + 1, 0); + struct tab_table *table = tab_create (7, ost->n_vars * 3 + 1); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Binomial Test")); tab_headers (table, 2, 0, 1, 0); tab_box (table, TAL_1, TAL_1, -1, TAL_1, - 0, 0, table->nc - 1, tab_nr(table) - 1 ); + 0, 0, tab_nc (table) - 1, tab_nr(table) - 1 ); for (v = 0 ; v < ost->n_vars; ++v) { diff --git a/src/language/stats/chisquare.c b/src/language/stats/chisquare.c index 4593df41..bc1b6474 100644 --- a/src/language/stats/chisquare.c +++ b/src/language/stats/chisquare.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -179,8 +180,8 @@ create_variable_frequency_table (const struct dictionary *dict, return NULL; } - table = tab_create(4, n_cells + 2, 0); - tab_dim (table, tab_natural_dimensions, NULL); + table = tab_create(4, n_cells + 2); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, var_to_string(var)); tab_text (table, 1, 0, TAB_LEFT, _("Observed N")); @@ -190,7 +191,7 @@ create_variable_frequency_table (const struct dictionary *dict, tab_headers (table, 1, 0, 1, 0); tab_box (table, TAL_1, TAL_1, -1, -1, - 0, 0, table->nc - 1, tab_nr(table) - 1 ); + 0, 0, tab_nc (table) - 1, tab_nr(table) - 1 ); tab_hline (table, TAL_1, 0, tab_nc(table) - 1, 1); @@ -199,7 +200,7 @@ create_variable_frequency_table (const struct dictionary *dict, tab_vline (table, TAL_1, i, 0, tab_nr(table) - 1); - tab_text (table, 0, table->nr - 1, TAB_LEFT, _("Total")); + tab_text (table, 0, tab_nr (table) - 1, TAB_LEFT, _("Total")); return table; } @@ -215,8 +216,8 @@ create_combo_frequency_table (const struct chisquare_test *test) int n_cells = test->hi - test->lo + 1; - table = tab_create(1 + ost->n_vars * 4, n_cells + 3, 0); - tab_dim (table, tab_natural_dimensions, NULL); + table = tab_create(1 + ost->n_vars * 4, n_cells + 3); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Frequencies")); for ( i = 0 ; i < ost->n_vars ; ++i ) @@ -254,12 +255,12 @@ create_combo_frequency_table (const struct chisquare_test *test) tab_headers (table, 1, 0, 2, 0); tab_box (table, TAL_1, TAL_1, -1, -1, - 0, 0, table->nc - 1, tab_nr(table) - 1 ); + 0, 0, tab_nc (table) - 1, tab_nr(table) - 1 ); tab_hline (table, TAL_1, 1, tab_nc(table) - 1, 1); tab_hline (table, TAL_1, 0, tab_nc(table) - 1, 2); - tab_text (table, 0, table->nr - 1, TAB_LEFT, _("Total")); + tab_text (table, 0, tab_nr (table) - 1, TAB_LEFT, _("Total")); return table; } @@ -271,8 +272,8 @@ create_stats_table (const struct chisquare_test *test) const struct one_sample_test *ost = (const struct one_sample_test*) test; struct tab_table *table; - table = tab_create (1 + ost->n_vars, 4, 0); - tab_dim (table, tab_natural_dimensions, NULL); + table = tab_create (1 + ost->n_vars, 4); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Test Statistics")); tab_headers (table, 1, 0, 1, 0); @@ -305,8 +306,9 @@ chisquare_execute (const struct dataset *ds, { const struct dictionary *dict = dataset_dict (ds); int v, i; - struct one_sample_test *ost = (struct one_sample_test *) test; - struct chisquare_test *cst = (struct chisquare_test *) test; + struct chisquare_test *cst = UP_CAST (test, struct chisquare_test, + parent.parent); + struct one_sample_test *ost = &cst->parent; int n_cells = 0; double total_expected = 0.0; const struct variable *wvar = dict_get_weight (dict); diff --git a/src/language/stats/correlations.c b/src/language/stats/correlations.c index 605609a7..c575205c 100644 --- a/src/language/stats/correlations.c +++ b/src/language/stats/correlations.c @@ -94,9 +94,9 @@ output_descriptives (const struct corr *corr, const gsl_matrix *means, const int heading_columns = 1; const int heading_rows = 1; - struct tab_table *t = tab_create (nc, nr, 0); + struct tab_table *t = tab_create (nc, nr); tab_title (t, _("Descriptive Statistics")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_headers (t, heading_columns, 0, heading_rows, 0); @@ -189,9 +189,9 @@ output_correlation (const struct corr *corr, const struct corr_opts *opts, /* One header row */ nr += heading_rows; - t = tab_create (nc, nr, 0); + t = tab_create (nc, nr); tab_title (t, _("Correlations")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_headers (t, heading_columns, 0, heading_rows, 0); diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q index 99fa41d9..5695ed64 100644 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@ -201,6 +201,12 @@ struct crosstabs_proc unsigned int statistics; /* Bit k is 1 if statistic k is requested. */ }; +/* Auxiliary data structure for tab_dim. */ +struct crosstabs_dim_aux + { + enum mv_class exclude; + }; + static void init_proc (struct crosstabs_proc *proc, struct dataset *ds) { @@ -230,8 +236,8 @@ free_proc (struct crosstabs_proc *proc) The rest of the data was allocated and destroyed at a lower level already. */ - free (pt); } + free (proc->pivots); } static int internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds, @@ -836,7 +842,7 @@ make_summary_table (struct crosstabs_proc *proc) struct string name; int i; - summary = tab_create (7, 3 + proc->n_pivots, 1); + summary = tab_create (7, 3 + proc->n_pivots); tab_title (summary, _("Summary.")); tab_headers (summary, 1, 0, 3, 0); tab_joint_text (summary, 1, 0, 6, 0, TAB_CENTER, _("Cases")); @@ -914,8 +920,8 @@ static void display_symmetric (struct crosstabs_proc *, struct pivot_table *, static void display_risk (struct pivot_table *, struct tab_table *); static void display_directional (struct crosstabs_proc *, struct pivot_table *, struct tab_table *); -static void crosstabs_dim (struct tab_table *, struct outp_driver *, - void *proc); +static void crosstabs_dim (struct tab_rendering *, void *aux); +static void crosstabs_dim_free (void *aux); static void table_value_missing (struct crosstabs_proc *proc, struct tab_table *table, int c, int r, unsigned char opt, const union value *v, @@ -1147,8 +1153,7 @@ create_crosstab_table (struct crosstabs_proc *proc, struct pivot_table *pt) int i; table = tab_create (pt->n_consts + 1 + pt->n_cols + 1, - (pt->n_entries / pt->n_cols) * 3 / 2 * proc->n_cells + 10, - true); + (pt->n_entries / pt->n_cols) * 3 / 2 * proc->n_cells + 10); tab_headers (table, pt->n_consts + 1, 0, 2, 0); /* First header line. */ @@ -1224,8 +1229,7 @@ create_chisq_table (struct pivot_table *pt) struct tab_table *chisq; chisq = tab_create (6 + (pt->n_vars - 2), - pt->n_entries / pt->n_cols * 3 / 2 * N_CHISQ + 10, - 1); + pt->n_entries / pt->n_cols * 3 / 2 * N_CHISQ + 10); tab_headers (chisq, 1 + (pt->n_vars - 2), 0, 1, 0); tab_title (chisq, _("Chi-square tests.")); @@ -1252,7 +1256,7 @@ create_sym_table (struct pivot_table *pt) struct tab_table *sym; sym = tab_create (6 + (pt->n_vars - 2), - pt->n_entries / pt->n_cols * 7 + 10, 1); + pt->n_entries / pt->n_cols * 7 + 10); tab_headers (sym, 2 + (pt->n_vars - 2), 0, 1, 0); tab_title (sym, _("Symmetric measures.")); @@ -1274,8 +1278,7 @@ create_risk_table (struct pivot_table *pt) { struct tab_table *risk; - risk = tab_create (4 + (pt->n_vars - 2), pt->n_entries / pt->n_cols * 4 + 10, - 1); + risk = tab_create (4 + (pt->n_vars - 2), pt->n_entries / pt->n_cols * 4 + 10); tab_headers (risk, 1 + pt->n_vars - 2, 0, 2, 0); tab_title (risk, _("Risk estimate.")); @@ -1300,7 +1303,7 @@ create_direct_table (struct pivot_table *pt) struct tab_table *direct; direct = tab_create (7 + (pt->n_vars - 2), - pt->n_entries / pt->n_cols * 7 + 10, 1); + pt->n_entries / pt->n_cols * 7 + 10); tab_headers (direct, 3 + (pt->n_vars - 2), 0, 1, 0); tab_title (direct, _("Directional measures.")); @@ -1348,6 +1351,7 @@ static void submit (struct crosstabs_proc *proc, struct pivot_table *pt, struct tab_table *t) { + struct crosstabs_dim_aux *aux; int i; if (t == NULL) @@ -1370,33 +1374,39 @@ submit (struct crosstabs_proc *proc, struct pivot_table *pt, tab_box (t, -1, -1, -1, TAL_GAP, 0, tab_t (t), tab_l (t) - 1, tab_nr (t) - 1); tab_vline (t, TAL_2, tab_l (t), 0, tab_nr (t) - 1); - tab_dim (t, crosstabs_dim, proc); + + aux = xmalloc (sizeof *aux); + aux->exclude = proc->exclude; + tab_dim (t, crosstabs_dim, crosstabs_dim_free, aux); + tab_submit (t); } /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -crosstabs_dim (struct tab_table *t, struct outp_driver *d, void *proc_) +crosstabs_dim (struct tab_rendering *r, void *aux_) { - struct crosstabs_proc *proc = proc_; + const struct tab_table *t = r->table; + struct outp_driver *d = r->driver; + struct crosstabs_dim_aux *aux = aux_; int i; /* Width of a numerical column. */ int c = outp_string_width (d, "0.000000", OUTP_PROPORTIONAL); - if (proc->exclude == MV_NEVER) + if (aux->exclude == MV_NEVER) c += outp_string_width (d, "M", OUTP_PROPORTIONAL); /* Set width for header columns. */ - if (t->l != 0) + if (tab_l (t) != 0) { size_t i; int w; - w = d->width - c * (t->nc - t->l); - for (i = 0; i <= t->nc; i++) - w -= t->wrv[i]; - w /= t->l; + w = d->width - c * (tab_nc (t) - tab_l (t)); + for (i = 0; i <= tab_nc (t); i++) + w -= r->wrv[i]; + w /= tab_l (t); if (w < d->prop_em_width * 8) w = d->prop_em_width * 8; @@ -1404,15 +1414,22 @@ crosstabs_dim (struct tab_table *t, struct outp_driver *d, void *proc_) if (w > d->prop_em_width * 15) w = d->prop_em_width * 15; - for (i = 0; i < t->l; i++) - t->w[i] = w; + for (i = 0; i < tab_l (t); i++) + r->w[i] = w; } - for (i = t->l; i < t->nc; i++) - t->w[i] = c; + for (i = tab_l (t); i < tab_nc (t); i++) + r->w[i] = c; + + for (i = 0; i < tab_nr (t); i++) + r->h[i] = tab_natural_height (r, i); +} - for (i = 0; i < t->nr; i++) - t->h[i] = tab_natural_height (t, d, i); +static void +crosstabs_dim_free (void *aux_) +{ + struct crosstabs_dim_aux *aux = aux_; + free (aux); } static bool @@ -1513,26 +1530,21 @@ table_value_missing (struct crosstabs_proc *proc, struct tab_table *table, int c, int r, unsigned char opt, const union value *v, const struct variable *var) { - struct substring s; - const struct fmt_spec *print = var_get_print_format (var); - const char *label = var_lookup_value_label (var, v); - if (label) - { - tab_text (table, c, r, TAB_LEFT, label); - return; - } - - s = ss_cstr (data_out_pool (v, dict_get_encoding (proc->dict), print, - table->container)); - if (proc->exclude == MV_NEVER && var_is_num_missing (var, v->f, MV_USER)) - s.string[s.length++] = 'M'; - while (s.length && *s.string == ' ') + if (label != NULL) + tab_text (table, c, r, TAB_LEFT, label); + else { - s.length--; - s.string++; + const struct fmt_spec *print = var_get_print_format (var); + if (proc->exclude == MV_NEVER && var_is_value_missing (var, v, MV_USER)) + { + char *s = data_out (v, dict_get_encoding (proc->dict), print); + tab_text_format (table, c, r, opt, "%sM", s + strspn (s, " ")); + free (s); + } + else + tab_value (table, c, r, opt, v, proc->dict, print); } - tab_raw (table, c, r, opt, &s); } /* Draws a line across TABLE at the current row to indicate the most @@ -1561,22 +1573,22 @@ format_cell_entry (struct tab_table *table, int c, int r, double value, { const struct fmt_spec f = {FMT_F, 10, 1}; union value v; - struct substring s; + char suffixes[3]; + int suffix_len; + char *s; v.f = value; - s = ss_cstr (data_out_pool (&v, dict_get_encoding (dict), &f, table->container)); + s = data_out (&v, dict_get_encoding (dict), &f); - while (*s.string == ' ') - { - s.length--; - s.string++; - } + suffix_len = 0; if (suffix != 0) - s.string[s.length++] = suffix; + suffixes[suffix_len++] = suffix; if (mark_missing) - s.string[s.length++] = 'M'; + suffixes[suffix_len++] = 'M'; + suffixes[suffix_len] = '\0'; - tab_raw (table, c, r, TAB_RIGHT, &s); + tab_text_format (table, c, r, TAB_RIGHT, "%s%s", + s + strspn (s, " "), suffixes); } /* Displays the crosstabulation table. */ diff --git a/src/language/stats/descriptives.c b/src/language/stats/descriptives.c index 6b57fd29..e78d771e 100644 --- a/src/language/stats/descriptives.c +++ b/src/language/stats/descriptives.c @@ -552,15 +552,15 @@ dump_z_table (struct dsc_proc *dsc) cnt++; } - t = tab_create (2, cnt + 1, 0); + t = tab_create (2, cnt + 1); tab_title (t, _("Mapping of variables to corresponding Z-scores.")); - tab_columns (t, SOM_COL_DOWN, 1); + tab_columns (t, SOM_COL_DOWN); tab_headers (t, 0, 0, 1, 0); tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 1, cnt); tab_hline (t, TAL_2, 0, 1, 1); tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Source")); tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Target")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); { size_t i, y; @@ -873,13 +873,13 @@ display (struct dsc_proc *dsc) sort (dsc->vars, dsc->var_cnt, sizeof *dsc->vars, descriptives_compare_dsc_vars, dsc); - t = tab_create (nc, dsc->var_cnt + 1, 0); + t = tab_create (nc, dsc->var_cnt + 1); tab_headers (t, 1, 0, 1, 0); tab_box (t, TAL_1, TAL_1, -1, -1, 0, 0, nc - 1, dsc->var_cnt); tab_box (t, -1, -1, -1, TAL_1, 1, 0, nc - 1, dsc->var_cnt); tab_hline (t, TAL_2, 0, nc - 1, 1); tab_vline (t, TAL_2, 1, 0, dsc->var_cnt); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); nc = 0; tab_text (t, nc++, 0, TAB_LEFT | TAT_TITLE, _("Variable")); diff --git a/src/language/stats/examine.q b/src/language/stats/examine.q index 08077942..4ca3af96 100644 --- a/src/language/stats/examine.q +++ b/src/language/stats/examine.q @@ -48,8 +48,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -104,11 +104,11 @@ struct factor_metrics struct percentile **ptl; size_t n_ptiles; - struct statistic *tukey_hinges; - struct statistic *box_whisker; - struct statistic *trimmed_mean; - struct statistic *histogram; - struct order_stats *np; + struct tukey_hinges *tukey_hinges; + struct box_whisker *box_whisker; + struct trimmed_mean *trimmed_mean; + struct histogram *histogram; + struct np *np; /* Three quartiles indexing into PTL */ struct percentile **quartiles; @@ -179,12 +179,12 @@ factor_destroy (struct xfactor *fctr) moments1_destroy (result->metrics[v].moments); extrema_destroy (result->metrics[v].minima); extrema_destroy (result->metrics[v].maxima); - statistic_destroy (result->metrics[v].trimmed_mean); - statistic_destroy (result->metrics[v].tukey_hinges); - statistic_destroy (result->metrics[v].box_whisker); - statistic_destroy (result->metrics[v].histogram); + statistic_destroy (&result->metrics[v].trimmed_mean->parent.parent); + statistic_destroy (&result->metrics[v].tukey_hinges->parent.parent); + statistic_destroy (&result->metrics[v].box_whisker->parent.parent); + statistic_destroy (&result->metrics[v].histogram->parent); for (i = 0 ; i < result->metrics[v].n_ptiles; ++i) - statistic_destroy ((struct statistic *) result->metrics[v].ptl[i]); + statistic_destroy (&result->metrics[v].ptl[i]->parent.parent); free (result->metrics[v].ptl); free (result->metrics[v].quartiles); casereader_destroy (result->metrics[v].up_reader); @@ -320,82 +320,6 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) }; -/* Plot the normal and detrended normal plots for RESULT. - Label the plots with LABEL */ -static void -np_plot (struct np *np, const char *label) -{ - double yfirst = 0, ylast = 0; - - double x_lower; - double x_upper; - double slack; - - /* Normal Plot */ - struct chart *np_chart; - - /* Detrended Normal Plot */ - struct chart *dnp_chart; - - /* The slope and intercept of the ideal normal probability line */ - const double slope = 1.0 / np->stddev; - const double intercept = -np->mean / np->stddev; - - if ( np->n < 1.0 ) - { - msg (MW, _("Not creating plot because data set is empty.")); - return ; - } - - np_chart = chart_create (); - dnp_chart = chart_create (); - - if ( !np_chart || ! dnp_chart ) - return ; - - chart_write_title (np_chart, _("Normal Q-Q Plot of %s"), label); - chart_write_xlabel (np_chart, _("Observed Value")); - chart_write_ylabel (np_chart, _("Expected Normal")); - - chart_write_title (dnp_chart, _("Detrended Normal Q-Q Plot of %s"), - label); - chart_write_xlabel (dnp_chart, _("Observed Value")); - chart_write_ylabel (dnp_chart, _("Dev from Normal")); - - yfirst = gsl_cdf_ugaussian_Pinv (1 / (np->n + 1)); - ylast = gsl_cdf_ugaussian_Pinv (np->n / (np->n + 1)); - - /* Need to make sure that both the scatter plot and the ideal fit into the - plot */ - x_lower = MIN (np->y_min, (yfirst - intercept) / slope) ; - x_upper = MAX (np->y_max, (ylast - intercept) / slope) ; - slack = (x_upper - x_lower) * 0.05 ; - - chart_write_xscale (np_chart, x_lower - slack, x_upper + slack, 5); - chart_write_xscale (dnp_chart, np->y_min, np->y_max, 5); - - chart_write_yscale (np_chart, yfirst, ylast, 5); - chart_write_yscale (dnp_chart, np->dns_min, np->dns_max, 5); - - { - struct casereader *reader = casewriter_make_reader (np->writer); - struct ccase *c; - while ((c = casereader_read (reader)) != NULL) - { - chart_datum (np_chart, 0, case_data_idx (c, NP_IDX_Y)->f, case_data_idx (c, NP_IDX_NS)->f); - chart_datum (dnp_chart, 0, case_data_idx (c, NP_IDX_Y)->f, case_data_idx (c, NP_IDX_DNS)->f); - - case_unref (c); - } - casereader_destroy (reader); - } - - chart_line (dnp_chart, 0, 0, np->y_min, np->y_max , CHART_DIM_X); - chart_line (np_chart, slope, intercept, yfirst, ylast , CHART_DIM_Y); - - chart_submit (np_chart); - chart_submit (dnp_chart); -} static void @@ -412,20 +336,37 @@ show_npplot (const struct variable **dependent_var, ll != ll_null (&fctr->result_list); ll = ll_next (ll)) { - struct string str; + struct string label; const struct factor_result *result = ll_data (ll, struct factor_result, ll); - - ds_init_empty (&str); - ds_put_format (&str, "%s ", var_get_name (dependent_var[v])); - - factor_to_string (fctr, result, &str); - - np_plot ((struct np*) result->metrics[v].np, ds_cstr(&str)); - - statistic_destroy ((struct statistic *)result->metrics[v].np); - - ds_destroy (&str); + struct chart *npp, *dnpp; + struct casereader *reader; + struct np *np; + + ds_init_empty (&label); + ds_put_format (&label, "%s ", var_get_name (dependent_var[v])); + factor_to_string (fctr, result, &label); + + np = result->metrics[v].np; + reader = casewriter_make_reader (np->writer); + npp = np_plot_create (np, reader, ds_cstr (&label)); + dnpp = dnp_plot_create (np, reader, ds_cstr (&label)); + + ds_destroy (&label); + + if (npp == NULL || dnpp == NULL) + { + msg (MW, _("Not creating NP plot because data set is empty.")); + chart_unref (npp); + chart_unref (dnpp); + } + else + { + chart_submit (npp); + chart_submit (dnpp); + } + + statistic_destroy (&np->parent.parent); } } } @@ -448,15 +389,25 @@ show_histogram (const struct variable **dependent_var, struct string str; const struct factor_result *result = ll_data (ll, struct factor_result, ll); + struct histogram *histogram; + double mean, var, n; + + histogram = result->metrics[v].histogram; + if (histogram == NULL) + { + /* Probably all values are SYSMIS. */ + continue; + } ds_init_empty (&str); ds_put_format (&str, "%s ", var_get_name (dependent_var[v])); factor_to_string (fctr, result, &str); - histogram_plot ((struct histogram *) result->metrics[v].histogram, - ds_cstr (&str), - (struct moments1 *) result->metrics[v].moments); + moments1_calculate (result->metrics[v].moments, + &n, &mean, &var, NULL, NULL); + chart_submit (histogram_chart_create (histogram, ds_cstr (&str), + n, mean, sqrt (var), false)); ds_destroy (&str); } @@ -474,25 +425,18 @@ show_boxplot_groups (const struct variable **dependent_var, for (v = 0; v < n_dep_var; ++v) { - struct ll *ll; - int f = 0; - struct chart *ch = chart_create (); + const struct factor_result *result; + struct boxplot *boxplot; double y_min = DBL_MAX; double y_max = -DBL_MAX; + char *title; - for (ll = ll_head (&fctr->result_list); - ll != ll_null (&fctr->result_list); - ll = ll_next (ll)) + ll_for_each (result, struct factor_result, ll, &fctr->result_list) { + struct factor_metrics *metrics = &result->metrics[v]; + const struct ll_list *max_list = extrema_list (metrics->maxima); + const struct ll_list *min_list = extrema_list (metrics->minima); const struct extremum *max, *min; - const struct factor_result *result = - ll_data (ll, struct factor_result, ll); - - const struct ll_list *max_list = - extrema_list (result->metrics[v].maxima); - - const struct ll_list *min_list = - extrema_list (result->metrics[v].minima); if ( ll_is_empty (max_list)) { @@ -500,52 +444,34 @@ show_boxplot_groups (const struct variable **dependent_var, continue; } - max = (const struct extremum *) - ll_data (ll_head(max_list), struct extremum, ll); - - min = (const struct extremum *) - ll_data (ll_head (min_list), struct extremum, ll); + max = ll_data (ll_head(max_list), struct extremum, ll); + min = ll_data (ll_head (min_list), struct extremum, ll); y_max = MAX (y_max, max->value); y_min = MIN (y_min, min->value); } - boxplot_draw_yscale (ch, y_max, y_min); - - if ( fctr->indep_var[0]) - chart_write_title (ch, _("Boxplot of %s vs. %s"), + if (fctr->indep_var[0]) + title = xasprintf (_("Boxplot of %s vs. %s"), var_to_string (dependent_var[v]), - var_to_string (fctr->indep_var[0]) ); + var_to_string (fctr->indep_var[0])); else - chart_write_title (ch, _("Boxplot of %s"), - var_to_string (dependent_var[v])); + title = xasprintf (_("Boxplot of %s"), + var_to_string (dependent_var[v])); + boxplot = boxplot_create (y_min, y_max, title); + free (title); - for (ll = ll_head (&fctr->result_list); - ll != ll_null (&fctr->result_list); - ll = ll_next (ll)) + ll_for_each (result, struct factor_result, ll, &fctr->result_list) { - const struct factor_result *result = - ll_data (ll, struct factor_result, ll); - - struct string str; - const double box_width = (ch->data_right - ch->data_left) - / (ll_count (&fctr->result_list) * 2.0 ) ; - - const double box_centre = (f++ * 2 + 1) * box_width + ch->data_left; - - ds_init_empty (&str); + struct factor_metrics *metrics = &result->metrics[v]; + struct string str = DS_EMPTY_INITIALIZER; factor_to_string_concise (fctr, result, &str); - - boxplot_draw_boxplot (ch, - box_centre, box_width, - (const struct box_whisker *) - result->metrics[v].box_whisker, - ds_cstr (&str)); - + boxplot_add_box (boxplot, metrics->box_whisker, ds_cstr (&str)); + metrics->box_whisker = NULL; ds_destroy (&str); } - chart_submit (ch); + chart_submit (boxplot_get_chart (boxplot)); } } @@ -558,74 +484,42 @@ show_boxplot_variables (const struct variable **dependent_var, ) { + const struct factor_result *result; int v; - struct ll *ll; - const struct ll_list *result_list = &fctr->result_list; - - for (ll = ll_head (result_list); - ll != ll_null (result_list); - ll = ll_next (ll)) + ll_for_each (result, struct factor_result, ll, &fctr->result_list) { struct string title; - struct chart *ch = chart_create (); double y_min = DBL_MAX; double y_max = -DBL_MAX; - - const struct factor_result *result = - ll_data (ll, struct factor_result, ll); - - const double box_width = (ch->data_right - ch->data_left) - / (n_dep_var * 2.0 ) ; + struct boxplot *boxplot; for (v = 0; v < n_dep_var; ++v) { - const struct ll *max_ll = - ll_head (extrema_list (result->metrics[v].maxima)); - const struct ll *min_ll = - ll_head (extrema_list (result->metrics[v].minima)); - - const struct extremum *max = - (const struct extremum *) ll_data (max_ll, struct extremum, ll); - - const struct extremum *min = - (const struct extremum *) ll_data (min_ll, struct extremum, ll); + const struct factor_metrics *metrics = &result->metrics[v]; + const struct ll *max_ll = ll_head (extrema_list (metrics->maxima)); + const struct ll *min_ll = ll_head (extrema_list (metrics->minima)); + const struct extremum *max = ll_data (max_ll, struct extremum, ll); + const struct extremum *min = ll_data (min_ll, struct extremum, ll); y_max = MAX (y_max, max->value); y_min = MIN (y_min, min->value); } - - boxplot_draw_yscale (ch, y_max, y_min); - ds_init_empty (&title); factor_to_string (fctr, result, &title); - -#if 0 - ds_put_format (&title, "%s = ", var_get_name (fctr->indep_var[0])); - var_append_value_name (fctr->indep_var[0], &result->value[0], &title); -#endif - - chart_write_title (ch, ds_cstr (&title)); + boxplot = boxplot_create (y_min, y_max, ds_cstr (&title)); ds_destroy (&title); for (v = 0; v < n_dep_var; ++v) { - struct string str; - const double box_centre = (v * 2 + 1) * box_width + ch->data_left; - - ds_init_empty (&str); - ds_init_cstr (&str, var_get_name (dependent_var[v])); - - boxplot_draw_boxplot (ch, - box_centre, box_width, - (const struct box_whisker *) result->metrics[v].box_whisker, - ds_cstr (&str)); - - ds_destroy (&str); + struct factor_metrics *metrics = &result->metrics[v]; + boxplot_add_box (boxplot, metrics->box_whisker, + var_get_name (dependent_var[v])); + metrics->box_whisker = NULL; } - chart_submit (ch); + chart_submit (boxplot_get_chart (boxplot)); } } @@ -674,16 +568,14 @@ output_examine (const struct dictionary *dict) if ( cmd.sbc_percentiles) show_percentiles (dependent_vars, n_dependent_vars, factor); - if (cmd.a_plot[XMN_PLT_BOXPLOT] && - cmd.cmp == XMN_GROUPS) - show_boxplot_groups (dependent_vars, n_dependent_vars, factor); - - - if (cmd.a_plot[XMN_PLT_BOXPLOT] && - cmd.cmp == XMN_VARIABLES) - show_boxplot_variables (dependent_vars, n_dependent_vars, - factor); - + if (cmd.a_plot[XMN_PLT_BOXPLOT]) + { + if (cmd.cmp == XMN_GROUPS) + show_boxplot_groups (dependent_vars, n_dependent_vars, factor); + else if (cmd.cmp == XMN_VARIABLES) + show_boxplot_variables (dependent_vars, n_dependent_vars, factor); + } + if (cmd.a_plot[XMN_PLT_HISTOGRAM]) show_histogram (dependent_vars, n_dependent_vars, factor); @@ -989,15 +881,13 @@ examine_group (struct cmd_examine *cmd, struct casereader *reader, int level, metric->n_ptiles = percentile_list.n_data; - metric->ptl = xcalloc (metric->n_ptiles, - sizeof (struct percentile *)); + metric->ptl = xcalloc (metric->n_ptiles, sizeof *metric->ptl); metric->quartiles = xcalloc (3, sizeof (*metric->quartiles)); for (i = 0 ; i < metric->n_ptiles; ++i) { - metric->ptl[i] = (struct percentile *) - percentile_create (percentile_list.data[i] / 100.0, metric->n_valid); + metric->ptl[i] = percentile_create (percentile_list.data[i] / 100.0, metric->n_valid); if ( percentile_list.data[i] == 25) metric->quartiles[0] = metric->ptl[i]; @@ -1018,18 +908,18 @@ examine_group (struct cmd_examine *cmd, struct casereader *reader, int level, n_os ++; } - os = xcalloc (sizeof (struct order_stats *), n_os); + os = xcalloc (n_os, sizeof *os); for (i = 0 ; i < metric->n_ptiles ; ++i ) { - os[i] = (struct order_stats *) metric->ptl[i]; + os[i] = &metric->ptl[i]->parent; } - os[i] = (struct order_stats *) metric->tukey_hinges; - os[i+1] = (struct order_stats *) metric->trimmed_mean; + os[i] = &metric->tukey_hinges->parent; + os[i+1] = &metric->trimmed_mean->parent; if (cmd->a_plot[XMN_PLT_NPPLOT]) - os[i+2] = metric->np; + os[i+2] = &metric->np->parent; order_stats_accumulate (os, n_os, casereader_clone (metric->up_reader), @@ -1080,7 +970,7 @@ examine_group (struct cmd_examine *cmd, struct casereader *reader, int level, { struct factor_metrics *metric = &result->metrics[v]; if ( metric->histogram) - histogram_add ((struct histogram *) metric->histogram, + histogram_add (metric->histogram, case_data (c, dependent_vars[v])->f, weight); } case_unref (c); @@ -1096,13 +986,13 @@ examine_group (struct cmd_examine *cmd, struct casereader *reader, int level, struct factor_metrics *metric = &result->metrics[v]; int n_vals = caseproto_get_n_widths (casereader_get_proto ( metric->up_reader)); + struct order_stats *os; metric->box_whisker = - box_whisker_create ((struct tukey_hinges *) metric->tukey_hinges, - cmd->v_id, n_vals - 1); + box_whisker_create ( metric->tukey_hinges, cmd->v_id, n_vals - 1); - order_stats_accumulate ((struct order_stats **) &metric->box_whisker, - 1, + os = &metric->box_whisker->parent; + order_stats_accumulate ( &os, 1, casereader_clone (metric->up_reader), wv, dependent_vars[v], MV_ANY); } @@ -1242,10 +1132,10 @@ show_summary (const struct variable **dependent_var, int n_dep_var, n_cols = heading_columns + 6; - tbl = tab_create (n_cols, n_rows, 0); + tbl = tab_create (n_cols, n_rows); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); /* Outline the box */ tab_box (tbl, @@ -1479,10 +1369,10 @@ show_descriptives (const struct variable **dependent_var, n_cols = heading_columns + 2; - tbl = tab_create (n_cols, n_rows, 0); + tbl = tab_create (n_cols, n_rows); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); /* Outline the box */ tab_box (tbl, @@ -1658,7 +1548,7 @@ show_descriptives (const struct variable **dependent_var, tab_double (tbl, n_cols - 2, heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS, TAB_CENTER, - trimmed_mean_calculate ((struct trimmed_mean *) result->metrics[v].trimmed_mean), + trimmed_mean_calculate (result->metrics[v].trimmed_mean), NULL); @@ -1791,10 +1681,10 @@ show_extremes (const struct variable **dependent_var, n_cols = heading_columns + 2; - tbl = tab_create (n_cols, n_rows, 0); + tbl = tab_create (n_cols, n_rows); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); /* Outline the box */ tab_box (tbl, @@ -1995,10 +1885,10 @@ show_percentiles (const struct variable **dependent_var, n_cols = heading_columns + n_percentiles; - tbl = tab_create (n_cols, n_rows, 0); + tbl = tab_create (n_cols, n_rows); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); /* Outline the box */ tab_box (tbl, @@ -2078,8 +1968,7 @@ show_percentiles (const struct variable **dependent_var, tab_vline (tbl, TAL_1, n_cols - n_percentiles -1, heading_rows, n_rows - 1); - tukey_hinges_calculate ((struct tukey_hinges *) result->metrics[v].tukey_hinges, - hinges); + tukey_hinges_calculate (result->metrics[v].tukey_hinges, hinges); for (j = 0; j < n_percentiles; ++j) { diff --git a/src/language/stats/factor.c b/src/language/stats/factor.c index 9d3d944e..b035fc8d 100644 --- a/src/language/stats/factor.c +++ b/src/language/stats/factor.c @@ -934,11 +934,11 @@ show_communalities (const struct cmd_factor * factor, if (nc <= 1) return; - t = tab_create (nc, nr, 0); + t = tab_create (nc, nr); tab_title (t, _("Communalities")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_headers (t, heading_columns, 0, heading_rows, 0); @@ -994,14 +994,14 @@ show_factor_matrix (const struct cmd_factor *factor, struct idata *idata, const const int nc = heading_columns + n_factors; gsl_permutation *perm; - struct tab_table *t = tab_create (nc, nr, 0); + struct tab_table *t = tab_create (nc, nr); if ( factor->extraction == EXTRACTION_PC ) tab_title (t, _("Component Matrix")); else tab_title (t, _("Factor Matrix")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_headers (t, heading_columns, 0, heading_rows, 0); @@ -1106,11 +1106,11 @@ show_explained_variance (const struct cmd_factor * factor, struct idata *idata, if ( nc <= heading_columns) return; - t = tab_create (nc, nr, 0); + t = tab_create (nc, nr); tab_title (t, _("Total Variance Explained")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_headers (t, heading_columns, 0, heading_rows, 0); @@ -1258,11 +1258,11 @@ show_correlation_matrix (const struct cmd_factor *factor, const struct idata *id if (nr <= heading_rows && suffix_rows == 0) return; - t = tab_create (nc, nr + suffix_rows, 0); + t = tab_create (nc, nr + suffix_rows); tab_title (t, _("Correlation Matrix")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_hline (t, TAL_1, 0, nc - 1, heading_rows); @@ -1403,9 +1403,9 @@ do_factor (const struct cmd_factor *factor, struct casereader *r) const int nr = heading_rows + factor->n_vars; - struct tab_table *t = tab_create (nc, nr, 0); + struct tab_table *t = tab_create (nc, nr); tab_title (t, _("Descriptive Statistics")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_headers (t, heading_columns, 0, heading_rows, 0); diff --git a/src/language/stats/frequencies.q b/src/language/stats/frequencies.q index 5a704d0d..e1d6fb0e 100644 --- a/src/language/stats/frequencies.q +++ b/src/language/stats/frequencies.q @@ -612,13 +612,14 @@ postcalc (const struct dataset *ds) hist = freq_tab_to_hist (ft,v); - histogram_plot_n (hist, var_to_string(v), + chart_submit (histogram_chart_create ( + hist, var_to_string(v), vf->tab.valid_cases, d[frq_mean], d[frq_stddev], - normal); + normal)); - statistic_destroy ((struct statistic *)hist); + statistic_destroy (&hist->parent); } if ( chart == GFT_PIE) @@ -1000,26 +1001,39 @@ compare_freq_alpha_d (const void *a_, const void *b_, const void *v_) /* Frequency table display. */ +struct full_dim_aux + { + bool show_labels; + }; + /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -full_dim (struct tab_table *t, struct outp_driver *d, void *aux UNUSED) +full_dim (struct tab_rendering *r, void *aux_) { - int i = 0; - int columns = 5; + const struct outp_driver *d = r->driver; + const struct tab_table *t = r->table; + const struct full_dim_aux *aux = aux_; + int i; - if (cmd.labels == FRQ_LABELS) + for (i = 0; i < tab_nc (t); i++) { - t->w[0] = MIN (tab_natural_width (t, d, 0), d->prop_em_width * 15); - i = 1; - columns ++; + r->w[i] = tab_natural_width (r, i); + if (aux->show_labels && i == 0) + r->w[i] = MIN (r->w[i], d->prop_em_width * 15); + else + r->w[i] = MAX (r->w[i], d->prop_em_width * 8); } - for (;i < columns; i++) - t->w[i] = MAX (tab_natural_width (t, d, i), d->prop_em_width * 8); + for (i = 0; i < tab_nr (t); i++) + r->h[i] = d->font_height; +} - for (i = 0; i < t->nr; i++) - t->h[i] = d->font_height; +static void +full_dim_free (void *aux_) +{ + struct full_dim_aux *aux = aux_; + free (aux); } /* Displays a full frequency table for variable V. */ @@ -1046,12 +1060,17 @@ dump_full (const struct variable *v, const struct variable *wv) const bool lab = (cmd.labels == FRQ_LABELS); + struct full_dim_aux *aux; + vf = get_var_freqs (v); ft = &vf->tab; n_categories = ft->n_valid + ft->n_missing; - t = tab_create (5 + lab, n_categories + 2, 0); + t = tab_create (5 + lab, n_categories + 2); tab_headers (t, 0, 0, 1, 0); - tab_dim (t, full_dim, NULL); + + aux = xmalloc (sizeof *aux); + aux->show_labels = lab; + tab_dim (t, full_dim, full_dim_free, aux); if (lab) tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Value Label")); @@ -1121,20 +1140,26 @@ dump_full (const struct variable *v, const struct variable *wv) /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -condensed_dim (struct tab_table *t, struct outp_driver *d, void *aux UNUSED) +condensed_dim (struct tab_rendering *r, void *aux UNUSED) { - int cum_w = MAX (outp_string_width (d, _("Cum"), OUTP_PROPORTIONAL), - MAX (outp_string_width (d, _("Cum"), OUTP_PROPORTIONAL), - outp_string_width (d, "000", OUTP_PROPORTIONAL))); + struct outp_driver *d = r->driver; + const struct tab_table *t = r->table; + + int cum_width = outp_string_width (d, _("Cum"), OUTP_PROPORTIONAL); + int zeros_width = outp_string_width (d, "000", OUTP_PROPORTIONAL); + int max_width = MAX (cum_width, zeros_width); int i; for (i = 0; i < 2; i++) - t->w[i] = MAX (tab_natural_width (t, d, i), d->prop_em_width * 8); + { + r->w[i] = tab_natural_width (r, i); + r->w[i] = MAX (r->w[i], d->prop_em_width * 8); + } for (i = 2; i < 4; i++) - t->w[i] = cum_w; - for (i = 0; i < t->nr; i++) - t->h[i] = d->font_height; + r->w[i] = max_width; + for (i = 0; i < tab_nr (t); i++) + r->h[i] = d->font_height; } /* Display condensed frequency table for variable V. */ @@ -1153,7 +1178,7 @@ dump_condensed (const struct variable *v, const struct variable *wv) vf = get_var_freqs (v); ft = &vf->tab; n_categories = ft->n_valid + ft->n_missing; - t = tab_create (4, n_categories + 2, 0); + t = tab_create (4, n_categories + 2); tab_headers (t, 0, 0, 2, 0); tab_text (t, 0, 1, TAB_CENTER | TAT_TITLE, _("Value")); @@ -1161,7 +1186,7 @@ dump_condensed (const struct variable *v, const struct variable *wv) tab_text (t, 2, 1, TAB_CENTER | TAT_TITLE, _("Pct")); tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Cum")); tab_text (t, 3, 1, TAB_CENTER | TAT_TITLE, _("Pct")); - tab_dim (t, condensed_dim, NULL); + tab_dim (t, condensed_dim, NULL, NULL); r = 2; for (f = ft->valid; f < ft->missing; f++) @@ -1191,7 +1216,7 @@ dump_condensed (const struct variable *v, const struct variable *wv) 0, 0, 3, r - 1); tab_hline (t, TAL_2, 0, 3, 2); tab_title (t, "%s", var_to_string (v)); - tab_columns (t, SOM_COL_DOWN, 1); + tab_columns (t, SOM_COL_DOWN); tab_submit (t); } @@ -1359,8 +1384,8 @@ dump_statistics (const struct variable *v, bool show_varname, } calc_stats (v, stat_value); - t = tab_create (3, n_stats + n_percentiles + 2, 0); - tab_dim (t, tab_natural_dimensions, NULL); + t = tab_create (3, n_stats + n_percentiles + 2); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_1, TAL_1, -1, -1 , 0 , 0 , 2, tab_nr(t) - 1) ; @@ -1401,7 +1426,7 @@ dump_statistics (const struct variable *v, bool show_varname, var_get_print_format (v)); } - tab_columns (t, SOM_COL_DOWN, 1); + tab_columns (t, SOM_COL_DOWN); if (show_varname) tab_title (t, "%s", var_to_string (v)); else @@ -1420,7 +1445,7 @@ freq_tab_to_hist (const struct freq_tab *ft, const struct variable *var) double x_min = DBL_MAX; double x_max = -DBL_MAX; - struct statistic *hist; + struct histogram *hist; const double bins = 11; struct hsh_iterator hi; @@ -1442,10 +1467,10 @@ freq_tab_to_hist (const struct freq_tab *ft, const struct variable *var) for( i = 0 ; i < ft->n_valid ; ++i ) { frq = &ft->valid[i]; - histogram_add ((struct histogram *)hist, frq->value.f, frq->count); + histogram_add (hist, frq->value.f, frq->count); } - return (struct histogram *)hist; + return hist; } @@ -1477,7 +1502,7 @@ freq_tab_to_slice_array(const struct freq_tab *frq_tab, ds_init_empty (&slices[i].label); var_append_value_name (var, &frq->value, &slices[i].label); - slices[i].magnetude = frq->count; + slices[i].magnitude = frq->count; } return slices; @@ -1494,14 +1519,12 @@ do_piechart(const struct variable *var, const struct freq_tab *frq_tab) slices = freq_tab_to_slice_array(frq_tab, var, &n_slices); - piechart_plot(var_to_string(var), slices, n_slices); + chart_submit (piechart_create (var_to_string(var), slices, n_slices)); for (i = 0 ; i < n_slices ; ++i ) - { - ds_destroy (&slices[i].label); - } + ds_destroy (&slices[i].label); - free(slices); + free (slices); } diff --git a/src/language/stats/npar-summary.c b/src/language/stats/npar-summary.c index d626dffa..8e6f11a8 100644 --- a/src/language/stats/npar-summary.c +++ b/src/language/stats/npar-summary.c @@ -102,16 +102,16 @@ do_summary_box (const struct descriptives *desc, if ( desc ) columns += 5; if ( quartiles ) columns += 3; - table = tab_create (columns, 2 + n_vars, 0); + table = tab_create (columns, 2 + n_vars); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Descriptive Statistics")); tab_headers (table, 1, 0, 1, 0); tab_box (table, TAL_1, TAL_1, -1, TAL_1, - 0, 0, table->nc - 1, tab_nr(table) - 1 ); + 0, 0, tab_nc (table) - 1, tab_nr(table) - 1 ); tab_hline (table, TAL_2, 0, tab_nc (table) -1, 2); tab_vline (table, TAL_2, 1, 0, tab_nr (table) - 1); diff --git a/src/language/stats/npar.q b/src/language/stats/npar.q index bbccce67..8c6f98f8 100644 --- a/src/language/stats/npar.q +++ b/src/language/stats/npar.q @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -223,10 +224,11 @@ npar_custom_chisquare (struct lexer *lexer, struct dataset *ds, struct npar_specs *specs = aux; struct chisquare_test *cstp = pool_alloc(specs->pool, sizeof(*cstp)); - struct one_sample_test *tp = (struct one_sample_test *) cstp; + struct one_sample_test *tp = &cstp->parent; + struct npar_test *nt = &tp->parent; - ((struct npar_test *)tp)->execute = chisquare_execute; - ((struct npar_test *)tp)->insert_variables = one_sample_insert_variables; + nt->execute = chisquare_execute; + nt->insert_variables = one_sample_insert_variables; if (!parse_variables_const_pool (lexer, specs->pool, dataset_dict (ds), &tp->vars, &tp->n_vars, @@ -316,7 +318,7 @@ npar_custom_chisquare (struct lexer *lexer, struct dataset *ds, specs->test, sizeof(*specs->test) * specs->n_tests); - specs->test[specs->n_tests - 1] = (struct npar_test *) tp; + specs->test[specs->n_tests - 1] = nt; return 1; } @@ -328,10 +330,11 @@ npar_custom_binomial (struct lexer *lexer, struct dataset *ds, { struct npar_specs *specs = aux; struct binomial_test *btp = pool_alloc(specs->pool, sizeof(*btp)); - struct one_sample_test *tp = (struct one_sample_test *) btp; + struct one_sample_test *tp = &btp->parent; + struct npar_test *nt = &tp->parent; - ((struct npar_test *)tp)->execute = binomial_execute; - ((struct npar_test *)tp)->insert_variables = one_sample_insert_variables; + nt->execute = binomial_execute; + nt->insert_variables = one_sample_insert_variables; btp->category1 = btp->category2 = btp->cutpoint = SYSMIS; @@ -381,7 +384,7 @@ npar_custom_binomial (struct lexer *lexer, struct dataset *ds, specs->test, sizeof(*specs->test) * specs->n_tests); - specs->test[specs->n_tests - 1] = (struct npar_test *) tp; + specs->test[specs->n_tests - 1] = nt; return 1; } @@ -412,7 +415,7 @@ parse_two_sample_related_test (struct lexer *lexer, const struct variable **vlist2; size_t n_vlist2; - ((struct npar_test *)test_parameters)->insert_variables = two_sample_insert_variables; + test_parameters->parent.insert_variables = two_sample_insert_variables; if (!parse_variables_const_pool (lexer, pool, dict, @@ -512,7 +515,8 @@ npar_custom_wilcoxon (struct lexer *lexer, struct npar_specs *specs = aux; struct two_sample_test *tp = pool_alloc (specs->pool, sizeof(*tp)); - ((struct npar_test *)tp)->execute = wilcoxon_execute; + struct npar_test *nt = &tp->parent; + nt->execute = wilcoxon_execute; if (!parse_two_sample_related_test (lexer, dataset_dict (ds), cmd, tp, specs->pool) ) @@ -522,7 +526,7 @@ npar_custom_wilcoxon (struct lexer *lexer, specs->test = pool_realloc (specs->pool, specs->test, sizeof(*specs->test) * specs->n_tests); - specs->test[specs->n_tests - 1] = (struct npar_test *) tp; + specs->test[specs->n_tests - 1] = nt; return 1; } @@ -535,7 +539,8 @@ npar_custom_mcnemar (struct lexer *lexer, struct npar_specs *specs = aux; struct two_sample_test *tp = pool_alloc(specs->pool, sizeof(*tp)); - ((struct npar_test *)tp)->execute = NULL; + struct npar_test *nt = &tp->parent; + nt->execute = NULL; if (!parse_two_sample_related_test (lexer, dataset_dict (ds), @@ -546,7 +551,7 @@ npar_custom_mcnemar (struct lexer *lexer, specs->test = pool_realloc (specs->pool, specs->test, sizeof(*specs->test) * specs->n_tests); - specs->test[specs->n_tests - 1] = (struct npar_test *) tp; + specs->test[specs->n_tests - 1] = nt; return 1; } @@ -558,7 +563,9 @@ npar_custom_sign (struct lexer *lexer, struct dataset *ds, struct npar_specs *specs = aux; struct two_sample_test *tp = pool_alloc(specs->pool, sizeof(*tp)); - ((struct npar_test *) tp)->execute = sign_execute; + struct npar_test *nt = &tp->parent; + + nt->execute = sign_execute; if (!parse_two_sample_related_test (lexer, dataset_dict (ds), cmd, tp, specs->pool) ) @@ -568,7 +575,7 @@ npar_custom_sign (struct lexer *lexer, struct dataset *ds, specs->test = pool_realloc (specs->pool, specs->test, sizeof(*specs->test) * specs->n_tests); - specs->test[specs->n_tests - 1] = (struct npar_test *) tp; + specs->test[specs->n_tests - 1] = nt; return 1; } @@ -579,7 +586,7 @@ one_sample_insert_variables (const struct npar_test *test, struct const_hsh_table *var_hash) { int i; - struct one_sample_test *ost = (struct one_sample_test *) test; + struct one_sample_test *ost = UP_CAST (test, struct one_sample_test, parent); for ( i = 0 ; i < ost->n_vars ; ++i ) const_hsh_insert (var_hash, ost->vars[i]); diff --git a/src/language/stats/oneway.q b/src/language/stats/oneway.q index 0f6b20a1..ddb84d89 100644 --- a/src/language/stats/oneway.q +++ b/src/language/stats/oneway.q @@ -259,9 +259,9 @@ show_anova_table (void) struct tab_table *t; - t = tab_create (n_cols, n_rows, 0); + t = tab_create (n_cols, n_rows); tab_headers (t, 2, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, @@ -370,9 +370,9 @@ show_descriptives (const struct dictionary *dict) for ( v = 0; v < n_vars; ++v ) n_rows += group_proc_get (vars[v])->n_groups + 1; - t = tab_create (n_cols, n_rows, 0); + t = tab_create (n_cols, n_rows); tab_headers (t, 2, 0, 2, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); /* Put a frame around the entire box, and vertical lines inside */ @@ -517,9 +517,9 @@ show_homogeneity (void) struct tab_table *t; - t = tab_create (n_cols, n_rows, 0); + t = tab_create (n_cols, n_rows); tab_headers (t, 1, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); /* Put a frame around the entire box, and vertical lines inside */ tab_box (t, @@ -577,9 +577,9 @@ show_contrast_coeffs (short *bad_contrast) struct tab_table *t; - t = tab_create (n_cols, n_rows, 0); + t = tab_create (n_cols, n_rows); tab_headers (t, 2, 0, 2, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); /* Put a frame around the entire box, and vertical lines inside */ tab_box (t, @@ -661,9 +661,9 @@ show_contrast_tests (short *bad_contrast) struct tab_table *t; - t = tab_create (n_cols, n_rows, 0); + t = tab_create (n_cols, n_rows); tab_headers (t, 3, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); /* Put a frame around the entire box, and vertical lines inside */ tab_box (t, diff --git a/src/language/stats/regression.q b/src/language/stats/regression.q index 41a23f3e..b61ae586 100644 --- a/src/language/stats/regression.q +++ b/src/language/stats/regression.q @@ -149,8 +149,8 @@ reg_stats_r (pspp_linreg_cache * c) rsq = c->ssm / c->sst; adjrsq = 1.0 - (1.0 - rsq) * (c->n_obs - 1.0) / (c->n_obs - c->n_indeps); std_error = sqrt (pspp_linreg_mse (c)); - t = tab_create (n_cols, n_rows, 0); - tab_dim (t, tab_natural_dimensions, NULL); + t = tab_create (n_cols, n_rows); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); tab_hline (t, TAL_2, 0, n_cols - 1, 1); tab_vline (t, TAL_2, 2, 0, n_rows - 1); @@ -191,9 +191,9 @@ reg_stats_coeff (pspp_linreg_cache * c) assert (c != NULL); n_rows = c->n_coeffs + 3; - t = tab_create (n_cols, n_rows, 0); + t = tab_create (n_cols, n_rows); tab_headers (t, 2, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); tab_hline (t, TAL_2, 0, n_cols - 1, 1); tab_vline (t, TAL_2, 2, 0, n_rows - 1); @@ -288,9 +288,9 @@ reg_stats_anova (pspp_linreg_cache * c) struct tab_table *t; assert (c != NULL); - t = tab_create (n_cols, n_rows, 0); + t = tab_create (n_cols, n_rows); tab_headers (t, 2, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); @@ -379,9 +379,9 @@ reg_stats_bcov (pspp_linreg_cache * c) assert (c != NULL); n_cols = c->n_indeps + 1 + 2; n_rows = 2 * (c->n_indeps + 1); - t = tab_create (n_cols, n_rows, 0); + t = tab_create (n_cols, n_rows); tab_headers (t, 2, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); tab_hline (t, TAL_2, 0, n_cols - 1, 1); tab_vline (t, TAL_2, 2, 0, n_rows - 1); diff --git a/src/language/stats/reliability.q b/src/language/stats/reliability.q index 681669d1..dfb81367 100644 --- a/src/language/stats/reliability.q +++ b/src/language/stats/reliability.q @@ -381,9 +381,9 @@ run_reliability (struct casereader *input, struct dataset *ds, { - struct tab_table *tab = tab_create(1, 1, 0); + struct tab_table *tab = tab_create(1, 1); - tab_dim (tab, tab_natural_dimensions, NULL); + tab_dim (tab, tab_natural_dimensions, NULL, NULL); tab_flags (tab, SOMF_NO_TITLE ); tab_text_format (tab, 0, 0, 0, "Scale: %s", ds_cstr (&rel->scale_name)); @@ -425,10 +425,10 @@ reliability_statistics (const struct reliability *rel) int heading_columns = rol[rel->model].heading_cols; int heading_rows = rol[rel->model].heading_rows; - struct tab_table *tbl = tab_create (n_cols, n_rows, 0); + struct tab_table *tbl = tab_create (n_cols, n_rows); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); tab_title (tbl, _("Reliability Statistics")); @@ -468,10 +468,10 @@ reliability_summary_total (const struct reliability *rel) const int heading_rows = 1; const int n_rows = rel->sc[0].n_items + heading_rows ; - struct tab_table *tbl = tab_create (n_cols, n_rows, 0); + struct tab_table *tbl = tab_create (n_cols, n_rows); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); tab_title (tbl, _("Item-Total Statistics")); @@ -678,10 +678,10 @@ case_processing_summary (casenumber n_valid, casenumber n_missing, int heading_columns = 2; int heading_rows = 1; struct tab_table *tbl; - tbl = tab_create (n_cols, n_rows, 0); + tbl = tab_create (n_cols, n_rows); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); tab_title (tbl, _("Case Processing Summary")); diff --git a/src/language/stats/roc.c b/src/language/stats/roc.c index 86aee1f9..1f2691d8 100644 --- a/src/language/stats/roc.c +++ b/src/language/stats/roc.c @@ -16,6 +16,8 @@ #include +#include + #include #include #include @@ -36,8 +38,8 @@ #include #include -#include -#include +#include +#include #include "gettext.h" #define _(msgid) gettext (msgid) @@ -386,13 +388,6 @@ struct roc_state double max; }; -#define CUTPOINT 0 -#define TP 1 -#define FN 2 -#define TN 3 -#define FP 4 - - /* Return a new casereader based upon CUTPOINT_RDR. The number of "positive" cases are placed into @@ -418,7 +413,7 @@ accumulate_counts (struct casereader *cutpoint_rdr, for ( ; (cpc = casereader_read (r) ); case_unref (cpc)) { struct ccase *new_case; - const double cp = case_data_idx (cpc, CUTPOINT)->f; + const double cp = case_data_idx (cpc, ROC_CUTPOINT)->f; assert (cp != SYSMIS); @@ -582,7 +577,7 @@ process_positive_group (const struct variable *var, struct casereader *reader, return process_group (var, reader, gt, dict, &rs->n1, &rs->cutpoint_rdr, ge, - TP, FN); + ROC_TP, ROC_FN); } /* @@ -600,7 +595,7 @@ process_negative_group (const struct variable *var, struct casereader *reader, return process_group (var, reader, lt, dict, &rs->n2, &rs->cutpoint_rdr, lt, - TN, FP); + ROC_TN, ROC_FP); } @@ -611,11 +606,11 @@ append_cutpoint (struct casewriter *writer, double cutpoint) { struct ccase *cc = case_create (casewriter_get_proto (writer)); - case_data_rw_idx (cc, CUTPOINT)->f = cutpoint; - case_data_rw_idx (cc, TP)->f = 0; - case_data_rw_idx (cc, FN)->f = 0; - case_data_rw_idx (cc, TN)->f = 0; - case_data_rw_idx (cc, FP)->f = 0; + case_data_rw_idx (cc, ROC_CUTPOINT)->f = cutpoint; + case_data_rw_idx (cc, ROC_TP)->f = 0; + case_data_rw_idx (cc, ROC_FN)->f = 0; + case_data_rw_idx (cc, ROC_TN)->f = 0; + case_data_rw_idx (cc, ROC_FP)->f = 0; casewriter_write (writer, cc); } @@ -623,9 +618,9 @@ append_cutpoint (struct casewriter *writer, double cutpoint) /* Create and initialise the rs[x].cutpoint_rdr casereaders. That is, the readers will - be created with width 5, ready to take the values (cutpoint, TP, FN, TN, FP), and the + be created with width 5, ready to take the values (cutpoint, ROC_TP, ROC_FN, ROC_TN, ROC_FP), and the reader will be populated with its final number of cases. - However on exit from this function, only CUTPOINT entries will be set to their final + However on exit from this function, only ROC_CUTPOINT entries will be set to their final value. The other entries will be initialised to zero. */ static void @@ -637,13 +632,13 @@ prepare_cutpoints (struct cmd_roc *roc, struct roc_state *rs, struct casereader struct caseproto *proto = caseproto_create (); struct subcase ordering; - subcase_init (&ordering, CUTPOINT, 0, SC_ASCEND); + subcase_init (&ordering, ROC_CUTPOINT, 0, SC_ASCEND); proto = caseproto_add_width (proto, 0); /* cutpoint */ - proto = caseproto_add_width (proto, 0); /* TP */ - proto = caseproto_add_width (proto, 0); /* FN */ - proto = caseproto_add_width (proto, 0); /* TN */ - proto = caseproto_add_width (proto, 0); /* FP */ + proto = caseproto_add_width (proto, 0); /* ROC_TP */ + proto = caseproto_add_width (proto, 0); /* ROC_FN */ + proto = caseproto_add_width (proto, 0); /* ROC_TN */ + proto = caseproto_add_width (proto, 0); /* ROC_FP */ for (i = 0 ; i < roc->n_vars; ++i) { @@ -935,7 +930,7 @@ show_auc (struct roc_state *rs, const struct cmd_roc *roc) const int n_fields = roc->print_se ? 5 : 1; const int n_cols = roc->n_vars > 1 ? n_fields + 1: n_fields; const int n_rows = 2 + roc->n_vars; - struct tab_table *tbl = tab_create (n_cols, n_rows, 0); + struct tab_table *tbl = tab_create (n_cols, n_rows); if ( roc->n_vars > 1) tab_title (tbl, _("Area Under the Curve")); @@ -944,7 +939,7 @@ show_auc (struct roc_state *rs, const struct cmd_roc *roc) tab_headers (tbl, n_cols - n_fields, 0, 1, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); tab_text (tbl, n_cols - n_fields, 1, TAT_TITLE, _("Area")); @@ -1030,13 +1025,13 @@ show_summary (const struct cmd_roc *roc) { const int n_cols = 3; const int n_rows = 4; - struct tab_table *tbl = tab_create (n_cols, n_rows, 0); + struct tab_table *tbl = tab_create (n_cols, n_rows); tab_title (tbl, _("Case Summary")); tab_headers (tbl, 1, 0, 2, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); tab_box (tbl, TAL_2, TAL_2, @@ -1088,7 +1083,7 @@ show_coords (struct roc_state *rs, const struct cmd_roc *roc) for (i = 0; i < roc->n_vars; ++i) n_rows += casereader_count_cases (rs[i].cutpoint_rdr); - tbl = tab_create (n_cols, n_rows, 0); + tbl = tab_create (n_cols, n_rows); if ( roc->n_vars > 1) tab_title (tbl, _("Coordinates of the Curve")); @@ -1098,7 +1093,7 @@ show_coords (struct roc_state *rs, const struct cmd_roc *roc) tab_headers (tbl, 1, 0, 1, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); tab_hline (tbl, TAL_2, 0, n_cols - 1, 1); @@ -1134,21 +1129,21 @@ show_coords (struct roc_state *rs, const struct cmd_roc *roc) for (; (cc = casereader_read (r)) != NULL; case_unref (cc), x++) { - const double se = case_data_idx (cc, TP)->f / + const double se = case_data_idx (cc, ROC_TP)->f / ( - case_data_idx (cc, TP)->f + case_data_idx (cc, ROC_TP)->f + - case_data_idx (cc, FN)->f + case_data_idx (cc, ROC_FN)->f ); - const double sp = case_data_idx (cc, TN)->f / + const double sp = case_data_idx (cc, ROC_TN)->f / ( - case_data_idx (cc, TN)->f + case_data_idx (cc, ROC_TN)->f + - case_data_idx (cc, FP)->f + case_data_idx (cc, ROC_FP)->f ); - tab_double (tbl, n_cols - 3, x, 0, case_data_idx (cc, CUTPOINT)->f, + tab_double (tbl, n_cols - 3, x, 0, case_data_idx (cc, ROC_CUTPOINT)->f, var_get_print_format (roc->vars[i])); tab_double (tbl, n_cols - 2, x, 0, se, NULL); @@ -1162,68 +1157,25 @@ show_coords (struct roc_state *rs, const struct cmd_roc *roc) } -static void -draw_roc (struct roc_state *rs, const struct cmd_roc *roc) -{ - int i; - - struct chart *roc_chart = chart_create (); - - chart_write_title (roc_chart, _("ROC Curve")); - chart_write_xlabel (roc_chart, _("1 - Specificity")); - chart_write_ylabel (roc_chart, _("Sensitivity")); - - chart_write_xscale (roc_chart, 0, 1, 5); - chart_write_yscale (roc_chart, 0, 1, 5); - - if ( roc->reference ) - { - chart_line (roc_chart, 1.0, 0, - 0.0, 1.0, - CHART_DIM_X); - } - - for (i = 0; i < roc->n_vars; ++i) - { - struct ccase *cc; - struct casereader *r = casereader_clone (rs[i].cutpoint_rdr); - - chart_vector_start (roc_chart, var_get_name (roc->vars[i])); - for (; (cc = casereader_read (r)) != NULL; - case_unref (cc)) - { - double se = case_data_idx (cc, TP)->f; - double sp = case_data_idx (cc, TN)->f; - - se /= case_data_idx (cc, FN)->f + - case_data_idx (cc, TP)->f ; - - sp /= case_data_idx (cc, TN)->f + - case_data_idx (cc, FP)->f ; - - chart_vector (roc_chart, 1 - sp, se); - } - chart_vector_end (roc_chart); - casereader_destroy (r); - } - - chart_write_legend (roc_chart); - - chart_submit (roc_chart); -} - - static void output_roc (struct roc_state *rs, const struct cmd_roc *roc) { show_summary (roc); if ( roc->curve ) - draw_roc (rs, roc); + { + struct roc_chart *rc; + size_t i; + + rc = roc_chart_create (roc->reference); + for (i = 0; i < roc->n_vars; i++) + roc_chart_add_var (rc, var_get_name (roc->vars[i]), + rs[i].cutpoint_rdr); + chart_submit (roc_chart_get_chart (rc)); + } show_auc (rs, roc); - if ( roc->print_coords ) show_coords (rs, roc); } diff --git a/src/language/stats/roc.h b/src/language/stats/roc.h new file mode 100644 index 00000000..5d63c96f --- /dev/null +++ b/src/language/stats/roc.h @@ -0,0 +1,28 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef LANGUAGE_STATS_ROC_H +#define LANGUAGE_STATS_ROC_H 1 + +/* These are case indexes into the cutpoint case readers for ROC + output, used by roc.c and roc-chart.c. */ +#define ROC_CUTPOINT 0 +#define ROC_TP 1 +#define ROC_FN 2 +#define ROC_TN 3 +#define ROC_FP 4 + +#endif /* language/stats/roc.h */ diff --git a/src/language/stats/sign.c b/src/language/stats/sign.c index a5a27212..d5970c6f 100644 --- a/src/language/stats/sign.c +++ b/src/language/stats/sign.c @@ -52,12 +52,12 @@ output_frequency_table (const struct two_sample_test *t2s, const struct dictionary *dict) { int i; - struct tab_table *table = tab_create (3, 1 + 4 * t2s->n_pairs, 0); + struct tab_table *table = tab_create (3, 1 + 4 * t2s->n_pairs); const struct variable *wv = dict_get_weight (dict); const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0; - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Frequencies")); @@ -65,11 +65,11 @@ output_frequency_table (const struct two_sample_test *t2s, /* Vertical lines inside the box */ tab_box (table, 0, 0, -1, TAL_1, - 1, 0, table->nc - 1, tab_nr (table) - 1 ); + 1, 0, tab_nc (table) - 1, tab_nr (table) - 1 ); /* Box around entire table */ tab_box (table, TAL_2, TAL_2, -1, -1, - 0, 0, table->nc - 1, tab_nr (table) - 1 ); + 0, 0, tab_nc (table) - 1, tab_nr (table) - 1 ); tab_text (table, 2, 0, TAB_CENTER, _("N")); @@ -86,7 +86,7 @@ output_frequency_table (const struct two_sample_test *t2s, ds_destroy (&pair_name); - tab_hline (table, TAL_1, 0, table->nc - 1, 1 + i * 4); + tab_hline (table, TAL_1, 0, tab_nc (table) - 1, 1 + i * 4); tab_text (table, 1, 1 + i * 4, TAB_LEFT, _("Negative Differences")); tab_text (table, 1, 2 + i * 4, TAB_LEFT, _("Positive Differences")); @@ -108,26 +108,26 @@ output_statistics_table (const struct two_sample_test *t2s, const struct sign_test_params *param) { int i; - struct tab_table *table = tab_create (1 + t2s->n_pairs, 4, 0); + struct tab_table *table = tab_create (1 + t2s->n_pairs, 4); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Test Statistics")); tab_headers (table, 0, 1, 0, 1); - tab_hline (table, TAL_2, 0, table->nc - 1, 1); - tab_vline (table, TAL_2, 1, 0, table->nr - 1); + tab_hline (table, TAL_2, 0, tab_nc (table) - 1, 1); + tab_vline (table, TAL_2, 1, 0, tab_nr (table) - 1); /* Vertical lines inside the box */ tab_box (table, -1, -1, -1, TAL_1, 0, 0, - table->nc - 1, tab_nr (table) - 1); + tab_nc (table) - 1, tab_nr (table) - 1); /* Box around entire table */ tab_box (table, TAL_2, TAL_2, -1, -1, - 0, 0, table->nc - 1, + 0, 0, tab_nc (table) - 1, tab_nr (table) - 1); tab_text (table, 0, 1, TAT_TITLE | TAB_LEFT, diff --git a/src/language/stats/t-test.q b/src/language/stats/t-test.q index 8f23cefd..a483bd9e 100644 --- a/src/language/stats/t-test.q +++ b/src/language/stats/t-test.q @@ -477,13 +477,13 @@ static void ssbox_base_init (struct ssbox *this, int cols, int rows) { this->finalize = ssbox_base_finalize; - this->t = tab_create (cols, rows, 0); + this->t = tab_create (cols, rows); - tab_columns (this->t, SOM_COL_DOWN, 1); + tab_columns (this->t, SOM_COL_DOWN); tab_headers (this->t, 0, 0, 1, 0); tab_box (this->t, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1); tab_hline (this->t, TAL_2, 0, cols- 1, 1); - tab_dim (this->t, tab_natural_dimensions, NULL); + tab_dim (this->t, tab_natural_dimensions, NULL, NULL); } /* ssbox implementations. */ @@ -1069,11 +1069,11 @@ trbox_base_init (struct trbox *self, size_t data_rows, int cols) const size_t rows = 3 + data_rows; self->finalize = trbox_base_finalize; - self->t = tab_create (cols, rows, 0); + self->t = tab_create (cols, rows); tab_headers (self->t, 0, 0, 3, 0); tab_box (self->t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols - 1, rows - 1); tab_hline (self->t, TAL_2, 0, cols- 1, 3); - tab_dim (self->t, tab_natural_dimensions, NULL); + tab_dim (self->t, tab_natural_dimensions, NULL, NULL); } /* Base finalizer for the trbox */ @@ -1093,14 +1093,14 @@ pscbox (struct t_test_proc *proc) struct tab_table *table; - table = tab_create (cols, rows, 0); + table = tab_create (cols, rows); - tab_columns (table, SOM_COL_DOWN, 1); + tab_columns (table, SOM_COL_DOWN); tab_headers (table, 0, 0, 1, 0); tab_box (table, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1); tab_hline (table, TAL_2, 0, cols - 1, 1); tab_vline (table, TAL_2, 2, 0, rows - 1); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Paired Samples Correlations")); /* column headings */ diff --git a/src/language/stats/wilcoxon.c b/src/language/stats/wilcoxon.c index 310206c0..c7e30277 100644 --- a/src/language/stats/wilcoxon.c +++ b/src/language/stats/wilcoxon.c @@ -225,9 +225,9 @@ show_ranks_box (const struct wilcoxon_state *ws, const struct variable *wv = dict_get_weight (dict); const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0; - struct tab_table *table = tab_create (5, 1 + 4 * t2s->n_pairs, 0); + struct tab_table *table = tab_create (5, 1 + 4 * t2s->n_pairs); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Ranks")); @@ -235,11 +235,11 @@ show_ranks_box (const struct wilcoxon_state *ws, /* Vertical lines inside the box */ tab_box (table, 0, 0, -1, TAL_1, - 1, 0, table->nc - 1, tab_nr (table) - 1 ); + 1, 0, tab_nc (table) - 1, tab_nr (table) - 1 ); /* Box around entire table */ tab_box (table, TAL_2, TAL_2, -1, -1, - 0, 0, table->nc - 1, tab_nr (table) - 1 ); + 0, 0, tab_nc (table) - 1, tab_nr (table) - 1 ); tab_text (table, 2, 0, TAB_CENTER, _("N")); @@ -261,7 +261,7 @@ show_ranks_box (const struct wilcoxon_state *ws, tab_text (table, 1, 3 + i * 4, TAB_LEFT, _("Ties")); tab_text (table, 1, 4 + i * 4, TAB_LEFT, _("Total")); - tab_hline (table, TAL_1, 0, table->nc - 1, 1 + i * 4); + tab_hline (table, TAL_1, 0, tab_nc (table) - 1, 1 + i * 4); tab_text (table, 0, 1 + i * 4, TAB_LEFT, ds_cstr (&pair_name)); @@ -290,8 +290,8 @@ show_ranks_box (const struct wilcoxon_state *ws, } - tab_hline (table, TAL_2, 0, table->nc - 1, 1); - tab_vline (table, TAL_2, 2, 0, table->nr - 1); + tab_hline (table, TAL_2, 0, tab_nc (table) - 1, 1); + tab_vline (table, TAL_2, 2, 0, tab_nr (table) - 1); tab_submit (table); @@ -306,9 +306,9 @@ show_tests_box (const struct wilcoxon_state *ws, ) { size_t i; - struct tab_table *table = tab_create (1 + t2s->n_pairs, exact ? 5 : 3, 0); + struct tab_table *table = tab_create (1 + t2s->n_pairs, exact ? 5 : 3); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Test Statistics")); @@ -316,11 +316,11 @@ show_tests_box (const struct wilcoxon_state *ws, /* Vertical lines inside the box */ tab_box (table, 0, 0, -1, TAL_1, - 0, 0, table->nc - 1, tab_nr (table) - 1 ); + 0, 0, tab_nc (table) - 1, tab_nr (table) - 1 ); /* Box around entire table */ tab_box (table, TAL_2, TAL_2, -1, -1, - 0, 0, table->nc - 1, tab_nr (table) - 1 ); + 0, 0, tab_nc (table) - 1, tab_nr (table) - 1 ); tab_text (table, 0, 1, TAB_LEFT, _("Z")); @@ -377,8 +377,8 @@ show_tests_box (const struct wilcoxon_state *ws, } } - tab_hline (table, TAL_2, 0, table->nc - 1, 1); - tab_vline (table, TAL_2, 1, 0, table->nr - 1); + tab_hline (table, TAL_2, 0, tab_nc (table) - 1, 1); + tab_vline (table, TAL_2, 1, 0, tab_nr (table) - 1); tab_submit (table); diff --git a/src/language/syntax-file.c b/src/language/syntax-file.c index 0771ade3..9b5fd043 100644 --- a/src/language/syntax-file.c +++ b/src/language/syntax-file.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -62,14 +63,16 @@ struct syntax_file_source static const char * name (const struct getl_interface *s) { - const struct syntax_file_source *sfs = (const struct syntax_file_source *) s; + const struct syntax_file_source *sfs = UP_CAST (s, struct syntax_file_source, + parent); return sfs->fn; } static int line_number (const struct getl_interface *s) { - const struct syntax_file_source *sfs = (const struct syntax_file_source *) s; + const struct syntax_file_source *sfs = UP_CAST (s, struct syntax_file_source, + parent); return sfs->ln; } @@ -80,7 +83,8 @@ static bool read_syntax_file (struct getl_interface *s, struct string *line) { - struct syntax_file_source *sfs = (struct syntax_file_source *) s; + struct syntax_file_source *sfs = UP_CAST (s, struct syntax_file_source, + parent); /* Open file, if not yet opened. */ if (sfs->syntax_file == NULL) @@ -121,7 +125,8 @@ read_syntax_file (struct getl_interface *s, static void syntax_close (struct getl_interface *s) { - struct syntax_file_source *sfs = (struct syntax_file_source *) s; + struct syntax_file_source *sfs = UP_CAST (s, struct syntax_file_source, + parent); if (sfs->syntax_file && EOF == fn_close (sfs->fn, sfs->syntax_file)) msg (MW, _("Closing `%s': %s."), sfs->fn, strerror (errno)); @@ -151,6 +156,6 @@ create_syntax_file_source (const char *fn) ss->parent.name = name ; ss->parent.location = line_number; - return (struct getl_interface *) ss; + return &ss->parent; } diff --git a/src/language/syntax-string-source.c b/src/language/syntax-string-source.c index 94a56f97..405141cd 100644 --- a/src/language/syntax-string-source.c +++ b/src/language/syntax-string-source.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical interface for PSPP. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -60,7 +61,8 @@ location (const struct getl_interface *i UNUSED) static void do_close (struct getl_interface *i ) { - struct syntax_string_source *sss = (struct syntax_string_source *) i; + struct syntax_string_source *sss = UP_CAST (i, struct syntax_string_source, + parent); ds_destroy (&sss->buffer); @@ -73,7 +75,8 @@ static bool read_single_line (struct getl_interface *i, struct string *line) { - struct syntax_string_source *sss = (struct syntax_string_source *) i; + struct syntax_string_source *sss = UP_CAST (i, struct syntax_string_source, + parent); size_t next; @@ -120,7 +123,7 @@ create_syntax_string_source (const char *format, ...) sss->parent.location = location; - return (struct getl_interface *) sss; + return &sss->parent; } /* Return the syntax currently contained in S. diff --git a/src/language/utilities/echo.c b/src/language/utilities/echo.c index 19e9f9e5..3d3c2c40 100644 --- a/src/language/utilities/echo.c +++ b/src/language/utilities/echo.c @@ -33,9 +33,9 @@ cmd_echo (struct lexer *lexer, struct dataset *ds UNUSED) if (lex_token (lexer) != T_STRING) return CMD_FAILURE; - tab = tab_create(1, 1, 0); + tab = tab_create(1, 1); - tab_dim (tab, tab_natural_dimensions, NULL); + tab_dim (tab, tab_natural_dimensions, NULL, NULL); tab_flags (tab, SOMF_NO_TITLE ); tab_text(tab, 0, 0, 0, ds_cstr (lex_tokstr (lexer))); diff --git a/src/language/xforms/count.c b/src/language/xforms/count.c index 8ce2d125..4fb889b1 100644 --- a/src/language/xforms/count.c +++ b/src/language/xforms/count.c @@ -352,7 +352,7 @@ count_trns_proc (void *trns_, struct ccase **c, static bool count_trns_free (void *trns_) { - struct count_trns *trns = (struct count_trns *) trns_; + struct count_trns *trns = trns_; pool_destroy (trns->pool); return true; } diff --git a/src/libpspp/abt.c b/src/libpspp/abt.c index 74b2ceb3..b7766129 100644 --- a/src/libpspp/abt.c +++ b/src/libpspp/abt.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #endif #include +#include #include @@ -145,8 +146,8 @@ insert_relative (struct abt *abt, const struct abt_node *p, bool after, p = p->down[dir]; dir = !after; } - ((struct abt_node *) p)->down[dir] = node; - node->up = (struct abt_node *) p; + CONST_CAST (struct abt_node *, p)->down[dir] = node; + node->up = CONST_CAST (struct abt_node *, p); abt_reaugmented (abt, node); } @@ -280,7 +281,7 @@ abt_find (const struct abt *abt, const struct abt_node *target) { cmp = abt->compare (target, p, abt->aux); if (cmp == 0) - return (struct abt_node *) p; + return CONST_CAST (struct abt_node *, p); } return NULL; @@ -307,7 +308,7 @@ abt_next (const struct abt *abt, const struct abt_node *p) p = p->down[1]; while (p->down[0] != NULL) p = p->down[0]; - return (struct abt_node *) p; + return CONST_CAST (struct abt_node *, p); } } @@ -332,7 +333,7 @@ abt_prev (const struct abt *abt, const struct abt_node *p) p = p->down[0]; while (p->down[1] != NULL) p = p->down[1]; - return (struct abt_node *) p; + return CONST_CAST (struct abt_node *, p); } } diff --git a/src/libpspp/abt.h b/src/libpspp/abt.h index 3801eb86..24d7268a 100644 --- a/src/libpspp/abt.h +++ b/src/libpspp/abt.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -150,12 +150,14 @@ tree paper. */ #include +#include /* Returns the data structure corresponding to the given NODE, assuming that NODE is embedded as the given MEMBER name in data type STRUCT. */ -#define abt_data(NODE, STRUCT, MEMBER) \ - ((STRUCT *) ((char *) (NODE) - offsetof (STRUCT, MEMBER))) +#define abt_data(NODE, STRUCT, MEMBER) \ + (CHECK_POINTER_HAS_TYPE (NODE, struct abt_node *), \ + UP_CAST (NODE, STRUCT, MEMBER)) /* Node in an augmented binary tree. */ struct abt_node diff --git a/src/libpspp/automake.mk b/src/libpspp/automake.mk index 746756d8..30a5424d 100644 --- a/src/libpspp/automake.mk +++ b/src/libpspp/automake.mk @@ -65,6 +65,10 @@ src_libpspp_libpspp_la_SOURCES = \ src/libpspp/sparse-xarray.h \ src/libpspp/start-date.c \ src/libpspp/start-date.h \ + src/libpspp/string-map.c \ + src/libpspp/string-map.h \ + src/libpspp/string-set.c \ + src/libpspp/string-set.h \ src/libpspp/str.c \ src/libpspp/str.h \ src/libpspp/taint.c \ diff --git a/src/libpspp/bt.c b/src/libpspp/bt.c index 26eb982b..751c8fe7 100644 --- a/src/libpspp/bt.c +++ b/src/libpspp/bt.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -67,6 +67,8 @@ #include #include +#include + static void rebalance_subtree (struct bt *, struct bt_node *, size_t); static struct bt_node **down_link (struct bt *, struct bt_node *); @@ -250,7 +252,7 @@ bt_find (const struct bt *bt, const struct bt_node *target) { cmp = bt->compare (target, p, bt->aux); if (cmp == 0) - return (struct bt_node *) p; + return CONST_CAST (struct bt_node *, p); } return NULL; @@ -283,7 +285,7 @@ bt_find_ge (const struct bt *bt, const struct bt_node *target) break; } } - return (struct bt_node *) q; + return CONST_CAST (struct bt_node *, q); } /* Searches BT for, and returns, the last node in in-order whose @@ -314,7 +316,7 @@ bt_find_le (const struct bt *bt, const struct bt_node *target) break; } } - return (struct bt_node *) q; + return CONST_CAST (struct bt_node *, q); } /* Returns the node in BT following P in in-order. @@ -338,7 +340,7 @@ bt_next (const struct bt *bt, const struct bt_node *p) p = p->down[1]; while (p->down[0] != NULL) p = p->down[0]; - return (struct bt_node *) p; + return CONST_CAST (struct bt_node *, p); } } @@ -363,7 +365,7 @@ bt_prev (const struct bt *bt, const struct bt_node *p) p = p->down[0]; while (p->down[1] != NULL) p = p->down[1]; - return (struct bt_node *) p; + return CONST_CAST (struct bt_node *, p); } } diff --git a/src/libpspp/bt.h b/src/libpspp/bt.h index 340b8760..7045632e 100644 --- a/src/libpspp/bt.h +++ b/src/libpspp/bt.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,12 +24,14 @@ fully encapsulated. */ #include +#include /* Returns the data structure corresponding to the given NODE, assuming that NODE is embedded as the given MEMBER name in data type STRUCT. */ -#define bt_data(NODE, STRUCT, MEMBER) \ - ((STRUCT *) ((char *) (NODE) - offsetof (STRUCT, MEMBER))) +#define bt_data(NODE, STRUCT, MEMBER) \ + (CHECK_POINTER_HAS_TYPE (NODE, struct bt_node *), \ + UP_CAST (NODE, STRUCT, MEMBER)) /* Node in a balanced binary tree. */ struct bt_node diff --git a/src/libpspp/cast.h b/src/libpspp/cast.h new file mode 100644 index 00000000..1e33857c --- /dev/null +++ b/src/libpspp/cast.h @@ -0,0 +1,92 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef LIBPSPP_CAST_H +#define LIBPSPP_CAST_H 1 + +#include + +/* Expands to a void expression that checks that POINTER is an + expression whose type is a qualified or unqualified version of + a type compatible with TYPE (a pointer type) and, if not, + causes a compiler warning to be issued (on typical compilers). + + Examples: + + int *ip; + const int *cip; + const int **cipp; + int ***ippp; + double *dp; + + // None of these causes a warning: + CHECK_POINTER_HAS_TYPE (ip, int *); + CHECK_POINTER_HAS_TYPE (ip, const int *); + CHECK_POINTER_HAS_TYPE (cip, int *); + CHECK_POINTER_HAS_TYPE (cip, const int *); + CHECK_POINTER_HAS_TYPE (dp, double *); + CHECK_POINTER_HAS_TYPE (dp, const double *); + CHECK_POINTER_HAS_TYPE (cipp, const int **); + CHECK_POINTER_HAS_TYPE (cipp, const int *const *); + CHECK_POINTER_HAS_TYPE (ippp, int ***); + CHECK_POINTER_HAS_TYPE (ippp, int **const *); + + // None of these causes a warning either, although it is unusual to + // const-qualify a pointer like this (it's like declaring a "const int", + // for example). + CHECK_POINTER_HAS_TYPE (ip, int *const); + CHECK_POINTER_HAS_TYPE (ip, const int *const); + CHECK_POINTER_HAS_TYPE (cip, int *const); + CHECK_POINTER_HAS_TYPE (cip, const int *const); + CHECK_POINTER_HAS_TYPE (cipp, const int **const); + CHECK_POINTER_HAS_TYPE (cipp, const int *const *const); + CHECK_POINTER_HAS_TYPE (ippp, int ***const); + CHECK_POINTER_HAS_TYPE (ippp, int **const *const); + + // Provokes a warning because "int" is not compatible with "double": + CHECK_POINTER_HAS_TYPE (dp, int *); + + // Provoke warnings because C's type compatibility rules only allow + // adding a "const" qualifier to the outermost pointer: + CHECK_POINTER_HAS_TYPE (ippp, const int ***); + CHECK_POINTER_HAS_TYPE (ippp, int *const**); +*/ +#define CHECK_POINTER_HAS_TYPE(POINTER, TYPE) \ + ((void) sizeof ((TYPE) (POINTER) == (POINTER))) + +/* Given expressions A and B, both of which have pointer type, + expands to a void expression that causes a compiler warning if + A and B are not pointers to qualified or unqualified versions + of compatible types. + + Examples similar to those given for CHECK_POINTER_HAS_TYPE, + above, can easily be devised. */ +#define CHECK_POINTER_COMPATIBILITY(A, B) ((void) sizeof ((A) == (B))) + +/* Equivalent to casting POINTER to TYPE, but also issues a + warning if the cast changes anything other than an outermost + "const" or "volatile" qualifier. */ +#define CONST_CAST(TYPE, POINTER) \ + (CHECK_POINTER_HAS_TYPE (POINTER, TYPE), \ + (TYPE) (POINTER)) + +/* Given POINTER, a pointer to the given MEMBER within structure + STRUCT, returns the address of the STRUCT. */ +#define UP_CAST(POINTER, STRUCT, MEMBER) \ + (CHECK_POINTER_COMPATIBILITY (&((STRUCT *) 0)->MEMBER, POINTER), \ + (STRUCT *) ((char *) (POINTER) - offsetof (STRUCT, MEMBER))) + +#endif /* libpspp/cast.h */ diff --git a/src/libpspp/hash.h b/src/libpspp/hash.h index 57fc2678..e586bcc0 100644 --- a/src/libpspp/hash.h +++ b/src/libpspp/hash.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/libpspp/heap.h b/src/libpspp/heap.h index 13422437..3a3c516a 100644 --- a/src/libpspp/heap.h +++ b/src/libpspp/heap.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -70,6 +70,7 @@ #ifndef LIBPSPP_HEAP_H #define LIBPSPP_HEAP_H 1 +#include #include #include @@ -78,8 +79,9 @@ struct pool; /* Returns the data structure corresponding to the given heap NODE, assuming that NODE is embedded as the given MEMBER name in data type STRUCT. */ -#define heap_data(NODE, STRUCT, MEMBER) \ - ((STRUCT *) ((char *) (NODE) - offsetof (STRUCT, MEMBER))) +#define heap_data(NODE, STRUCT, MEMBER) \ + (CHECK_POINTER_HAS_TYPE (NODE, struct heap_node *), \ + UP_CAST (NODE, STRUCT, MEMBER)) /* A node in a heap. Opaque. One of these structures must be embedded in your heap node. */ diff --git a/src/libpspp/hmap.h b/src/libpspp/hmap.h index e73d84fd..1592f803 100644 --- a/src/libpspp/hmap.h +++ b/src/libpspp/hmap.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -115,13 +115,16 @@ } */ +#include #include +#include /* Returns the data structure corresponding to the given NODE, assuming that NODE is embedded as the given MEMBER name in data type STRUCT. NODE must not be a null pointer. */ #define HMAP_DATA(NODE, STRUCT, MEMBER) \ - ((STRUCT *) ((char *) (NODE) - offsetof (STRUCT, MEMBER))) + (CHECK_POINTER_HAS_TYPE (NODE, struct hmap_node *), \ + UP_CAST (NODE, STRUCT, MEMBER)) /* Like HMAP_DATA, except that a null NODE yields a null pointer result. */ @@ -180,6 +183,7 @@ static inline struct hmap_node *hmap_next (const struct hmap *, const struct hmap_node *); /* Counting. */ +static bool hmap_is_empty (const struct hmap *); static inline size_t hmap_count (const struct hmap *); static inline size_t hmap_capacity (const struct hmap *); @@ -440,6 +444,14 @@ hmap_next (const struct hmap *map, const struct hmap_node *node) : hmap_first_nonempty_bucket__ (map, (node->hash & map->mask) + 1)); } +/* Returns true if MAP currently contains no data items, false + otherwise. */ +static inline bool +hmap_is_empty (const struct hmap *map) +{ + return map->count == 0; +} + /* Returns the number of data items currently in MAP. */ static inline size_t hmap_count (const struct hmap *map) diff --git a/src/libpspp/hmapx.c b/src/libpspp/hmapx.c index d7324508..437b2bdb 100644 --- a/src/libpspp/hmapx.c +++ b/src/libpspp/hmapx.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,7 +32,7 @@ hmapx_destroy (struct hmapx *map) { if (map != NULL) { - if (hmapx_count (map) > 0) + if (!(hmapx_is_empty (map))) { struct hmapx_node *node, *next; for (node = hmapx_first (map); node != NULL; node = next) diff --git a/src/libpspp/hmapx.h b/src/libpspp/hmapx.h index 32a4452f..d463504a 100644 --- a/src/libpspp/hmapx.h +++ b/src/libpspp/hmapx.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -165,6 +165,7 @@ static inline struct hmapx_node *hmapx_next (const struct hmapx *, const struct hmapx_node *); /* Counting. */ +static inline bool hmapx_is_empty (const struct hmapx *); static inline size_t hmapx_count (const struct hmapx *); static inline size_t hmapx_capacity (const struct hmapx *); @@ -404,6 +405,14 @@ hmapx_next (const struct hmapx *map, const struct hmapx_node *node) return HMAP_NEXT (node, struct hmapx_node, hmap_node, &map->hmap); } +/* Returns true if MAP currently contains no data items, false + otherwise. */ +static inline bool +hmapx_is_empty (const struct hmapx *map) +{ + return hmap_is_empty (&map->hmap); +} + /* Returns the number of data items currently in MAP. */ static inline size_t hmapx_count (const struct hmapx *map) diff --git a/src/libpspp/ll.c b/src/libpspp/ll.c index b9d595bc..e6533f2c 100644 --- a/src/libpspp/ll.c +++ b/src/libpspp/ll.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -169,7 +169,7 @@ ll_find_equal (const struct ll *r0, const struct ll *r1, for (x = r0; x != r1; x = ll_next (x)) if (compare (x, target, aux) == 0) break; - return (struct ll *) x; + return CONST_CAST (struct ll *, x); } /* Returns the first node in R0...R1 for which PREDICATE returns @@ -185,7 +185,7 @@ ll_find_if (const struct ll *r0, const struct ll *r1, for (x = r0; x != r1; x = ll_next (x)) if (predicate (x, aux)) break; - return (struct ll *) x; + return CONST_CAST (struct ll *, x); } /* Compares each pair of adjacent nodes in R0...R1 @@ -203,10 +203,10 @@ ll_find_adjacent_equal (const struct ll *r0, const struct ll *r1, for (x = r0, y = ll_next (x); y != r1; x = y, y = ll_next (y)) if (compare (x, y, aux) == 0) - return (struct ll *) x; + return CONST_CAST (struct ll *, x); } - return (struct ll *) r1; + return CONST_CAST (struct ll *, r1); } /* Returns the number of nodes in R0...R1. @@ -272,7 +272,7 @@ ll_max (const struct ll *r0, const struct ll *r1, if (compare (x, max, aux) > 0) max = x; } - return (struct ll *) max; + return CONST_CAST (struct ll *, max); } /* Returns the least node in R0...R1 according to COMPARE given @@ -291,7 +291,7 @@ ll_min (const struct ll *r0, const struct ll *r1, if (compare (x, min, aux) < 0) min = x; } - return (struct ll *) min; + return CONST_CAST (struct ll *, min); } /* Lexicographically compares A0...A1 to B0...B1. @@ -474,7 +474,7 @@ ll_find_run (const struct ll *r0, const struct ll *r1, while (r0 != r1 && compare (ll_prev (r0), r0, aux) <= 0); } - return (struct ll *) r0; + return CONST_CAST (struct ll *, r0); } /* Merges B0...B1 into A0...A1 according to COMPARE given @@ -681,6 +681,6 @@ ll_find_partition (const struct ll *r0, const struct ll *r1, if (predicate (x, aux)) return NULL; - return (struct ll *) partition; + return CONST_CAST (struct ll *, partition); } diff --git a/src/libpspp/ll.h b/src/libpspp/ll.h index 65ecf55f..bf871f6b 100644 --- a/src/libpspp/ll.h +++ b/src/libpspp/ll.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,6 +50,9 @@ #include #include #include +#include + +#include /* Embedded, circular doubly linked list. @@ -108,8 +111,9 @@ /* Returns the data structure corresponding to the given node LL, assuming that LL is embedded as the given MEMBER name in data type STRUCT. */ -#define ll_data(LL, STRUCT, MEMBER) \ - ((STRUCT *) ((char *) (LL) - offsetof (STRUCT, MEMBER))) +#define ll_data(LL, STRUCT, MEMBER) \ + (CHECK_POINTER_HAS_TYPE(LL, struct ll *), \ + UP_CAST(LL, STRUCT, MEMBER)) /* Linked list node. */ struct ll @@ -378,7 +382,7 @@ ll_tail (const struct ll_list *list) static inline struct ll * ll_null (const struct ll_list *list) { - return (struct ll *) &list->null; + return CONST_CAST (struct ll *, &list->null); } /* Returns the node following LL in its list, diff --git a/src/libpspp/llx.c b/src/libpspp/llx.c index 4dc82bff..c58f840c 100644 --- a/src/libpspp/llx.c +++ b/src/libpspp/llx.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -232,7 +232,7 @@ llx_find_equal (const struct llx *r0, const struct llx *r1, for (x = r0; x != r1; x = llx_next (x)) if (compare (llx_data (x), target, aux) == 0) break; - return (struct llx *) x; + return CONST_CAST (struct llx *, x); } /* Returns the first node in R0...R1 for which PREDICATE returns @@ -248,7 +248,7 @@ llx_find_if (const struct llx *r0, const struct llx *r1, for (x = r0; x != r1; x = llx_next (x)) if (predicate (llx_data (x), aux)) break; - return (struct llx *) x; + return CONST_CAST (struct llx *, x); } /* Compares each pair of adjacent nodes in R0...R1 @@ -266,10 +266,10 @@ llx_find_adjacent_equal (const struct llx *r0, const struct llx *r1, for (x = r0, y = llx_next (x); y != r1; x = y, y = llx_next (y)) if (compare (llx_data (x), llx_data (y), aux) == 0) - return (struct llx *) x; + return CONST_CAST (struct llx *, x); } - return (struct llx *) r1; + return CONST_CAST (struct llx *, r1); } /* Returns the number of nodes in R0...R1. @@ -329,7 +329,7 @@ llx_max (const struct llx *r0, const struct llx *r1, if (compare (llx_data (x), llx_data (max), aux) > 0) max = x; } - return (struct llx *) max; + return CONST_CAST (struct llx *, max); } /* Returns the least node in R0...R1 according to COMPARE given @@ -348,7 +348,7 @@ llx_min (const struct llx *r0, const struct llx *r1, if (compare (llx_data (x), llx_data (min), aux) < 0) min = x; } - return (struct llx *) min; + return CONST_CAST (struct llx *, min); } /* Lexicographically compares A0...A1 to B0...B1. @@ -521,7 +521,7 @@ llx_find_run (const struct llx *r0, const struct llx *r1, llx_data (r0), aux) <= 0); } - return (struct llx *) r0; + return CONST_CAST (struct llx *, r0); } /* Merges B0...B1 into A0...A1 according to COMPARE given @@ -734,7 +734,7 @@ llx_find_partition (const struct llx *r0, const struct llx *r1, if (predicate (llx_data (x), aux)) return NULL; - return (struct llx *) partition; + return CONST_CAST (struct llx *, partition); } /* Allocates and returns a node using malloc. */ diff --git a/src/libpspp/range-map.h b/src/libpspp/range-map.h index 3dd77c9f..024fe937 100644 --- a/src/libpspp/range-map.h +++ b/src/libpspp/range-map.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,12 +33,14 @@ #include #include +#include /* Returns the data structure corresponding to the given NODE, assuming that NODE is embedded as the given MEMBER name in data type STRUCT. */ #define range_map_data(NODE, STRUCT, MEMBER) \ - ((STRUCT *) ((char *) (NODE) - offsetof (STRUCT, MEMBER))) + (CHECK_POINTER_HAS_TYPE (NODE, struct range_map_node *), \ + UP_CAST (NODE, STRUCT, MEMBER)) /* A range map node, to be embedded in the data value. */ struct range_map_node diff --git a/src/libpspp/range-set.c b/src/libpspp/range-set.c index efa3b4d6..cd17fe02 100644 --- a/src/libpspp/range-set.c +++ b/src/libpspp/range-set.c @@ -287,7 +287,7 @@ range_set_allocate_fully (struct range_set *rs, unsigned long int request, bool range_set_contains (const struct range_set *rs_, unsigned long int position) { - struct range_set *rs = (struct range_set *) rs_; + struct range_set *rs = CONST_CAST (struct range_set *, rs_); if (position < rs->cache_end && position >= rs->cache_start) return rs->cache_value; else @@ -328,7 +328,7 @@ range_set_contains (const struct range_set *rs_, unsigned long int position) unsigned long int range_set_scan (const struct range_set *rs_, unsigned long int start) { - struct range_set *rs = (struct range_set *) rs_; + struct range_set *rs = CONST_CAST (struct range_set *, rs_); unsigned long int retval = ULONG_MAX; struct bt_node *bt_node; diff --git a/src/libpspp/range-set.h b/src/libpspp/range-set.h index 941692b4..ee7dac23 100644 --- a/src/libpspp/range-set.h +++ b/src/libpspp/range-set.h @@ -26,6 +26,7 @@ #include #include +#include /* A set of ranges. */ struct range_set @@ -122,7 +123,7 @@ static inline const struct range_set_node * range_set_next (const struct range_set *rs, const struct range_set_node *node) { return (node != NULL - ? range_set_next__ (rs, (struct range_set_node *) node) + ? range_set_next__ (rs, CONST_CAST (struct range_set_node *, node)) : range_set_first__ (rs)); } @@ -147,7 +148,7 @@ static inline const struct range_set_node * range_set_prev (const struct range_set *rs, const struct range_set_node *node) { return (node != NULL - ? range_set_prev__ (rs, (struct range_set_node *) node) + ? range_set_prev__ (rs, CONST_CAST (struct range_set_node *, node)) : range_set_last__ (rs)); } diff --git a/src/libpspp/sparse-array.c b/src/libpspp/sparse-array.c index 28398d5c..298f2caf 100644 --- a/src/libpspp/sparse-array.c +++ b/src/libpspp/sparse-array.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -577,7 +578,7 @@ leaf_size (const struct sparse_array *spar) static struct leaf_node * find_leaf_node (const struct sparse_array *spar_, unsigned long int key) { - struct sparse_array *spar = (struct sparse_array *) spar_; + struct sparse_array *spar = CONST_CAST (struct sparse_array *, spar_); const union pointer *p; int level; @@ -679,7 +680,7 @@ static void * scan_forward (const struct sparse_array *spar_, unsigned long int start, unsigned long int *found) { - struct sparse_array *spar = (struct sparse_array *) spar_; + struct sparse_array *spar = CONST_CAST (struct sparse_array *, spar_); /* Check the cache. */ if (start >> BITS_PER_LEVEL == spar->cache_ofs) @@ -761,7 +762,7 @@ static void * scan_reverse (const struct sparse_array *spar_, unsigned long int start, unsigned long int *found) { - struct sparse_array *spar = (struct sparse_array *) spar_; + struct sparse_array *spar = CONST_CAST (struct sparse_array *, spar_); /* Check the cache. */ if (start >> BITS_PER_LEVEL == spar->cache_ofs) diff --git a/src/libpspp/str.c b/src/libpspp/str.c index afe32de9..8243aa06 100644 --- a/src/libpspp/str.c +++ b/src/libpspp/str.c @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -1214,7 +1215,7 @@ ds_capacity (const struct string *st) char * ds_cstr (const struct string *st_) { - struct string *st = (struct string *) st_; + struct string *st = CONST_CAST (struct string *, st_); if (st->ss.string == NULL) ds_extend (st, 1); st->ss.string[st->ss.length] = '\0'; diff --git a/src/libpspp/string-map.c b/src/libpspp/string-map.c new file mode 100644 index 00000000..48124797 --- /dev/null +++ b/src/libpspp/string-map.c @@ -0,0 +1,366 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include +#include + +#include +#include + +#include "gl/xalloc.h" + +static struct string_map_node *string_map_find_node__ ( + const struct string_map *, const char *key, unsigned int hash); +static bool string_map_delete__ (struct string_map *, const char *key, + unsigned int hash); +static struct string_map_node *string_map_insert__ (struct string_map *, + char *key, char *value, + unsigned int hash); + +/* Sets NODE's value to a copy of NEW_VALUE and returns the node's previous + value. The caller is responsible for freeing the returned string (with + free()). */ +char * +string_map_node_swap_value (struct string_map_node *node, + const char *new_value) +{ + return string_map_node_swap_value_nocopy (node, xstrdup (new_value)); +} + +/* Sets NODE's value to NEW_VALUE, which must be a malloc()'d string, + transferring ownership of NEW_VALUE to the node. Returns the node's + previous value, which the caller is responsible for freeing (with + free()). */ +char * +string_map_node_swap_value_nocopy (struct string_map_node *node, + char *new_value) +{ + char *old_value = node->value; + node->value = new_value; + return old_value; +} + +/* Replaces NODE's value by a copy of VALUE. */ +void +string_map_node_set_value (struct string_map_node *node, const char *value) +{ + string_map_node_set_value_nocopy (node, xstrdup (value)); +} + +/* Replaces NODE's value by VALUE, which must be a malloc()'d string, + transferring ownership of VALUE to the node.. */ +void +string_map_node_set_value_nocopy (struct string_map_node *node, char *value) +{ + free (node->value); + node->value = value; +} + +/* Frees NODE and and its key and value. Ordinarily nodes are owned by + string_maps, but this function should only be used by a caller that owns + NODE, such as one that has called string_map_delete_nofree() for the + node. */ +void +string_map_node_destroy (struct string_map_node *node) +{ + free (node->key); + free (node->value); + free (node); +} + +/* Initializes MAP as an initially empty string map. */ +void +string_map_init (struct string_map *map) +{ + hmap_init (&map->hmap); +} + +/* Initializes MAP as a new string map that initially contains the same pairs + as OLD. */ +void +string_map_clone (struct string_map *map, const struct string_map *old) +{ + const struct string_map_node *node; + const char *key, *value; + + string_map_init (map); + hmap_reserve (&map->hmap, string_map_count (old)); + STRING_MAP_FOR_EACH_KEY_VALUE (key, value, node, old) + string_map_insert__ (map, xstrdup (key), xstrdup (value), + node->hmap_node.hash); +} + +/* Exchanges the contents of string maps A and B. */ +void +string_map_swap (struct string_map *a, struct string_map *b) +{ + hmap_swap (&a->hmap, &b->hmap); +} + +/* Frees MAP and its nodes and key-value pairs. */ +void +string_map_destroy (struct string_map *map) +{ + if (map != NULL) + { + string_map_clear (map); + hmap_destroy (&map->hmap); + } +} + +/* Returns true if MAP contains KEY as a key, otherwise false. */ +bool +string_map_contains (const struct string_map *map, const char *key) +{ + return string_map_find_node (map, key) != NULL; +} + +/* If MAP contains KEY as a key, returns the corresponding value. Otherwise, + returns a null pointer. */ +const char * +string_map_find (const struct string_map *map, const char *key) +{ + const struct string_map_node *node = string_map_find_node (map, key); + return node != NULL ? node->value : NULL; +} + +/* If MAP contains KEY as a key, returns the corresponding node. Otherwise, + returns a null pointer. */ +struct string_map_node * +string_map_find_node (const struct string_map *map, const char *key) +{ + return string_map_find_node__ (map, key, hash_string (key, 0)); +} + +/* If MAP contains KEY as a key, deletes that key's node and returns its value, + which the caller is responsible for freeing (using free()). Otherwise, + returns a null pointer. */ +char * +string_map_find_and_delete (struct string_map *map, const char *key) +{ + struct string_map_node *node = string_map_find_node (map, key); + char *value = NULL; + if (node != NULL) + { + value = node->value; + node->value = NULL; + string_map_delete_node (map, node); + } + return value; +} + +/* If MAP does not contain KEY as a key, inserts a new node containing copies + of KEY and VALUE and returns the new node. Otherwise, returns the existing + node that contains KEY. */ +struct string_map_node * +string_map_insert (struct string_map *map, const char *key, const char *value) +{ + unsigned int hash = hash_string (key, 0); + struct string_map_node *node = string_map_find_node__ (map, key, hash); + if (node == NULL) + node = string_map_insert__ (map, xstrdup (key), xstrdup (value), hash); + return node; +} + +/* If MAP does not contain KEY as a key, inserts a new node containing KEY and + VALUE and returns the new node. Otherwise, returns the existing node that + contains KEY. Either way, ownership of KEY and VALUE is transferred to + MAP. */ +struct string_map_node * +string_map_insert_nocopy (struct string_map *map, char *key, char *value) +{ + unsigned int hash = hash_string (key, 0); + struct string_map_node *node = string_map_find_node__ (map, key, hash); + if (node == NULL) + node = string_map_insert__ (map, key, value, hash); + else + { + free (key); + free (value); + } + return node; +} + +/* If MAP does not contain KEY as a key, inserts a new node containing copies + of KEY and VALUE. Otherwise, replaces the existing node's value by a copy + of VALUE. Returns the node. */ +struct string_map_node * +string_map_replace (struct string_map *map, const char *key, const char *value) +{ + unsigned int hash = hash_string (key, 0); + struct string_map_node *node = string_map_find_node__ (map, key, hash); + if (node == NULL) + node = string_map_insert__ (map, xstrdup (key), xstrdup (value), hash); + else + string_map_node_set_value (node, value); + return node; +} + +/* If MAP does not contain KEY as a key, inserts a new node containing KEY and + VALUE. Otherwise, replaces the existing node's value by VALUE. Either way, + ownership of KEY and VALUE is transferred to MAP. Returns the node. */ +struct string_map_node * +string_map_replace_nocopy (struct string_map *map, char *key, char *value) +{ + unsigned int hash = hash_string (key, 0); + struct string_map_node *node = string_map_find_node__ (map, key, hash); + if (node == NULL) + node = string_map_insert__ (map, key, value, hash); + else + { + free (key); + string_map_node_set_value_nocopy (node, value); + } + return node; +} + +/* Searches MAP for a node with KEY as its key. If found, deletes the node + and its key and value and returns true. Otherwise, returns false without + modifying MAP. */ +bool +string_map_delete (struct string_map *map, const char *key) +{ + return string_map_delete__ (map, key, hash_string (key, 0)); +} + +/* Deletes NODE from MAP and destroys the node and its key and value. */ +void +string_map_delete_node (struct string_map *map, struct string_map_node *node) +{ + string_map_delete_nofree (map, node); + string_map_node_destroy (node); +} + +/* Deletes NODE from MAP. Transfers ownership of NODE to the caller, which + becomes responsible for destroying it. */ +void +string_map_delete_nofree (struct string_map *map, struct string_map_node *node) +{ + hmap_delete (&map->hmap, &node->hmap_node); +} + +/* Removes all nodes from MAP and frees them and their keys and values. */ +void +string_map_clear (struct string_map *map) +{ + struct string_map_node *node, *next; + + STRING_MAP_FOR_EACH_NODE_SAFE (node, next, map) + string_map_delete_node (map, node); +} + +/* Inserts a copy of each of the nodes in SRC into DST. When SRC and DST both + have a particular key, the value in DST's node is left unchanged. */ +void +string_map_insert_map (struct string_map *dst, const struct string_map *src) +{ + const struct string_map_node *node; + + STRING_MAP_FOR_EACH_NODE (node, src) + { + if (!string_map_find_node__ (dst, node->key, node->hmap_node.hash)) + string_map_insert__ (dst, xstrdup (node->key), xstrdup (node->value), + node->hmap_node.hash); + } +} + +/* Inserts a copy of each of the nodes in SRC into DST. When SRC and DST both + have a particular key, the value in DST's node is replaced by a copy of the + value in SRC's node. */ +void +string_map_replace_map (struct string_map *dst, const struct string_map *src) +{ + const struct string_map_node *snode; + + STRING_MAP_FOR_EACH_NODE (snode, src) + { + struct string_map_node *dnode; + dnode = string_map_find_node__ (dst, snode->key, snode->hmap_node.hash); + if (dnode != NULL) + string_map_node_set_value (dnode, snode->value); + else + string_map_insert__ (dst, xstrdup (snode->key), xstrdup (snode->value), + snode->hmap_node.hash); + } +} + +/* Inserts each of the keys in MAP into KEYS. KEYS must already have been + initialized (using string_set_init()). */ +void +string_map_get_keys (const struct string_map *map, struct string_set *keys) +{ + const struct string_map_node *node; + const char *key; + + STRING_MAP_FOR_EACH_KEY (key, node, map) + string_set_insert (keys, key); +} + +/* Inserts each of the values in MAP into VALUES. VALUES must already have + been initialized (using string_set_init()). */ +void +string_map_get_values (const struct string_map *map, struct string_set *values) +{ + const struct string_map_node *node; + const char *value; + + STRING_MAP_FOR_EACH_VALUE (value, node, map) + string_set_insert (values, value); +} + +static struct string_map_node * +string_map_find_node__ (const struct string_map *map, const char *key, + unsigned int hash) +{ + struct string_map_node *node; + + HMAP_FOR_EACH_WITH_HASH (node, struct string_map_node, hmap_node, + hash, &map->hmap) + if (!strcmp (key, node->key)) + return node; + + return NULL; +} + +static bool +string_map_delete__ (struct string_map *map, const char *key, + unsigned int hash) +{ + struct string_map_node *node = string_map_find_node__ (map, key, hash); + if (node != NULL) + { + string_map_delete_node (map, node); + return true; + } + else + return false; +} + +static struct string_map_node * +string_map_insert__ (struct string_map *map, char *key, char *value, + unsigned int hash) +{ + struct string_map_node *node = xmalloc (sizeof *node); + node->key = key; + node->value = value; + hmap_insert (&map->hmap, &node->hmap_node, hash); + return node; +} + diff --git a/src/libpspp/string-map.h b/src/libpspp/string-map.h new file mode 100644 index 00000000..f8ffabcf --- /dev/null +++ b/src/libpspp/string-map.h @@ -0,0 +1,213 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef LIBPSPP_STRING_MAP_H +#define LIBPSPP_STRING_MAP_H + +/* Map from a unique string key to a string value. + + This is a convenient wrapper around a "struct hmap" for storing string + key-value pairs. */ + +#include +#include + +struct string_set; + +/* A node within a string map. */ +struct string_map_node + { + struct hmap_node hmap_node; + char *key; + char *value; + }; + +/* Returns the string key within NODE. The caller must not modify or free the + returned string. */ +static inline const char * +string_map_node_get_key (const struct string_map_node *node) +{ + return node->key; +} + +/* Returns the string key within NODE. The caller must not free the returned + string. */ +static inline const char * +string_map_node_get_value (const struct string_map_node *node) +{ + return node->value; +} + +/* Returns the string key within NODE. The caller must not free the returned + string. */ +static inline char * +string_map_node_get_value_rw (struct string_map_node *node) +{ + return node->value; +} + +char *string_map_node_swap_value (struct string_map_node *, + const char *new_value); +char *string_map_node_swap_value_nocopy (struct string_map_node *, + char *new_value); +void string_map_node_set_value (struct string_map_node *, const char *value); +void string_map_node_set_value_nocopy (struct string_map_node *, char *value); +void string_map_node_destroy (struct string_map_node *); + +/* Unordered map from unique string keys to string values. */ +struct string_map + { + struct hmap hmap; + }; + +/* Suitable for use as the initializer for a string_map named MAP. Typical + usage: + struct string_map map = STRING_MAP_INITIALIZER (map); + STRING_MAP_INITIALIZER is an alternative to calling string_map_init. */ +#define STRING_MAP_INITIALIZER(MAP) { HMAP_INITIALIZER ((MAP).hmap) } + +void string_map_init (struct string_map *); +void string_map_clone (struct string_map *, const struct string_map *); +void string_map_swap (struct string_map *, struct string_map *); +void string_map_destroy (struct string_map *); + +static inline size_t string_map_count (const struct string_map *); +static inline bool string_map_is_empty (const struct string_map *); + +bool string_map_contains (const struct string_map *, const char *); +const char *string_map_find (const struct string_map *, const char *); +struct string_map_node *string_map_find_node (const struct string_map *, + const char *); +char *string_map_find_and_delete (struct string_map *, const char *key); + +struct string_map_node *string_map_insert (struct string_map *, + const char *key, const char *value); +struct string_map_node *string_map_insert_nocopy (struct string_map *, + char *key, char *value); +struct string_map_node *string_map_replace (struct string_map *, + const char *key, const char *value); +struct string_map_node *string_map_replace_nocopy (struct string_map *, + char *key, char *value); +bool string_map_delete (struct string_map *, const char *); +void string_map_delete_node (struct string_map *, struct string_map_node *); +void string_map_delete_nofree (struct string_map *, struct string_map_node *); + +void string_map_clear (struct string_map *); +void string_map_insert_map (struct string_map *, const struct string_map *); +void string_map_replace_map (struct string_map *, const struct string_map *); + +void string_map_get_keys (const struct string_map *, struct string_set *); +void string_map_get_values (const struct string_map *, struct string_set *); + +static inline struct string_map_node *string_map_first ( + const struct string_map *); +static inline struct string_map_node *string_map_next ( + const struct string_map *, const struct string_map_node *); + +/* Macros for conveniently iterating through a string_map, e.g. to print all of + the key-value pairs in "my_map": + + struct string_map_node *node; + const char *key, *value; + + STRING_MAP_FOR_EACH_KEY_VALUE (key, value, node, &my_map) + printf ("%s=%s\n", key, value); + */ +#define STRING_MAP_FOR_EACH_NODE(NODE, MAP) \ + for ((NODE) = string_map_first (MAP); (NODE) != NULL; \ + (NODE) = string_map_next (MAP, NODE)) +#define STRING_MAP_FOR_EACH_NODE_SAFE(NODE, NEXT, MAP) \ + for ((NODE) = string_map_first (MAP); \ + ((NODE) != NULL \ + && ((NEXT) = string_map_next (MAP, NODE), 1)); \ + (NODE) = (NEXT)) +#define STRING_MAP_FOR_EACH_KEY(KEY, NODE, MAP) \ + for ((NODE) = string_map_first (MAP); \ + ((NODE) != NULL \ + && ((KEY) = string_map_node_get_key (NODE), 1)); \ + (NODE) = string_map_next (MAP, NODE)) +#define STRING_MAP_FOR_EACH_KEY_SAFE(KEY, NODE, NEXT, MAP) \ + for ((NODE) = string_map_first (MAP); \ + ((NODE) != NULL \ + && ((KEY) = string_map_node_get_key (NODE), 1) \ + && ((NEXT) = string_map_next (MAP, NODE), 1)); \ + (NODE) = (NEXT)) +#define STRING_MAP_FOR_EACH_VALUE(VALUE, NODE, MAP) \ + for ((NODE) = string_map_first (MAP); \ + ((NODE) != NULL \ + && ((VALUE) = (NODE)->value, 1)); \ + (NODE) = string_map_next (MAP, NODE)) +#define STRING_MAP_FOR_EACH_VALUE_SAFE(VALUE, NODE, NEXT, MAP) \ + for ((NODE) = string_map_first (MAP); \ + ((NODE) != NULL \ + && ((VALUE) = (NODE)->value, 1) \ + && ((NEXT) = string_map_next (MAP, NODE), 1)); \ + (NODE) = (NEXT)) +#define STRING_MAP_FOR_EACH_KEY_VALUE(KEY, VALUE, NODE, MAP) \ + for ((NODE) = string_map_first (MAP); \ + ((NODE) != NULL \ + && ((KEY) = string_map_node_get_key (NODE), 1) \ + && ((VALUE) = (NODE)->value, 1)); \ + (NODE) = string_map_next (MAP, NODE)) +#define STRING_MAP_FOR_EACH_KEY_VALUE_SAFE(KEY, VALUE, NODE, NEXT, MAP) \ + for ((NODE) = string_map_first (MAP); \ + ((NODE) != NULL \ + && ((KEY) = string_map_node_get_key (NODE), 1) \ + && ((VALUE) = (NODE)->value, 1) \ + && ((NEXT) = string_map_next (MAP, NODE), 1)); \ + (NODE) = (NEXT)) + +/* Returns the number of key-value pairs currently in MAP. */ +static inline size_t +string_map_count (const struct string_map *map) +{ + return hmap_count (&map->hmap); +} + +/* Returns true if MAP currently contains no key-value pairs, false + otherwise. */ +static inline bool +string_map_is_empty (const struct string_map *map) +{ + return hmap_is_empty (&map->hmap); +} + +/* Returns the first node in MAP, or a null pointer if MAP is empty. See the + hmap_first function for information about complexity (O(1) amortized) and + ordering (arbitrary). + + The STRING_MAP_FOR_EACH family of macros provide convenient ways to iterate + over all the nodes in a string map. */ +static inline struct string_map_node * +string_map_first (const struct string_map *map) +{ + return HMAP_FIRST (struct string_map_node, hmap_node, &map->hmap); +} + +/* Returns the next node in MAP following NODE, or a null pointer if NODE is + the last node in MAP. See the hmap_next function for information about + complexity (O(1) amortized) and ordering (arbitrary). + + The STRING_MAP_FOR_EACH family of macros provide convenient ways to iterate + over all the nodes in a string map. */ +static inline struct string_map_node * +string_map_next (const struct string_map *map, + const struct string_map_node *node) +{ + return HMAP_NEXT (node, struct string_map_node, hmap_node, &map->hmap); +} + +#endif /* libpspp/string-map.h */ diff --git a/src/libpspp/string-set.c b/src/libpspp/string-set.c new file mode 100644 index 00000000..3fd370db --- /dev/null +++ b/src/libpspp/string-set.c @@ -0,0 +1,261 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* If you add routines in this file, please add a corresponding test to + string-set-test.c. */ + +#include + +#include + +#include +#include + +#include + +#include "gl/xalloc.h" + +static struct string_set_node *string_set_find_node__ ( + const struct string_set *, const char *, unsigned int hash); +static void string_set_insert__ (struct string_set *, char *, + unsigned int hash); +static bool string_set_delete__ (struct string_set *, const char *, + unsigned int hash); + +/* Initializes SET as a new string set that is initially empty. */ +void +string_set_init (struct string_set *set) +{ + hmap_init (&set->hmap); +} + +/* Initializes SET as a new string set that initially contains the same strings + as OLD. */ +void +string_set_clone (struct string_set *set, const struct string_set *old) +{ + const struct string_set_node *node; + const char *s; + + string_set_init (set); + hmap_reserve (&set->hmap, string_set_count (old)); + STRING_SET_FOR_EACH (s, node, old) + string_set_insert__ (set, xstrdup (s), node->hmap_node.hash); +} + +/* Exchanges the contents of string sets A and B. */ +void +string_set_swap (struct string_set *a, struct string_set *b) +{ + hmap_swap (&a->hmap, &b->hmap); +} + +/* Frees SET and its nodes and strings. */ +void +string_set_destroy (struct string_set *set) +{ + if (set != NULL) + { + string_set_clear (set); + hmap_destroy (&set->hmap); + } +} + +/* Returns true if SET contains S, false otherwise. */ +bool +string_set_contains (const struct string_set *set, const char *s) +{ + return string_set_find_node (set, s) != NULL; +} + +/* Returns the node in SET that contains S, or a null pointer if SET does not + contain S. */ +struct string_set_node * +string_set_find_node (const struct string_set *set, const char *s) +{ + return string_set_find_node__ (set, s, hash_string (s, 0)); +} + +/* Inserts a copy of S into SET. Returns true if successful, false if SET + is unchanged because it already contained S. */ +bool +string_set_insert (struct string_set *set, const char *s) +{ + unsigned int hash = hash_string (s, 0); + if (!string_set_find_node__ (set, s, hash)) + { + string_set_insert__ (set, xstrdup (s), hash); + return true; + } + else + return false; +} + +/* Inserts S, which must be a malloc'd string, into SET, transferring ownership + of S to SET. Returns true if successful, false if SET is unchanged because + it already contained a copy of S. (In the latter case, S is freed.) */ +bool +string_set_insert_nocopy (struct string_set *set, char *s) +{ + unsigned int hash = hash_string (s, 0); + if (!string_set_find_node__ (set, s, hash)) + { + string_set_insert__ (set, s, hash); + return true; + } + else + { + free (s); + return false; + } +} + +/* Deletes S from SET. Returns true if successful, false if SET is unchanged + because it did not contain a copy of S. */ +bool +string_set_delete (struct string_set *set, const char *s) +{ + return string_set_delete__ (set, s, hash_string (s, 0)); +} + +/* Deletes NODE from SET, and frees NODE and its string. */ +void +string_set_delete_node (struct string_set *set, struct string_set_node *node) +{ + free (string_set_delete_nofree (set, node)); +} + +/* Deletes NODE from SET and frees NODE. Returns the string that NODE + contained, transferring ownership to the caller. */ +char * +string_set_delete_nofree (struct string_set *set, struct string_set_node *node) +{ + char *string = node->string; + hmap_delete (&set->hmap, &node->hmap_node); + free (node); + return string; +} + +/* Removes all nodes from SET. */ +void +string_set_clear (struct string_set *set) +{ + struct string_set_node *node, *next; + + HMAP_FOR_EACH_SAFE (node, next, struct string_set_node, hmap_node, + &set->hmap) + string_set_delete_node (set, node); +} + +/* Calculates A = union(A, B). + + If B may be modified, string_set_union_and_intersection() is + faster than this function. */ +void +string_set_union (struct string_set *a, const struct string_set *b) +{ + struct string_set_node *node; + HMAP_FOR_EACH (node, struct string_set_node, hmap_node, &b->hmap) + if (!string_set_find_node__ (a, node->string, node->hmap_node.hash)) + string_set_insert__ (a, xstrdup (node->string), node->hmap_node.hash); +} + +/* Calculates A = union(A, B) and B = intersect(A, B). + + If only the intersection is needed, string_set_intersect() is + faster. */ +void +string_set_union_and_intersection (struct string_set *a, struct string_set *b) +{ + struct string_set_node *node, *next; + + HMAP_FOR_EACH_SAFE (node, next, struct string_set_node, hmap_node, + &b->hmap) + if (!string_set_find_node__ (a, node->string, node->hmap_node.hash)) + { + hmap_delete (&b->hmap, &node->hmap_node); + hmap_insert (&a->hmap, &node->hmap_node, node->hmap_node.hash); + } +} + +/* Calculates A = intersect(A, B). */ +void +string_set_intersect (struct string_set *a, const struct string_set *b) +{ + struct string_set_node *node, *next; + + HMAP_FOR_EACH_SAFE (node, next, struct string_set_node, hmap_node, + &a->hmap) + if (!string_set_find_node__ (b, node->string, node->hmap_node.hash)) + string_set_delete_node (a, node); +} + +/* Removes from A all of the strings in B. */ +void +string_set_subtract (struct string_set *a, const struct string_set *b) +{ + struct string_set_node *node, *next; + + if (string_set_count (a) < string_set_count (b)) + { + HMAP_FOR_EACH_SAFE (node, next, struct string_set_node, hmap_node, + &a->hmap) + if (string_set_find_node__ (b, node->string, node->hmap_node.hash)) + string_set_delete_node (a, node); + } + else + { + HMAP_FOR_EACH (node, struct string_set_node, hmap_node, &b->hmap) + string_set_delete__ (a, node->string, node->hmap_node.hash); + } +} + +/* Internal functions. */ + +static struct string_set_node * +string_set_find_node__ (const struct string_set *set, const char *s, + unsigned int hash) +{ + struct string_set_node *node; + + HMAP_FOR_EACH_WITH_HASH (node, struct string_set_node, hmap_node, + hash, &set->hmap) + if (!strcmp (s, node->string)) + return node; + + return NULL; +} + +static void +string_set_insert__ (struct string_set *set, char *s, unsigned int hash) +{ + struct string_set_node *node = xmalloc (sizeof *node); + node->string = s; + hmap_insert (&set->hmap, &node->hmap_node, hash); +} + +static bool +string_set_delete__ (struct string_set *set, const char *s, unsigned int hash) +{ + struct string_set_node *node = string_set_find_node__ (set, s, hash); + if (node != NULL) + { + string_set_delete_node (set, node); + return true; + } + else + return false; +} diff --git a/src/libpspp/string-set.h b/src/libpspp/string-set.h new file mode 100644 index 00000000..a604e151 --- /dev/null +++ b/src/libpspp/string-set.h @@ -0,0 +1,148 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef LIBPSPP_STRING_SET_H +#define LIBPSPP_STRING_SET_H + +/* Set of unique strings. + + This is a convenient wrapper around a "struct hmap" for storing strings. */ + +#include +#include + +/* A node in the string set. */ +struct string_set_node + { + struct hmap_node hmap_node; + char *string; + }; + +/* Returns the string within NODE. The caller must not modify or free the + returned string. */ +static inline const char * +string_set_node_get_string (const struct string_set_node *node) +{ + return node->string; +} + +/* An unordered set of unique strings. */ +struct string_set + { + struct hmap hmap; + }; + +/* Suitable for use as the initializer for a string_set named SET. Typical + usage: + struct string_set set = STRING_SET_INITIALIZER (set); + STRING_SET_INITIALIZER is an alternative to calling string_set_init. */ +#define STRING_SET_INITIALIZER(SET) { HMAP_INITIALIZER ((SET).hmap) } + +void string_set_init (struct string_set *); +void string_set_clone (struct string_set *, const struct string_set *); +void string_set_swap (struct string_set *, struct string_set *); +void string_set_destroy (struct string_set *); + +static inline size_t string_set_count (const struct string_set *); +static inline bool string_set_is_empty (const struct string_set *); + +bool string_set_contains (const struct string_set *, const char *); +struct string_set_node *string_set_find_node (const struct string_set *, + const char *); + +bool string_set_insert (struct string_set *, const char *); +bool string_set_insert_nocopy (struct string_set *, char *); +bool string_set_delete (struct string_set *, const char *); +void string_set_delete_node (struct string_set *, struct string_set_node *); +char *string_set_delete_nofree (struct string_set *, struct string_set_node *); + +void string_set_clear (struct string_set *); +void string_set_union (struct string_set *, const struct string_set *); +void string_set_union_and_intersection (struct string_set *, + struct string_set *); +void string_set_intersect (struct string_set *, const struct string_set *); +void string_set_subtract (struct string_set *, const struct string_set *); + +static inline const struct string_set_node *string_set_first ( + const struct string_set *); +static inline const struct string_set_node *string_set_next ( + const struct string_set *, const struct string_set_node *); + +/* Macros for conveniently iterating through a string_set, e.g. to print all of + the strings in "my_set": + + struct string_set_node *node; + const char *string; + + STRING_SET_FOR_EACH (string, node, &my_set) + puts (string); + */ +#define STRING_SET_FOR_EACH(STRING, NODE, SET) \ + for ((NODE) = string_set_first (SET); \ + ((NODE) != NULL \ + ? ((STRING) = string_set_node_get_string (NODE), \ + 1) \ + : 0); \ + (NODE) = string_set_next (SET, NODE)) +#define STRING_SET_FOR_EACH_SAFE(STRING, NODE, NEXT, SET) \ + for ((NODE) = string_set_first (SET); \ + ((NODE) != NULL \ + ? ((STRING) = string_set_node_get_string (NODE), \ + (NEXT) = string_set_next (SET, NODE), \ + 1) \ + : 0); \ + (NODE) = (NEXT)) + +/* Returns the number of strings currently in SET. */ +static inline size_t +string_set_count (const struct string_set *set) +{ + return hmap_count (&set->hmap); +} + +/* Returns true if SET currently contains no strings, false otherwise. */ +static inline bool +string_set_is_empty (const struct string_set *set) +{ + return hmap_is_empty (&set->hmap); +} + +/* Returns the first node in SET, or a null pointer if SET is empty. See the + hmap_first function for information about complexity (O(1) amortized) and + ordering (arbitrary). + + The STRING_SET_FOR_EACH and STRING_SET_FOR_EACH_SAFE macros provide + convenient ways to iterate over all the nodes in a string set. */ +static inline const struct string_set_node * +string_set_first (const struct string_set *set) +{ + return HMAP_FIRST (struct string_set_node, hmap_node, &set->hmap); +} + +/* Returns the next node in SET following NODE, or a null pointer if NODE is + the last node in SET. See the hmap_next function for information about + complexity (O(1) amortized) and ordering (arbitrary). + + The STRING_SET_FOR_EACH and STRING_SET_FOR_EACH_SAFE macros provide + convenient ways to iterate over all the nodes in a string set. */ +static inline const struct string_set_node * +string_set_next (const struct string_set *set, + const struct string_set_node *node) +{ + return HMAP_NEXT (node, struct string_set_node, hmap_node, &set->hmap); +} + +#endif /* libpspp/string-set.h */ diff --git a/src/libpspp/taint.c b/src/libpspp/taint.c index 3a74587b..4c1cecb9 100644 --- a/src/libpspp/taint.c +++ b/src/libpspp/taint.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ #include #include +#include #include "xalloc.h" @@ -79,7 +80,7 @@ taint_create (void) struct taint * taint_clone (const struct taint *taint_) { - struct taint *taint = (struct taint *) taint_; + struct taint *taint = CONST_CAST (struct taint *, taint_); assert (taint->ref_cnt > 0); taint->ref_cnt++; @@ -139,8 +140,8 @@ taint_destroy (struct taint *taint) void taint_propagate (const struct taint *from_, const struct taint *to_) { - struct taint *from = (struct taint *) from_; - struct taint *to = (struct taint *) to_; + struct taint *from = CONST_CAST (struct taint *, from_); + struct taint *to = CONST_CAST (struct taint *, to_); if (from != to) { @@ -165,7 +166,7 @@ taint_is_tainted (const struct taint *taint) void taint_set_taint (const struct taint *taint_) { - struct taint *taint = (struct taint *) taint_; + struct taint *taint = CONST_CAST (struct taint *, taint_); if (!taint->tainted) recursively_set_taint (taint); } @@ -186,7 +187,7 @@ taint_has_tainted_successor (const struct taint *taint) void taint_reset_successor_taint (const struct taint *taint_) { - struct taint *taint = (struct taint *) taint_; + struct taint *taint = CONST_CAST (struct taint *, taint_); if (taint->tainted_successor) { diff --git a/src/libpspp/tmpfile.c b/src/libpspp/tmpfile.c index 0d309364..aff135d0 100644 --- a/src/libpspp/tmpfile.c +++ b/src/libpspp/tmpfile.c @@ -26,6 +26,7 @@ #include #include +#include #include "error.h" #include "xalloc.h" @@ -81,7 +82,7 @@ tmpfile_destroy (struct tmpfile *tf) static bool do_seek (const struct tmpfile *tf_, off_t offset) { - struct tmpfile *tf = (struct tmpfile *) tf_; + struct tmpfile *tf = CONST_CAST (struct tmpfile *, tf_); if (!tmpfile_error (tf)) { @@ -106,7 +107,7 @@ do_seek (const struct tmpfile *tf_, off_t offset) static bool do_read (const struct tmpfile *tf_, void *buffer, size_t bytes) { - struct tmpfile *tf = (struct tmpfile *) tf_; + struct tmpfile *tf = CONST_CAST (struct tmpfile *, tf_); assert (!tmpfile_error (tf)); if (bytes > 0 && fread (buffer, bytes, 1, tf->file) != 1) diff --git a/src/libpspp/tower.c b/src/libpspp/tower.c index e8d253d0..91579877 100644 --- a/src/libpspp/tower.c +++ b/src/libpspp/tower.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ #include #include +#include #include static struct tower_node *abt_to_tower_node (const struct abt_node *); @@ -184,7 +185,7 @@ tower_lookup (const struct tower *t_, unsigned long height, unsigned long *node_start) { - struct tower *t = (struct tower *) t_; + struct tower *t = CONST_CAST (struct tower *, t_); struct abt_node *p; assert (height < tower_height (t)); @@ -237,7 +238,7 @@ tower_lookup (const struct tower *t_, struct tower_node * tower_get (const struct tower *t_, unsigned long int index) { - struct tower *t = (struct tower *) t_; + struct tower *t = CONST_CAST (struct tower *, t_); struct abt_node *p; assert (index < tower_count (t)); diff --git a/src/libpspp/tower.h b/src/libpspp/tower.h index 246984a2..9be8231c 100644 --- a/src/libpspp/tower.h +++ b/src/libpspp/tower.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -51,12 +51,14 @@ #include #include +#include /* Returns the data structure corresponding to the given NODE, assuming that NODE is embedded as the given MEMBER name in data type STRUCT. */ -#define tower_data(NODE, STRUCT, MEMBER) \ - ((STRUCT *) ((char *) (NODE) - offsetof (STRUCT, MEMBER))) +#define tower_data(NODE, STRUCT, MEMBER) \ + (CHECK_POINTER_HAS_TYPE (NODE, struct tower_node *), \ + UP_CAST (NODE, STRUCT, MEMBER)) /* A node within a tower. */ struct tower_node diff --git a/src/math/box-whisker.c b/src/math/box-whisker.c index 288fc072..de4124ef 100644 --- a/src/math/box-whisker.c +++ b/src/math/box-whisker.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include "tukey-hinges.h" #include #include +#include #include #include #include @@ -30,8 +31,8 @@ static void destroy (struct statistic *s) { - struct order_stats *os = (struct order_stats *) s; - struct box_whisker *bw = (struct box_whisker *) s; + struct box_whisker *bw = UP_CAST (s, struct box_whisker, parent.parent); + struct order_stats *os = &bw->parent; struct ll *ll; for (ll = ll_head (&bw->outliers); ll != ll_null (&bw->outliers); ) @@ -53,7 +54,7 @@ static void acc (struct statistic *s, const struct ccase *cx, double c UNUSED, double cc UNUSED, double y) { - struct box_whisker *bw = (struct box_whisker *) s; + struct box_whisker *bw = UP_CAST (s, struct box_whisker, parent.parent); bool extreme; struct outlier *o; @@ -110,13 +111,13 @@ box_whisker_outliers (const struct box_whisker *bw) return &bw->outliers; } -struct statistic * +struct box_whisker * box_whisker_create (const struct tukey_hinges *th, const struct variable *id_var, size_t casenumber_idx) { struct box_whisker *w = xzalloc (sizeof (*w)); - struct order_stats *os = (struct order_stats *) w; - struct statistic *stat = (struct statistic *) w; + struct order_stats *os = &w->parent; + struct statistic *stat = &os->parent; os->n_k = 0; @@ -135,5 +136,5 @@ box_whisker_create (const struct tukey_hinges *th, ll_init (&w->outliers); - return stat; + return w; } diff --git a/src/math/box-whisker.h b/src/math/box-whisker.h index 5202b646..bef091e8 100644 --- a/src/math/box-whisker.h +++ b/src/math/box-whisker.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,7 +52,7 @@ struct box_whisker const struct variable *id_var; }; -struct statistic * box_whisker_create (const struct tukey_hinges *, +struct box_whisker * box_whisker_create (const struct tukey_hinges *, const struct variable *, size_t); void box_whisker_whiskers (const struct box_whisker *bw, double whiskers[2]); diff --git a/src/math/histogram.c b/src/math/histogram.c index 67079398..3c88c385 100644 --- a/src/math/histogram.c +++ b/src/math/histogram.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004, 2008 Free Software Foundation, Inc. + Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ #include #include +#include #include #include "chart-geometry.h" @@ -28,7 +29,8 @@ void histogram_add (struct histogram *h, double y, double c) { - ((struct statistic *)h)->accumulate ((struct statistic *) h, NULL, c, 0, y); + struct statistic *stat = &h->parent; + stat->accumulate (stat, NULL, c, 0, y); } @@ -36,7 +38,7 @@ histogram_add (struct histogram *h, double y, double c) static void acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc UNUSED, double y) { - struct histogram *hist = (struct histogram *) s; + struct histogram *hist = UP_CAST (s, struct histogram, parent); gsl_histogram_accumulate (hist->gsl_hist, y, c); } @@ -45,17 +47,17 @@ acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc UNU static void destroy (struct statistic *s) { - struct histogram *h = (struct histogram *) s; + struct histogram *h = UP_CAST (s, struct histogram, parent); gsl_histogram_free (h->gsl_hist); free (s); } -struct statistic * +struct histogram * histogram_create (int bins, double min, double max) { struct histogram *h = xmalloc (sizeof *h); - struct statistic *stat = (struct statistic *) h; + struct statistic *stat = &h->parent; double upper_limit, lower_limit; double bin_width = chart_rounded_tick ((max - min) / (double) bins); @@ -78,6 +80,6 @@ histogram_create (int bins, double min, double max) stat->accumulate = acc; stat->destroy = destroy; - return stat; + return h; } diff --git a/src/math/histogram.h b/src/math/histogram.h index b2b204ee..bc4a5ae6 100644 --- a/src/math/histogram.h +++ b/src/math/histogram.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,7 +30,7 @@ struct histogram gsl_histogram *gsl_hist; }; -struct statistic * histogram_create (int bins, double max, double min); +struct histogram * histogram_create (int bins, double max, double min); void histogram_add (struct histogram *h, double y, double c); diff --git a/src/math/levene.c b/src/math/levene.c index 7bd58210..f7e26999 100644 --- a/src/math/levene.c +++ b/src/math/levene.c @@ -246,9 +246,7 @@ levene2_precalc (struct levene_info *l) struct hsh_table *hash = group_proc_get (var)->group_hash; - for(g = (struct group_statistics *) hsh_first(hash,&hi); - g != 0 ; - g = (struct group_statistics *) hsh_next(hash,&hi) ) + for (g = hsh_first(hash,&hi); g != 0; g = hsh_next(hash, &hi)) { g->lz_mean = g->lz_total / g->n ; } @@ -308,9 +306,7 @@ levene2_postcalc (struct levene_info *l) struct group_proc *gp = group_proc_get (var); struct hsh_table *hash = gp->group_hash; - for(g = (struct group_statistics *) hsh_first(hash,&hi); - g != 0 ; - g = (struct group_statistics *) hsh_next(hash,&hi) ) + for (g = hsh_first(hash, &hi); g != 0; g = hsh_next(hash, &hi)) { lz_numerator += g->n * pow2(g->lz_mean - l->lz[v].grand_mean ); } diff --git a/src/math/np.c b/src/math/np.c index e61bf58e..b6318209 100644 --- a/src/math/np.c +++ b/src/math/np.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -32,8 +33,8 @@ static void destroy (struct statistic *stat) { - struct order_stats *os = (struct order_stats *) stat; - free (os); + struct np *np = UP_CAST (stat, struct np, parent.parent); + free (np); } @@ -42,7 +43,7 @@ acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc, double y) { struct ccase *cp; - struct np *np = (struct np *) s; + struct np *np = UP_CAST (s, struct np, parent.parent); double rank = np->prev_cc + (c + 1) / 2.0; double ns = gsl_cdf_ugaussian_Pinv (rank / ( np->n + 1 )); @@ -69,13 +70,13 @@ acc (struct statistic *s, const struct ccase *cx UNUSED, np->prev_cc = cc; } -struct order_stats * +struct np * np_create (const struct moments1 *m) { double variance; struct np *np = xzalloc (sizeof (*np)); - struct statistic *stat = (struct statistic *) np; - struct order_stats *os = (struct order_stats *) np; + struct order_stats *os = &np->parent; + struct statistic *stat = &os->parent; struct caseproto *proto; int i; @@ -98,5 +99,5 @@ np_create (const struct moments1 *m) stat->destroy = destroy; stat->accumulate = acc; - return os; + return np; } diff --git a/src/math/np.h b/src/math/np.h index 7db51f73..b5265bd4 100644 --- a/src/math/np.h +++ b/src/math/np.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -54,6 +54,6 @@ struct np }; -struct order_stats * np_create (const struct moments1 *); +struct np * np_create (const struct moments1 *); #endif diff --git a/src/math/order-stats.c b/src/math/order-stats.c index 1b6aa131..e550d2b2 100644 --- a/src/math/order-stats.c +++ b/src/math/order-stats.c @@ -90,7 +90,7 @@ update_k_values (const struct ccase *cx, double y_i, double c_i, double cc_i, { int k; struct order_stats *tos = os[j]; - struct statistic *stat = (struct statistic *) tos; + struct statistic *stat = &tos->parent; for (k = 0 ; k < tos->n_k; ++k) { struct k *myk = &tos->k[k]; diff --git a/src/math/percentiles.c b/src/math/percentiles.c index bf99de16..c76bb492 100644 --- a/src/math/percentiles.c +++ b/src/math/percentiles.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #define N_(msgid) msgid #include +#include #include #include #include @@ -44,7 +45,7 @@ const char *const ptile_alg_desc[] = { double percentile_calculate (const struct percentile *ptl, enum pc_alg alg) { - struct percentile *mutable = (struct percentile *) ptl; + struct percentile *mutable = CONST_CAST (struct percentile *, ptl); const struct order_stats *os = &ptl->parent; assert (os->cc == ptl->w); @@ -154,18 +155,19 @@ percentile_calculate (const struct percentile *ptl, enum pc_alg alg) static void destroy (struct statistic *stat) { - struct order_stats *os = (struct order_stats *) stat; + struct percentile *ptl = UP_CAST (stat, struct percentile, parent.parent); + struct order_stats *os = &ptl->parent; free (os->k); - free (os); + free (ptl); } -struct order_stats * +struct percentile * percentile_create (double p, double W) { struct percentile *ptl = xzalloc (sizeof (*ptl)); - struct order_stats *os = (struct order_stats *) ptl; - struct statistic *stat = (struct statistic *) ptl; + struct order_stats *os = &ptl->parent; + struct statistic *stat = &os->parent; assert (p >= 0); assert (p <= 1.0); @@ -186,6 +188,6 @@ percentile_create (double p, double W) stat->destroy = destroy; - return os; + return ptl; } diff --git a/src/math/percentiles.h b/src/math/percentiles.h index 0dd09820..ff46bea6 100644 --- a/src/math/percentiles.h +++ b/src/math/percentiles.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004, 2008 Free Software Foundation, Inc. + Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,7 +52,7 @@ struct percentile /* Create the Pth percentile. W is the total sum of weights in the data set */ -struct order_stats *percentile_create (double p, double W); +struct percentile *percentile_create (double p, double W); /* Return the value of the percentile */ double percentile_calculate (const struct percentile *ptl, enum pc_alg alg); diff --git a/src/math/trimmed-mean.c b/src/math/trimmed-mean.c index da3d4240..d1cc6b70 100644 --- a/src/math/trimmed-mean.c +++ b/src/math/trimmed-mean.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -27,8 +28,8 @@ static void acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc, double y) { - struct trimmed_mean *tm = (struct trimmed_mean *) s; - struct order_stats *os = (struct order_stats *) s; + struct trimmed_mean *tm = UP_CAST (s, struct trimmed_mean, parent.parent); + struct order_stats *os = &tm->parent; if ( cc > os->k[0].tc && cc < os->k[1].tc) tm->sum += c * y; @@ -40,17 +41,18 @@ acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc, do static void destroy (struct statistic *s) { - struct order_stats *os = (struct order_stats *) s; + struct trimmed_mean *tm = UP_CAST (s, struct trimmed_mean, parent.parent); + struct order_stats *os = &tm->parent; free (os->k); - free (s); + free (tm); } -struct statistic * +struct trimmed_mean * trimmed_mean_create (double W, double tail) { struct trimmed_mean *tm = xzalloc (sizeof (*tm)); - struct order_stats *os = (struct order_stats *) tm; - struct statistic *stat = (struct statistic *) tm; + struct order_stats *os = &tm->parent; + struct statistic *stat = &os->parent; os->n_k = 2; os->k = xcalloc (sizeof (*os->k), 2); @@ -68,7 +70,7 @@ trimmed_mean_create (double W, double tail) tm->w = W; tm->tail = tail; - return stat; + return tm; } diff --git a/src/math/trimmed-mean.h b/src/math/trimmed-mean.h index 9339cab9..c667b1be 100644 --- a/src/math/trimmed-mean.h +++ b/src/math/trimmed-mean.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,7 +36,7 @@ struct trimmed_mean double tail; }; -struct statistic * trimmed_mean_create (double W, double c_min); +struct trimmed_mean * trimmed_mean_create (double W, double c_min); double trimmed_mean_calculate (const struct trimmed_mean *); #endif diff --git a/src/math/tukey-hinges.c b/src/math/tukey-hinges.c index 95a79c1d..22ab4521 100644 --- a/src/math/tukey-hinges.c +++ b/src/math/tukey-hinges.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include #include +#include #include void @@ -59,19 +60,20 @@ tukey_hinges_calculate (const struct tukey_hinges *th, double hinge[3]) static void destroy (struct statistic *s) { - struct order_stats *os = (struct order_stats *) s; + struct tukey_hinges *th = UP_CAST (s, struct tukey_hinges, parent.parent); + struct order_stats *os = &th->parent; free (os->k); free (s); }; -struct statistic * +struct tukey_hinges * tukey_hinges_create (double W, double c_min) { double d; struct tukey_hinges *th = xzalloc (sizeof (*th)); - struct order_stats *os = (struct order_stats *) th; - struct statistic *stat = (struct statistic *) th; + struct order_stats *os = &th->parent; + struct statistic *stat = &os->parent; assert (c_min >= 0); @@ -97,5 +99,5 @@ tukey_hinges_create (double W, double c_min) stat->destroy = destroy; - return stat; + return th; } diff --git a/src/math/tukey-hinges.h b/src/math/tukey-hinges.h index d87691f8..4b509da1 100644 --- a/src/math/tukey-hinges.h +++ b/src/math/tukey-hinges.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ struct tukey_hinges struct order_stats parent; }; -struct statistic * tukey_hinges_create (double W, double c_min); +struct tukey_hinges * tukey_hinges_create (double W, double c_min); void tukey_hinges_calculate (const struct tukey_hinges *h, double hinge[3]); diff --git a/src/output/afm.c b/src/output/afm.c deleted file mode 100644 index 480aa158..00000000 --- a/src/output/afm.c +++ /dev/null @@ -1,1156 +0,0 @@ -/* PSPP - a program for statistical analysis. - Copyright (C) 2006 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include -#include "afm.h" -#include "c-ctype.h" -#include "c-strtod.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "error.h" -#include "minmax.h" -#include -#include -#include - -#include "gettext.h" -#define _(msgid) gettext (msgid) - -/* A kern pair entry. */ -struct afm_kern_pair - { - struct afm_character *successor; /* Second character. */ - int adjust; /* Adjustment. */ - }; - -/* A ligature. */ -struct afm_ligature - { - struct afm_character *successor; /* Second character. */ - struct afm_character *ligature; /* Resulting ligature. */ - }; - -/* How to map between byte strings and character values. */ -enum mapping_scheme - { - MAP_UNKNOWN, /* Not yet determined. */ - MAP_ONE_BYTE, /* 8-bit coding. */ - MAP_TWO_BYTE, /* 16-bit coding. */ - MAP_ESCAPE, /* 8-bit coding with escape to change fonts. */ - MAP_DOUBLE_ESCAPE, /* 8-bit coding with multiple escapes. */ - MAP_SHIFT /* 8-bit coding with 2 fonts that toggle. */ - }; - -/* AFM file data. */ -struct afm - { - struct pool *pool; /* Containing pool. */ - char *findfont_name; /* Name for PostScript /findfont operator. */ - int ascent; /* Height above the baseline (non-negative). */ - int descent; /* Depth below the baseline (non-negative). */ - - /* Encoding characters into strings. */ - enum mapping_scheme mapping; /* Basic mapping scheme. */ - char escape_char; /* MAP_ESCAPE only: escape character to use. */ - char shift_out; /* MAP_SHIFT only: selects font 0. */ - char shift_in; /* MAP_SHIFT only: selects font 1. */ - - /* Characters. */ - struct afm_character *undefined_codes[256]; - struct afm_character **codes[256]; - struct afm_character **chars; - size_t char_cnt; - }; - -/* AFM file parser. */ -struct parser - { - struct pool *pool; /* Containing pool. */ - struct afm *afm; /* AFM being parsed. */ - FILE *file; /* File being parsed. */ - const char *file_name; /* Name of file being parsed. */ - int line_number; /* Current line number in file. */ - jmp_buf bail_out; /* longjmp() target for error handling. */ - - size_t char_allocated; - int max_code; - }; - -static struct afm *create_afm (void); -static struct afm_character *create_character (struct afm *); - -static void afm_error (struct parser *, const char *, ...) - PRINTF_FORMAT (2, 3) - NO_RETURN; - -static void parse_afm (struct parser *); -static void skip_section (struct parser *, const char *end_key); -static bool parse_set_specific (struct parser *, const char *end_key); -static void parse_direction (struct parser *); -static void parse_char_metrics (struct parser *); -static void parse_kern_pairs (struct parser *); -static void add_kern_pair (struct parser *p, - struct afm_character *, struct afm_character *, - int adjust); - -static int skip_spaces (struct parser *); -static char *parse_key (struct parser *); -static void skip_line (struct parser *); -static void force_eol (struct parser *); -static bool get_integer (struct parser *, int *); -static int force_get_integer (struct parser *); -static bool get_number (struct parser *, int *); -static int force_get_number (struct parser *); -static bool get_hex_code (struct parser *, int *); -static int force_get_hex_code (struct parser *); -static bool get_word (struct parser *, char **); -static char *force_get_word (struct parser *); -static bool get_string (struct parser *, char **); -static char *force_get_string (struct parser *); - -static struct afm_character *get_char_by_name (struct parser *, const char *); -static struct afm_character *get_char_by_code (const struct afm *, int code); - -/* Reads FILE_NAME as an AFM file and returns the metrics data. - Returns a null pointer if the file cannot be parsed. */ -struct afm * -afm_open (const char *file_name) -{ - struct afm *volatile afm; - struct parser *parser; - - parser = pool_create_container (struct parser, pool); - afm = parser->afm = create_afm (); - parser->file = pool_fopen (parser->pool, file_name, "r"); - parser->file_name = file_name; - parser->line_number = 0; - if (parser->file == NULL) - { - error (0, errno, _("opening font metrics file \"%s\""), file_name); - goto error; - } - - if (setjmp (parser->bail_out)) - goto error; - - parse_afm (parser); - pool_destroy (parser->pool); - return afm; - - error: - pool_destroy (parser->pool); - pool_destroy (afm->pool); - return create_afm (); -} - -/* Creates and returns an empty set of metrics. */ -static struct afm * -create_afm (void) -{ - struct afm *afm; - struct afm_character *def_char; - size_t i; - - afm = pool_create_container (struct afm, pool); - afm->findfont_name = NULL; - afm->ascent = 0; - afm->descent = 0; - afm->mapping = MAP_UNKNOWN; - afm->escape_char = 255; - afm->shift_out = 14; - afm->shift_in = 15; - def_char = create_character (afm); - for (i = 0; i < 256; i++) - afm->undefined_codes[i] = def_char; - for (i = 0; i < 256; i++) - afm->codes[i] = afm->undefined_codes; - afm->chars = NULL; - afm->char_cnt = 0; - - return afm; -} - -/* Creates and returns an initialized character within AFM. */ -static struct afm_character * -create_character (struct afm *afm) -{ - struct afm_character *c = pool_alloc (afm->pool, sizeof *c); - c->code = ' '; - c->name = NULL; - c->width = 12000; - c->ascent = 0; - c->descent = 0; - c->kern_pairs = NULL; - c->kern_pair_cnt = 0; - c->ligatures = NULL; - c->ligature_cnt = 0; - return c; -} - -/* Reports the given MESSAGE at the current line in parser P - and bails out with longjmp(). */ -static void -afm_error (struct parser *p, const char *message, ...) -{ - va_list args; - char *msg; - - va_start (args, message); - msg = xasprintf (message, args); - va_end (args); - - error_at_line (0, 0, p->file_name, p->line_number, "%s", msg); - free (msg); - - longjmp (p->bail_out, 1); -} - -/* Parses an AFM file with parser P. */ -static void -parse_afm (struct parser *p) -{ - char *key; - - p->char_allocated = 0; - p->max_code = 0; - - key = force_get_word (p); - if (strcmp (key, "StartFontMetrics")) - afm_error (p, _("first line must be StartFontMetrics")); - skip_line (p); - - do - { - key = parse_key (p); - if (!strcmp (key, "FontName")) - p->afm->findfont_name = pool_strdup (p->afm->pool, - force_get_string (p)); - else if (!strcmp (key, "Ascender")) - p->afm->ascent = force_get_integer (p); - else if (!strcmp (key, "Descender")) - p->afm->descent = force_get_integer (p); - else if (!strcmp (key, "MappingScheme")) - { - int scheme = force_get_integer (p); - if (scheme == 4) - p->afm->mapping = MAP_ONE_BYTE; - else if (scheme == 2 || scheme == 5 || scheme == 6) - p->afm->mapping = MAP_TWO_BYTE; - else if (scheme == 3) - p->afm->mapping = MAP_ESCAPE; - else if (scheme == 7) - p->afm->mapping = MAP_DOUBLE_ESCAPE; - else if (scheme == 8) - p->afm->mapping = MAP_SHIFT; - else - afm_error (p, _("unsupported MappingScheme %d"), scheme); - } - else if (!strcmp (key, "EscChar")) - p->afm->escape_char = force_get_integer (p); - else if (!strcmp (key, "StartDirection")) - parse_direction (p); - else if (!strcmp (key, "StartCharMetrics")) - parse_char_metrics (p); - else if (!strcmp (key, "StartKernPairs") - || !strcmp (key, "StartKernPairs0")) - parse_kern_pairs (p); - else if (!strcmp (key, "StartTrackKern")) - skip_section (p, "EndTrackKern"); - else if (!strcmp (key, "StartComposites")) - skip_section (p, "EndComposites"); - else - skip_line (p); - } - while (strcmp (key, "EndFontMetrics")); - - if (p->afm->findfont_name == NULL) - afm_error (p, _("required FontName is missing")); - if (p->afm->mapping == MAP_UNKNOWN) - { - /* There seem to be a number of fonts out there that use a - 2-byte encoding but don't announce it with - MappingScheme. */ - p->afm->mapping = p->max_code > 255 ? MAP_TWO_BYTE : MAP_ONE_BYTE; - } -} - -/* Reads lines from parser P until one starts with END_KEY. */ -static void -skip_section (struct parser *p, const char *end_key) -{ - const char *key; - skip_line (p); - do - { - key = parse_key (p); - skip_line (p); - } - while (strcmp (key, end_key)); -} - -/* Attempts to read an integer from parser P. - If one is found, and it is nonzero, skips lines until END_KEY - is encountered and returns false. - Otherwise, skips the rest of the line and returns true. - (This is useful because AFM files can have multiple sets of - metrics. Set 0 is for normal text, other sets are for - vertical text, etc. We only care about set 0.) */ -static bool -parse_set_specific (struct parser *p, const char *end_key) -{ - int set; - - if (get_integer (p, &set) && set != 0) - { - skip_section (p, end_key); - return false; - } - else - { - force_eol (p); - return true; - } -} - -/* Parses a StartDirection...EndDirection section in parser P. */ -static void -parse_direction (struct parser *p) -{ - const char *key; - - if (!parse_set_specific (p, "EndDirection")) - return; - - do - { - key = parse_key (p); - if (!strcmp (key, "CharWidth")) - p->afm->codes[0][0]->width = force_get_integer (p); - skip_line (p); - } - while (strcmp (key, "EndDirection")); -} - -/* Parses a StartCharMetrics...EndCharMetrics section in parser - P. */ -static void -parse_char_metrics (struct parser *p) -{ - struct parsing_ligature - { - struct afm_character *first; - char *successor; - char *ligature; - }; - - struct parsing_ligature *ligatures = NULL; - size_t ligature_cnt = 0; - size_t ligature_allocated = 0; - - size_t i; - - skip_line (p); - - for (;;) - { - char *key; - struct afm_character *c; - - key = parse_key (p); - if (!strcmp (key, "EndCharMetrics")) - break; - - if (p->afm->char_cnt == p->char_allocated) - p->afm->chars = pool_2nrealloc (p->afm->pool, p->afm->chars, - &p->char_allocated, - sizeof *p->afm->chars); - c = create_character (p->afm); - - if (!strcmp (key, "C")) - c->code = force_get_integer (p); - else if (!strcmp (key, "CH")) - c->code = force_get_hex_code (p); - else - afm_error (p, _("CharMetrics line must start with C or CH")); - if (c->code < 0 || c->code > 65535) - c->code = -1; - - if (c->code > p->max_code) - p->max_code = c->code; - - p->afm->chars[p->afm->char_cnt++] = c; - if (c->code != -1) - p->afm->codes[c->code >> 8][c->code & 0xff] = c; - - key = force_get_word (p); - while (!strcmp (key, ";")) - { - if (!get_word (p, &key)) - break; - - if (!strcmp (key, "N")) - c->name = force_get_word (p); - else if (!strcmp (key, "WX") || !strcmp (key, "W0X")) - c->width = force_get_number (p); - else if (!strcmp (key, "W") || !strcmp (key, "W0")) - { - c->width = force_get_number (p); - force_get_number (p); - } - else if (!strcmp (key, "B")) - { - int llx, lly, urx, ury; - llx = force_get_number (p); - lly = force_get_number (p); - urx = force_get_number (p); - ury = force_get_number (p); - c->ascent = MAX (0, ury); - c->descent = MAX (0, -lly); - } - else if (!strcmp (key, "L")) - { - struct parsing_ligature *ligature; - if (ligature_cnt == ligature_allocated) - ligatures = pool_2nrealloc (p->pool, ligatures, - &ligature_allocated, - sizeof *ligatures); - ligature = &ligatures[ligature_cnt++]; - ligature->first = c; - ligature->successor = force_get_word (p); - ligature->ligature = force_get_word (p); - } - else - { - while (strcmp (key, ";")) - key = force_get_word (p); - continue; - } - if (!get_word (p, &key)) - break; - } - } - skip_line (p); - - for (i = 0; i < ligature_cnt; i++) - { - struct parsing_ligature *src = &ligatures[i]; - struct afm_ligature *dst; - src->first->ligatures = pool_nrealloc (p->afm->pool, - src->first->ligatures, - src->first->ligature_cnt + 1, - sizeof *src->first->ligatures); - dst = &src->first->ligatures[src->first->ligature_cnt++]; - dst->successor = get_char_by_name (p, src->successor); - dst->ligature = get_char_by_name (p, src->ligature); - } -} - -/* Parses a StartKernPairs...EndKernPairs section in parser P. */ -static void -parse_kern_pairs (struct parser *p) -{ - char *key; - - skip_line (p); - - do - { - struct afm_character *c1, *c2; - int adjust; - - key = parse_key (p); - if (!strcmp (key, "KP") || !strcmp (key, "KPX")) - { - c1 = get_char_by_name (p, force_get_word (p)); - c2 = get_char_by_name (p, force_get_word (p)); - adjust = force_get_number (p); - if (!strcmp (key, "KP")) - force_get_number (p); - add_kern_pair (p, c1, c2, adjust); - } - else if (!strcmp (key, "KPH")) - { - c1 = get_char_by_code (p->afm, force_get_hex_code (p)); - c2 = get_char_by_code (p->afm, force_get_hex_code (p)); - adjust = force_get_number (p); - force_get_number (p); - add_kern_pair (p, c1, c2, adjust); - } - else - skip_line (p); - } - while (strcmp (key, "EndKernPairs")); -} - -/* Adds a kern pair that adjusts (FIRST, SECOND) by ADJUST units - to the metrics within parser P. */ -static void -add_kern_pair (struct parser *p, struct afm_character *first, - struct afm_character *second, int adjust) -{ - struct afm_kern_pair *kp; - - first->kern_pairs = pool_nrealloc (p->afm->pool, first->kern_pairs, - first->kern_pair_cnt + 1, - sizeof *first->kern_pairs); - kp = &first->kern_pairs[first->kern_pair_cnt++]; - kp->successor = second; - kp->adjust = adjust; -} - -/* Returns the character with the given NAME with the metrics for - parser P. Reports an error if no character has the given - name. */ -static struct afm_character * -get_char_by_name (struct parser *p, const char *name) -{ - size_t i; - - for (i = 0; i < p->afm->char_cnt; i++) - { - struct afm_character *c = p->afm->chars[i]; - if (c->name != NULL && !strcmp (c->name, name)) - return c; - } - afm_error (p, _("reference to unknown character \"%s\""), name); -} - -/* Returns the character with the given CODE within AFM. - Returns a default character if the font doesn't have a - character with that code. */ -static struct afm_character * -get_char_by_code (const struct afm *afm, int code_) -{ - uint16_t code = code_; - return afm->codes[code >> 8][code & 0xff]; -} - -/* Skips white space, except for new-lines, within parser P. */ -static int -skip_spaces (struct parser *p) -{ - int c; - while (isspace (c = getc (p->file)) && c != '\n') - continue; - ungetc (c, p->file); - return c; -} - -/* Parses a word at the beginning of a line. - Skips comments. - Reports an error if not at the beginning of a line. */ -static char * -parse_key (struct parser *p) -{ - force_eol (p); - for (;;) - { - char *key; - - do - { - p->line_number++; - getc (p->file); - } - while (skip_spaces (p) == '\n'); - - key = force_get_word (p); - if (strcmp (key, "Comment")) - return key; - - skip_line (p); - } -} - -/* Skips to the next line within parser P. */ -static void -skip_line (struct parser *p) -{ - for (;;) - { - int c = getc (p->file); - if (c == EOF) - afm_error (p, _("expected end of file")); - if (c == '\n') - break; - } - ungetc ('\n', p->file); -} - -/* Ensures that parser P is at the end of a line. */ -static void -force_eol (struct parser *p) -{ - if (skip_spaces (p) != '\n') - afm_error (p, _("syntax error expecting end of line")); -} - -/* Tries to read an integer into *INTEGER at the current position - in parser P. - Returns success. */ -static bool -get_integer (struct parser *p, int *integer) -{ - int c = skip_spaces (p); - if (isdigit (c) || c == '-') - { - char *tail; - long tmp; - - errno = 0; - tmp = strtol (force_get_word (p), &tail, 10); - if (errno == ERANGE || tmp < INT_MIN || tmp > INT_MAX) - afm_error (p, _("number out of valid range")); - if (*tail != '\0') - afm_error (p, _("invalid numeric syntax")); - *integer = tmp; - - return true; - } - else - return false; -} - -/* Returns an integer read from the current position in P. - Reports an error if unsuccessful. */ -static int -force_get_integer (struct parser *p) -{ - int integer; - if (!get_integer (p, &integer)) - afm_error (p, _("syntax error expecting integer")); - return integer; -} - -/* Tries to read a floating-point number at the current position - in parser P. Stores the number's integer part into *INTEGER. - Returns success. */ -static bool -get_number (struct parser *p, int *integer) -{ - int c = skip_spaces (p); - if (c == '-' || c == '.' || isdigit (c)) - { - char *tail; - double number; - - errno = 0; - number = c_strtod (force_get_word (p), &tail); - if (errno == ERANGE || number < INT_MIN || number > INT_MAX) - afm_error (p, _("number out of valid range")); - if (*tail != '\0') - afm_error (p, _("invalid numeric syntax")); - *integer = number; - - return true; - } - else - return false; -} - -/* Returns the integer part of a floating-point number read from - the current position in P. - Reports an error if unsuccessful. */ -static int -force_get_number (struct parser *p) -{ - int integer; - if (!get_number (p, &integer)) - afm_error (p, _("syntax error expecting number")); - return integer; -} - -/* Tries to read an integer expressed in hexadecimal into - *INTEGER from P. - Returns success. */ -static bool -get_hex_code (struct parser *p, int *integer) -{ - if (skip_spaces (p) == '<') - { - if (fscanf (p->file, "<%x", integer) != 1 || getc (p->file) != '>') - afm_error (p, _("syntax error in hex constant")); - return true; - } - else - return false; -} - -/* Reads an integer expressed in hexadecimal and returns its - value. - Reports an error if unsuccessful. */ -static int -force_get_hex_code (struct parser *p) -{ - int integer; - if (!get_hex_code (p, &integer)) - afm_error (p, _("syntax error expecting hex constant")); - return integer; -} - -/* Tries to read a word from P into *WORD. - The word is allocated in P's pool. - Returns success. */ -static bool -get_word (struct parser *p, char **word) -{ - if (skip_spaces (p) != '\n') - { - struct string s; - int c; - - ds_init_empty (&s); - while (!isspace (c = getc (p->file)) && c != EOF) - ds_put_char (&s, c); - ungetc (c, p->file); - *word = ds_cstr (&s); - pool_register (p->pool, free, *word); - return true; - } - else - { - *word = NULL; - return false; - } -} - -/* Reads a word from P and returns it. - The word is allocated in P's pool. - Reports an error if unsuccessful. */ -static char * -force_get_word (struct parser *p) -{ - char *word; - if (!get_word (p, &word)) - afm_error (p, _("unexpected end of line")); - return word; -} - -/* Reads a string, consisting of the remainder of the current - line, from P, and stores it in *STRING. - Leading and trailing spaces are removed. - The word is allocated in P's pool. - Returns true if a non-empty string was successfully read, - false otherwise. */ -static bool -get_string (struct parser *p, char **string) -{ - struct string s = DS_EMPTY_INITIALIZER; - - skip_spaces (p); - for (;;) - { - int c = getc (p->file); - if (c == EOF || c == '\n') - break; - ds_put_char (&s, c); - } - ungetc ('\n', p->file); - ds_rtrim (&s, ss_cstr (CC_SPACES)); - - if (!ds_is_empty (&s)) - { - *string = ds_cstr (&s); - pool_register (p->pool, free, *string); - return true; - } - else - { - *string = NULL; - ds_destroy (&s); - return false; - } -} - -/* Reads a string, consisting of the remainder of the current - line, from P, and returns it. - Leading and trailing spaces are removed. - The word is allocated in P's pool. - Reports an error if the string is empty. */ -static char * -force_get_string (struct parser *p) -{ - char *string; - if (!get_string (p, &string)) - afm_error (p, _("unexpected end of line expecting string")); - return string; -} - -/* Closes AFM and frees its storage. */ -void -afm_close (struct afm *afm) -{ - if (afm != NULL) - pool_destroy (afm->pool); -} - -/* Returns the string that must be passed to the PostScript - "findfont" operator to obtain AFM's font. */ -const char * -afm_get_findfont_name (const struct afm *afm) -{ - return afm->findfont_name; -} - -/* Returns the ascent for AFM, that is, the font's height above - the baseline, in units of 1/1000 of the nominal font size. */ -int -afm_get_ascent (const struct afm *afm) -{ - return afm->ascent; -} - -/* Returns the descent for AFM, that is, the font's depth below - the baseline, in units of 1/1000 of the nominal font size. */ -int -afm_get_descent (const struct afm *afm) -{ - return afm->descent; -} - -/* Returns the character numbered CODE within AFM, - or a default character if the font has none. */ -const struct afm_character * -afm_get_character (const struct afm *afm, int code) -{ - return get_char_by_code (afm, code); -} - -/* Returns the ligature formed when FIRST is followed by SECOND, - or a null pointer if there is no such ligature. */ -const struct afm_character * -afm_get_ligature (const struct afm_character *first, - const struct afm_character *second) -{ - size_t i; - - for (i = 0; i < first->ligature_cnt; i++) - if (first->ligatures[i].successor == second) - return first->ligatures[i].ligature; - return NULL; -} - -/* Returns the pair kerning x-adjustment when FIRST is followed - by SECOND, or 0 if no pair kerning should be done for the - given pair of characters. */ -int -afm_get_kern_adjustment (const struct afm_character *first, - const struct afm_character *second) -{ - size_t i; - - for (i = 0; i < first->kern_pair_cnt; i++) - if (first->kern_pairs[i].successor == second) - return first->kern_pairs[i].adjust; - return 0; -} - -/* Encodes the N characters in S as a PostScript string in OUT, - using a single-byte encoding. - Returns the number of characters remaining after all those - that could be successfully encoded were. */ -static size_t -encode_one_byte (const struct afm_character **s, size_t n, - struct string *out) -{ - ds_put_char (out, '('); - for (; n > 0; s++, n--) - { - uint8_t code = (*s)->code; - if (code != (*s)->code) - break; - - if (code == '(' || code == ')' || code == '\\') - ds_put_format (out, "\\%c", code); - else if (!c_isprint (code)) - ds_put_format (out, "\\%03o", code); - else - ds_put_char (out, code); - } - ds_put_char (out, ')'); - return n; -} - -/* State of binary encoder for PostScript. */ -struct binary_encoder - { - struct string *out; /* Output string. */ - uint32_t b; /* Accumulated bytes for base-85 encoding. */ - size_t n; /* Number of bytes in b (0...3). */ - }; - -/* Initializes encoder E for output to OUT. */ -static void -binary_init (struct binary_encoder *e, struct string *out) -{ - e->out = out; - e->b = e->n = 0; -} - -/* Returns the character that represents VALUE in ASCII85 - encoding. */ -static int -value_to_ascii85 (int value) -{ - assert (value >= 0 && value < 85); -#if C_CTYPE_ASCII - return value + 33; -#else - return ("!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK" - "LMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu")[value]; -#endif -} - -/* Appends the first N characters of the ASCII85 representation - of B to string OUT. */ -static void -append_ascii85_block (unsigned b, size_t n, struct string *out) -{ - char c[5]; - int i; - - for (i = 4; i >= 0; i--) - { - c[i] = value_to_ascii85 (b % 85); - b /= 85; - } - ds_put_substring (out, ss_buffer (c, n)); -} - -/* Encodes BYTE with encoder E. */ -static void -binary_put (struct binary_encoder *e, uint8_t byte) -{ - e->b = (e->b << 8) | byte; - e->n++; - if (e->n % 4 == 0) - { - if (e->n == 4) - ds_put_cstr (e->out, "<~"); - - if (e->b != 0) - append_ascii85_block (e->b, 5, e->out); - else - ds_put_char (e->out, 'z'); - } -} - -/* Finishes up encoding with E. */ -static void -binary_finish (struct binary_encoder *e) -{ - if (e->n >= 4) - { - /* We output at least one complete ASCII85 block. - Finish up. */ - size_t n = e->n % 4; - if (n > 0) - append_ascii85_block (e->b << 8 * (4 - n), n + 1, e->out); - ds_put_cstr (e->out, "~>"); - } - else if (e->n > 0) - { - /* It's cheaper (or at least the same cost) to encode this - string in hexadecimal. */ - uint32_t b; - size_t i; - - ds_put_cstr (e->out, "<"); - b = e->b << 8 * (4 - e->n); - for (i = 0; i < e->n; i++) - { - ds_put_format (e->out, "%02x", b >> 24); - b <<= 8; - } - ds_put_cstr (e->out, ">"); - } - else - { - /* Empty string. */ - ds_put_cstr (e->out, "()"); - } -} - -/* Encodes the N characters in S into encoder E, - using a two-byte encoding. - Returns the number of characters remaining after all those - that could be successfully encoded were. */ -static size_t -encode_two_byte (const struct afm_character **s, size_t n, - struct binary_encoder *e) -{ - for (; n > 0; s++, n--) - { - uint16_t code = (*s)->code; - if (code != (*s)->code) - break; - - binary_put (e, code >> 8); - binary_put (e, code); - } - return n; -} - -/* Encodes the N characters in S into encoder E, - using an escape-based encoding with ESCAPE_CHAR as escape. - Returns the number of characters remaining after all those - that could be successfully encoded were. */ -static size_t -encode_escape (const struct afm_character **s, size_t n, - unsigned char escape_char, - struct binary_encoder *e) -{ - uint8_t cur_font = 0; - - for (; n > 0; s++, n--) - { - uint16_t code = (*s)->code; - uint8_t font_num = code >> 8; - uint8_t char_num = code & 0xff; - if (code != (*s)->code) - break; - - if (font_num != cur_font) - { - if (font_num == escape_char) - break; - binary_put (e, escape_char); - binary_put (e, font_num); - cur_font = font_num; - } - binary_put (e, char_num); - } - return n; -} - -/* Encodes the N characters in S into encoder E, - using an double escape-based encoding with ESCAPE_CHAR as - escape. - Returns the number of characters remaining after all those - that could be successfully encoded were. */ -static size_t -encode_double_escape (const struct afm_character **s, size_t n, - unsigned char escape_char, - struct binary_encoder *e) -{ - unsigned cur_font = 0; - - for (; n > 0; s++, n--) - { - unsigned font_num = (*s)->code >> 8; - uint8_t char_num = (*s)->code & 0xff; - if ((*s)->code & ~0x1ffff) - break; - - if (font_num != cur_font) - { - if (font_num == (escape_char & 0xff)) - break; - if (font_num >= 256) - binary_put (e, escape_char); - binary_put (e, escape_char); - binary_put (e, font_num & 0xff); - cur_font = font_num; - } - binary_put (e, char_num); - } - return n; -} - -/* Encodes the N characters in S into encoder E, - using a shift-based encoding with SHIFT_IN and SHIFT_OUT as - shift characters. - Returns the number of characters remaining after all those - that could be successfully encoded were. */ -static size_t -encode_shift (const struct afm_character **s, size_t n, - unsigned char shift_in, unsigned char shift_out, - struct binary_encoder *e) -{ - unsigned cur_font = 0; - - for (; n > 0; s++, n--) - { - int font_num = ((*s)->code & 0x100) != 0; - uint8_t char_num = (*s)->code & 0xff; - if ((*s)->code & ~0x1ff) - break; - - if (font_num != cur_font) - { - binary_put (e, font_num ? shift_out : shift_in); - cur_font = font_num; - } - binary_put (e, char_num); - } - return n; -} - -/* Encodes the N characters in S into a PostScript string in OUT, - according to AFM's character encoding. - Returns the number of characters successfully encoded, - which may be less than N if an unencodable character was - encountered. */ -size_t -afm_encode_string (const struct afm *afm, - const struct afm_character **s, size_t n, - struct string *out) -{ - size_t initial_length = ds_length (out); - size_t chars_left; - - if (afm->mapping == MAP_ONE_BYTE) - chars_left = encode_one_byte (s, n, out); - else - { - struct binary_encoder e; - - binary_init (&e, out); - switch (afm->mapping) - { - case MAP_TWO_BYTE: - chars_left = encode_two_byte (s, n, &e); - break; - - case MAP_ESCAPE: - chars_left = encode_escape (s, n, afm->escape_char, &e); - break; - - case MAP_DOUBLE_ESCAPE: - chars_left = encode_double_escape (s, n, afm->escape_char, &e); - break; - - case MAP_SHIFT: - chars_left = encode_shift (s, n, afm->shift_in, afm->shift_out, &e); - break; - - default: - NOT_REACHED (); - } - binary_finish (&e); - } - - if (chars_left == n) - ds_truncate (out, initial_length); - return n - chars_left; -} diff --git a/src/output/afm.h b/src/output/afm.h deleted file mode 100644 index 6525af6b..00000000 --- a/src/output/afm.h +++ /dev/null @@ -1,61 +0,0 @@ -/* PSPP - a program for statistical analysis. - Copyright (C) 2006 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef AFM_H -#define AFM_H 1 - -#include -#include - -/* Metrics for a single character. */ -struct afm_character - { - int code; /* Non-negative character code, -1 if none. */ - const char *name; /* Character name, if any. */ - int width; /* Width. */ - int ascent; /* Height above baseline, never negative. */ - int descent; /* Depth below baseline, never negative. */ - - /* Pairwise kerning data for this character in the first - position, other characters in the second position. */ - struct afm_kern_pair *kern_pairs; - size_t kern_pair_cnt; - - /* Ligature data for this character in the first position, - other characters in the second position. */ - struct afm_ligature *ligatures; - size_t ligature_cnt; - }; - -struct afm *afm_open (const char *file_name); -void afm_close (struct afm *); - -int afm_get_ascent (const struct afm *); -int afm_get_descent (const struct afm *); -const char *afm_get_findfont_name (const struct afm *); - -const struct afm_character *afm_get_character (const struct afm *, - int code); -const struct afm_character *afm_get_ligature (const struct afm_character *, - const struct afm_character *); -int afm_get_kern_adjustment (const struct afm_character *, - const struct afm_character *); - -size_t afm_encode_string (const struct afm *, - const struct afm_character **, size_t, - struct string *); - -#endif /* afm.h */ diff --git a/src/output/ascii.c b/src/output/ascii.c index 29d7b76b..b224b3eb 100644 --- a/src/output/ascii.c +++ b/src/output/ascii.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,11 +29,12 @@ #include #include #include +#include +#include +#include -#include "chart.h" #include "error.h" #include "minmax.h" -#include "output.h" #include "xalloc.h" #include "gettext.h" @@ -44,7 +45,7 @@ output-file="pspp.list" append=no|yes If output-file exists, append to it? chart-files="pspp-#.png" Name used for charts. - chart-type=png Format of charts (use "none" to disable). + chart-type=png|none paginate=on|off Formfeeds are desired? tab-width=8 Width of a tab; 0 to not use tabs. @@ -108,7 +109,7 @@ struct ascii_driver_ext bool squeeze_blank_lines; /* Squeeze multiple blank lines into one? */ enum emphasis_style emphasis; /* How to emphasize text. */ int tab_width; /* Width of a tab; 0 not to use tabs. */ - const char *chart_type; /* Type of charts to output; NULL for none. */ + bool enable_charts; /* Enable charts? */ const char *chart_file_name; /* Name of files used for charts. */ bool auto_width; /* Use viewwidth as page width? */ @@ -133,15 +134,17 @@ struct ascii_driver_ext static void ascii_flush (struct outp_driver *); static int get_default_box_char (size_t idx); static bool update_page_size (struct outp_driver *, bool issue_error); -static bool handle_option (struct outp_driver *this, const char *key, +static bool handle_option (void *this, const char *key, const struct string *val); static bool -ascii_open_driver (struct outp_driver *this, struct substring options) +ascii_open_driver (const char *name, int types, struct substring options) { + struct outp_driver *this; struct ascii_driver_ext *x; int i; + this = outp_allocate_driver (&ascii_class, name, types); this->width = 79; this->font_height = 1; this->prop_em_width = 1; @@ -157,7 +160,7 @@ ascii_open_driver (struct outp_driver *this, struct substring options) x->emphasis = EMPH_BOLD; x->tab_width = 8; x->chart_file_name = pool_strdup (x->pool, "pspp-#.png"); - x->chart_type = pool_strdup (x->pool, "png"); + x->enable_charts = true; x->auto_width = false; x->auto_length = false; x->page_length = 66; @@ -172,9 +175,9 @@ ascii_open_driver (struct outp_driver *this, struct substring options) x->page_number = 0; x->lines = NULL; x->line_cap = 0; - x->chart_cnt = 0; + x->chart_cnt = 1; - if (!outp_parse_options (options, handle_option, this)) + if (!outp_parse_options (this->name, options, handle_option, this)) goto error; if (!update_page_size (this, true)) @@ -189,10 +192,13 @@ ascii_open_driver (struct outp_driver *this, struct substring options) x->box[i] = pool_strdup (x->pool, s); } + outp_register_driver (this); + return true; error: pool_destroy (x->pool); + outp_free_driver (this); return false; } @@ -312,9 +318,10 @@ static const struct outp_option option_tab[] = }; static bool -handle_option (struct outp_driver *this, const char *key, +handle_option (void *this_, const char *key, const struct string *val) { + struct outp_driver *this = this_; struct ascii_driver_ext *x = this->ext; int subcat; const char *value; @@ -478,10 +485,16 @@ handle_option (struct outp_driver *this, const char *key, error (0, 0, _("`chart-files' value must contain `#'")); break; case 2: - if (value[0] != '\0') - x->chart_type = pool_strdup (x->pool, value); + if (!strcmp (value, "png")) + x->enable_charts = true; + else if (!strcmp (value, "none")) + x->enable_charts = false; else - x->chart_type = NULL; + { + error (0, 0, + _("ascii: `png' or `none' expected for `chart-type'")); + return false; + } break; case 3: x->init = pool_strdup (x->pool, value); @@ -603,15 +616,6 @@ ascii_line (struct outp_driver *this, } } -static void -ascii_submit (struct outp_driver *this UNUSED, struct som_entity *s) -{ - extern struct som_table_class tab_table_class; - - assert (s->class == &tab_table_class); - assert (s->type == SOM_CHART); -} - static void text_draw (struct outp_driver *this, enum outp_font font, @@ -866,19 +870,15 @@ ascii_flush (struct outp_driver *this) } static void -ascii_chart_initialise (struct outp_driver *this, struct chart *ch) +ascii_output_chart (struct outp_driver *this, const struct chart *chart) { struct ascii_driver_ext *x = this->ext; struct outp_text t; + char *file_name; char *text; - if (x->chart_type == NULL) - return; - - /* Initialize chart. */ - chart_init_separate (ch, x->chart_type, x->chart_file_name, ++x->chart_cnt); - if (ch->file_name == NULL) - return; + /* Draw chart into separate file */ + file_name = chart_draw_png (chart, x->chart_file_name, x->chart_cnt++); /* Mention chart in output. First advance current position. */ @@ -895,7 +895,7 @@ ascii_chart_initialise (struct outp_driver *this, struct chart *ch) } /* Then write the text. */ - text = xasprintf ("See %s for a chart.", ch->file_name); + text = xasprintf ("See %s for a chart.", file_name); t.font = OUTP_FIXED; t.justification = OUTP_LEFT; t.string = ss_cstr (text); @@ -906,17 +906,10 @@ ascii_chart_initialise (struct outp_driver *this, struct chart *ch) ascii_text_draw (this, &t); this->cp_y++; + free (file_name); free (text); } -static void -ascii_chart_finalise (struct outp_driver *this, struct chart *ch) -{ - struct ascii_driver_ext *x = this->ext; - if (x->chart_type != NULL) - chart_finalise_separate (ch); -} - const struct outp_class ascii_class = { "ascii", @@ -929,12 +922,11 @@ const struct outp_class ascii_class = ascii_close_page, ascii_flush, - ascii_submit, + ascii_output_chart, + + NULL, /* submit */ ascii_line, ascii_text_metrics, ascii_text_draw, - - ascii_chart_initialise, - ascii_chart_finalise }; diff --git a/src/output/automake.mk b/src/output/automake.mk index ec92c559..7e233750 100644 --- a/src/output/automake.mk +++ b/src/output/automake.mk @@ -1,35 +1,40 @@ ## Process this file with automake to produce Makefile.in -*- makefile -*- - -include $(top_srcdir)/src/output/charts/automake.mk - noinst_LTLIBRARIES += src/output/liboutput.la -output_sources = \ - src/output/afm.c \ - src/output/afm.h \ +src_output_liboutput_la_CPPFLAGS = $(LIBXML2_CFLAGS) $(AM_CPPFLAGS) + +src_output_liboutput_la_SOURCES = \ src/output/ascii.c \ + src/output/chart.c \ + src/output/chart.h \ + src/output/charts/boxplot.c \ + src/output/charts/boxplot.h \ + src/output/charts/cartesian.c \ + src/output/charts/cartesian.h \ + src/output/charts/np-plot.c \ + src/output/charts/np-plot.h \ + src/output/charts/piechart.c \ + src/output/charts/piechart.h \ + src/output/charts/plot-chart.c \ + src/output/charts/plot-chart.h \ + src/output/charts/plot-hist.c \ + src/output/charts/plot-hist.h \ + src/output/charts/roc-chart.c \ + src/output/charts/roc-chart.h \ src/output/html.c \ src/output/htmlP.h \ src/output/journal.c \ src/output/journal.h \ - src/output/output.c \ - src/output/output.h \ - src/output/postscript.c \ src/output/manager.c \ src/output/manager.h \ - src/output/chart.h \ - src/output/table.c src/output/table.h - - -if WITHCHARTS -src_output_liboutput_la_SOURCES = $(output_sources) src/output/chart.c - -EXTRA_DIST += src/output/dummy-chart.c -else -src_output_liboutput_la_SOURCES = $(output_sources) src/output/dummy-chart.c - -EXTRA_DIST += src/output/chart.c + src/output/odt.c \ + src/output/output.c \ + src/output/output.h \ + src/output/table.c \ + src/output/table.h +if HAVE_CAIRO +src_output_liboutput_la_SOURCES += src/output/cairo.c endif EXTRA_DIST += src/output/OChangeLog diff --git a/src/output/cairo.c b/src/output/cairo.c new file mode 100644 index 00000000..162009c4 --- /dev/null +++ b/src/output/cairo.c @@ -0,0 +1,910 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "error.h" +#include "intprops.h" +#include "minmax.h" +#include "xalloc.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +/* Cairo driver options: (defaults listed first) + + output-file="pspp.pdf" + output-type=pdf|ps|png|svg + paper-size=letter (see "papersize" file) + orientation=portrait|landscape + headers=on|off + + left-margin=0.5in + right-margin=0.5in + top-margin=0.5in + bottom-margin=0.5in + + prop-font=serif + emph-font=serif italic + fixed-font=monospace + font-size=10000 + + line-gutter=1pt + line-spacing=1pt + line-width=0.5pt + */ + +/* Measurements as we present to the rest of PSPP. */ +#define XR_POINT PANGO_SCALE +#define XR_INCH (XR_POINT * 72) + +/* Conversions to and from points. */ +static double +xr_to_pt (int x) +{ + return x / (double) XR_POINT; +} + +static int +pt_to_xr (double x) +{ + return x * XR_POINT + 0.5; +} + +/* Output types. */ +enum xr_output_type + { + XR_PDF, + XR_PS, + XR_SVG + }; + +/* A font for use with Cairo. */ +struct xr_font + { + char *string; + PangoFontDescription *desc; + PangoLayout *layout; + PangoFontMetrics *metrics; + }; + +/* Cairo output driver extension record. */ +struct xr_driver_ext + { + cairo_t *cairo; + struct xr_font fonts[OUTP_FONT_CNT]; + + bool draw_headers; /* Draw headers at top of page? */ + int page_number; /* Current page number. */ + + int line_gutter; /* Space around lines. */ + int line_space; /* Space between lines. */ + int line_width; /* Width of lines. */ + }; + +struct xr_driver_options + { + struct outp_driver *driver; + + char *file_name; /* Output file name. */ + enum xr_output_type file_type; /* Type of output file. */ + + + bool portrait; /* Portrait mode? */ + + int paper_width; /* Width of paper before dropping margins. */ + int paper_length; /* Length of paper before dropping margins. */ + int left_margin; /* Left margin in XR units. */ + int right_margin; /* Right margin in XR units. */ + int top_margin; /* Top margin in XR units. */ + int bottom_margin; /* Bottom margin in XR units. */ + }; + +static bool handle_option (void *options, const char *key, + const struct string *val); +static void draw_headers (struct outp_driver *this); + +static bool load_font (struct outp_driver *this, struct xr_font *); +static void free_font (struct xr_font *); +static int text_width (struct outp_driver *, const char *, enum outp_font); + +/* Driver initialization. */ + +static struct outp_driver * +xr_allocate (const char *name, int types) +{ + struct outp_driver *this; + struct xr_driver_ext *x; + size_t i; + + this = outp_allocate_driver (&cairo_class, name, types); + this->width = this->length = 0; + this->font_height = XR_POINT * 10; + this->ext = x = xzalloc (sizeof *x); + x->cairo = NULL; + x->fonts[OUTP_FIXED].string = xstrdup ("monospace"); + x->fonts[OUTP_PROPORTIONAL].string = xstrdup ("serif"); + x->fonts[OUTP_EMPHASIS].string = xstrdup ("serif italic"); + for (i = 0; i < OUTP_FONT_CNT; i++) + { + struct xr_font *font = &x->fonts[i]; + font->desc = NULL; + font->metrics = NULL; + font->layout = NULL; + } + x->draw_headers = true; + x->page_number = 0; + x->line_gutter = XR_POINT; + x->line_space = XR_POINT; + x->line_width = XR_POINT / 2; + + return this; +} + +static bool +xr_set_cairo (struct outp_driver *this, cairo_t *cairo) +{ + struct xr_driver_ext *x = this->ext; + int i; + + x->cairo = cairo; + + cairo_set_line_width (x->cairo, xr_to_pt (x->line_width)); + + for (i = 0; i < OUTP_FONT_CNT; i++) + if (!load_font (this, &x->fonts[i])) + return false; + + this->fixed_width = text_width (this, "0", OUTP_FIXED); + this->prop_em_width = text_width (this, "0", OUTP_PROPORTIONAL); + + this->horiz_line_width[OUTP_L_NONE] = 0; + this->horiz_line_width[OUTP_L_SINGLE] = 2 * x->line_gutter + x->line_width; + this->horiz_line_width[OUTP_L_DOUBLE] = (2 * x->line_gutter + x->line_space + + 2 * x->line_width); + memcpy (this->vert_line_width, this->horiz_line_width, + sizeof this->vert_line_width); + + return true; +} + +struct outp_driver * +xr_create_driver (cairo_t *cairo) +{ + struct outp_driver *this; + + this = xr_allocate ("cairo", 0); + this->width = INT_MAX / 8; + this->length = INT_MAX / 8; + if (!xr_set_cairo (this, cairo)) + { + this->class->close_driver (this); + outp_free_driver (this); + return NULL; + } + return this; +} + +static bool +xr_open_driver (const char *name, int types, struct substring option_string) +{ + struct outp_driver *this; + struct xr_driver_ext *x; + struct xr_driver_options options; + cairo_surface_t *surface; + cairo_status_t status; + double width_pt, length_pt; + + this = xr_allocate (name, types); + x = this->ext; + + options.driver = this; + options.file_name = xstrdup ("pspp.pdf"); + options.file_type = XR_PDF; + options.portrait = true; + outp_get_paper_size ("", &options.paper_width, &options.paper_length); + options.left_margin = XR_INCH / 2; + options.right_margin = XR_INCH / 2; + options.top_margin = XR_INCH / 2; + options.bottom_margin = XR_INCH / 2; + + outp_parse_options (this->name, option_string, handle_option, &options); + + width_pt = options.paper_width / 1000.0; + length_pt = options.paper_length / 1000.0; + if (options.portrait) + { + this->width = pt_to_xr (width_pt); + this->length = pt_to_xr (length_pt); + } + else + { + this->width = pt_to_xr (width_pt); + this->length = pt_to_xr (length_pt); + } + if (x->draw_headers) + options.top_margin += 3 * this->font_height; + this->width -= options.left_margin + options.right_margin; + this->length -= options.top_margin + options.bottom_margin; + + if (options.file_type == XR_PDF) + surface = cairo_pdf_surface_create (options.file_name, + width_pt, length_pt); + else if (options.file_type == XR_PS) + surface = cairo_ps_surface_create (options.file_name, width_pt, length_pt); + else if (options.file_type == XR_SVG) + surface = cairo_svg_surface_create (options.file_name, + width_pt, length_pt); + else + NOT_REACHED (); + + status = cairo_surface_status (surface); + if (status != CAIRO_STATUS_SUCCESS) + { + error (0, 0, _("opening output file \"%s\": %s"), + options.file_name, cairo_status_to_string (status)); + cairo_surface_destroy (surface); + goto error; + } + + x->cairo = cairo_create (surface); + cairo_surface_destroy (surface); + + cairo_translate (x->cairo, + xr_to_pt (options.left_margin), + xr_to_pt (options.top_margin)); + + if (this->length / this->font_height < 15) + { + error (0, 0, _("The defined page is not long " + "enough to hold margins and headers, plus least 15 " + "lines of the default fonts. In fact, there's only " + "room for %d lines."), + this->length / this->font_height); + goto error; + } + + if (!xr_set_cairo (this, x->cairo)) + goto error; + + outp_register_driver (this); + free (options.file_name); + return true; + + error: + this->class->close_driver (this); + outp_free_driver (this); + free (options.file_name); + return false; +} + +static bool +xr_close_driver (struct outp_driver *this) +{ + struct xr_driver_ext *x = this->ext; + bool ok = true; + size_t i; + + if (x->cairo != NULL) + { + cairo_status_t status; + + cairo_surface_finish (cairo_get_target (x->cairo)); + status = cairo_status (x->cairo); + if (status != CAIRO_STATUS_SUCCESS) + error (0, 0, _("error writing output file for %s driver: %s"), + this->name, cairo_status_to_string (status)); + cairo_destroy (x->cairo); + } + + for (i = 0; i < OUTP_FONT_CNT; i++) + free_font (&x->fonts[i]); + free (x); + + return ok; +} + +/* Generic option types. */ +enum +{ + output_file_arg, + output_type_arg, + paper_size_arg, + orientation_arg, + line_style_arg, + boolean_arg, + dimension_arg, + string_arg, + nonneg_int_arg +}; + +/* All the options that the Cairo driver supports. */ +static const struct outp_option option_tab[] = +{ + {"output-file", output_file_arg,0}, + {"output-type", output_type_arg,0}, + {"paper-size", paper_size_arg, 0}, + {"orientation", orientation_arg,0}, + + {"headers", boolean_arg, 1}, + + {"prop-font", string_arg, OUTP_PROPORTIONAL}, + {"emph-font", string_arg, OUTP_EMPHASIS}, + {"fixed-font", string_arg, OUTP_FIXED}, + + {"left-margin", dimension_arg, 0}, + {"right-margin", dimension_arg, 1}, + {"top-margin", dimension_arg, 2}, + {"bottom-margin", dimension_arg, 3}, + {"font-size", dimension_arg, 4}, + {"line-width", dimension_arg, 5}, + {"line-gutter", dimension_arg, 6}, + {"line-width", dimension_arg, 7}, + {NULL, 0, 0}, +}; + +static bool +handle_option (void *options_, const char *key, const struct string *val) +{ + struct xr_driver_options *options = options_; + struct outp_driver *this = options->driver; + struct xr_driver_ext *x = this->ext; + int subcat; + char *value = ds_cstr (val); + + switch (outp_match_keyword (key, option_tab, &subcat)) + { + case -1: + error (0, 0, + _("unknown configuration parameter `%s' for %s device " + "driver"), key, this->class->name); + break; + case output_file_arg: + free (options->file_name); + options->file_name = xstrdup (value); + break; + case output_type_arg: + if (!strcmp (value, "pdf")) + options->file_type = XR_PDF; + else if (!strcmp (value, "ps")) + options->file_type = XR_PS; + else if (!strcmp (value, "svg")) + options->file_type = XR_SVG; + else + { + error (0, 0, _("unknown Cairo output type \"%s\""), value); + return false; + } + break; + case paper_size_arg: + outp_get_paper_size (value, + &options->paper_width, &options->paper_length); + break; + case orientation_arg: + if (!strcmp (value, "portrait")) + options->portrait = true; + else if (!strcmp (value, "landscape")) + options->portrait = false; + else + error (0, 0, _("unknown orientation `%s' (valid orientations are " + "`portrait' and `landscape')"), value); + break; + case boolean_arg: + if (!strcmp (value, "on") || !strcmp (value, "true") + || !strcmp (value, "yes") || atoi (value)) + x->draw_headers = true; + else if (!strcmp (value, "off") || !strcmp (value, "false") + || !strcmp (value, "no") || !strcmp (value, "0")) + x->draw_headers = false; + else + { + error (0, 0, _("boolean value expected for %s"), key); + return false; + } + break; + case dimension_arg: + { + int dimension = outp_evaluate_dimension (value); + + if (dimension <= 0) + break; + switch (subcat) + { + case 0: + options->left_margin = dimension; + break; + case 1: + options->right_margin = dimension; + break; + case 2: + options->top_margin = dimension; + break; + case 3: + options->bottom_margin = dimension; + break; + case 4: + this->font_height = dimension; + break; + case 5: + x->line_width = dimension; + break; + case 6: + x->line_gutter = dimension; + break; + case 7: + x->line_width = dimension; + break; + default: + NOT_REACHED (); + } + } + break; + case string_arg: + free (x->fonts[subcat].string); + x->fonts[subcat].string = ds_xstrdup (val); + break; + default: + NOT_REACHED (); + } + + return true; +} + +/* Basic file operations. */ + +static void +xr_open_page (struct outp_driver *this) +{ + struct xr_driver_ext *x = this->ext; + + x->page_number++; + + if (x->draw_headers) + draw_headers (this); +} + +static void +xr_close_page (struct outp_driver *this) +{ + struct xr_driver_ext *x = this->ext; + cairo_show_page (x->cairo); +} + +static void +xr_output_chart (struct outp_driver *this, const struct chart *chart) +{ + struct xr_driver_ext *x = this->ext; + struct chart_geometry geom; + + outp_eject_page (this); + outp_open_page (this); + + cairo_save (x->cairo); + cairo_translate (x->cairo, 0.0, xr_to_pt (this->length)); + cairo_scale (x->cairo, 1.0, -1.0); + chart_geometry_init (x->cairo, &geom, + xr_to_pt (this->width), xr_to_pt (this->length)); + chart_draw (chart, x->cairo, &geom); + chart_geometry_free (x->cairo, &geom); + cairo_restore (x->cairo); + + outp_close_page (this); +} + +/* Draws a line from (x0,y0) to (x1,y1). */ +static void +dump_line (struct outp_driver *this, int x0, int y0, int x1, int y1) +{ + struct xr_driver_ext *x = this->ext; + cairo_new_path (x->cairo); + cairo_move_to (x->cairo, xr_to_pt (x0), xr_to_pt (y0)); + cairo_line_to (x->cairo, xr_to_pt (x1), xr_to_pt (y1)); + cairo_stroke (x->cairo); +} + +/* Draws a horizontal line X0...X2 at Y if LEFT says so, + shortening it to X0...X1 if SHORTEN is true. + Draws a horizontal line X1...X3 at Y if RIGHT says so, + shortening it to X2...X3 if SHORTEN is true. */ +static void +horz_line (struct outp_driver *this, + int x0, int x1, int x2, int x3, int y, + enum outp_line_style left, enum outp_line_style right, + bool shorten) +{ + if (left != OUTP_L_NONE && right != OUTP_L_NONE && !shorten) + dump_line (this, x0, y, x3, y); + else + { + if (left != OUTP_L_NONE) + dump_line (this, x0, y, shorten ? x1 : x2, y); + if (right != OUTP_L_NONE) + dump_line (this, shorten ? x2 : x1, y, x3, y); + } +} + +/* Draws a vertical line Y0...Y2 at X if TOP says so, + shortening it to Y0...Y1 if SHORTEN is true. + Draws a vertical line Y1...Y3 at X if BOTTOM says so, + shortening it to Y2...Y3 if SHORTEN is true. */ +static void +vert_line (struct outp_driver *this, + int y0, int y1, int y2, int y3, int x, + enum outp_line_style top, enum outp_line_style bottom, + bool shorten) +{ + if (top != OUTP_L_NONE && bottom != OUTP_L_NONE && !shorten) + dump_line (this, x, y0, x, y3); + else + { + if (top != OUTP_L_NONE) + dump_line (this, x, y0, x, shorten ? y1 : y2); + if (bottom != OUTP_L_NONE) + dump_line (this, x, shorten ? y2 : y1, x, y3); + } +} + +/* Draws a generalized intersection of lines in the rectangle + (X0,Y0)-(X3,Y3). The line coming from the top to the center + is of style TOP, from left to center of style LEFT, from + bottom to center of style BOTTOM, and from right to center of + style RIGHT. */ +static void +xr_line (struct outp_driver *this, + int x0, int y0, int x3, int y3, + enum outp_line_style top, enum outp_line_style left, + enum outp_line_style bottom, enum outp_line_style right) +{ + /* The algorithm here is somewhat subtle, to allow it to handle + all the kinds of intersections that we need. + + Three additional ordinates are assigned along the x axis. The + first is xc, midway between x0 and x3. The others are x1 and + x2; for a single vertical line these are equal to xc, and for + a double vertical line they are the ordinates of the left and + right half of the double line. + + yc, y1, and y2 are assigned similarly along the y axis. + + The following diagram shows the coordinate system and output + for double top and bottom lines, single left line, and no + right line: + + x0 x1 xc x2 x3 + y0 ________________________ + | # # | + | # # | + | # # | + | # # | + | # # | + y1 = y2 = yc |######### # | + | # # | + | # # | + | # # | + | # # | + y3 |________#_____#_______| + */ + struct xr_driver_ext *ext = this->ext; + + /* Offset from center of each line in a pair of double lines. */ + int double_line_ofs = (ext->line_space + ext->line_width) / 2; + + /* Are the lines along each axis single or double? + (It doesn't make sense to have different kinds of line on the + same axis, so we don't try to gracefully handle that case.) */ + bool double_vert = top == OUTP_L_DOUBLE || bottom == OUTP_L_DOUBLE; + bool double_horz = left == OUTP_L_DOUBLE || right == OUTP_L_DOUBLE; + + /* When horizontal lines are doubled, + the left-side line along y1 normally runs from x0 to x2, + and the right-side line along y1 from x3 to x1. + If the top-side line is also doubled, we shorten the y1 lines, + so that the left-side line runs only to x1, + and the right-side line only to x2. + Otherwise, the horizontal line at y = y1 below would cut off + the intersection, which looks ugly: + x0 x1 x2 x3 + y0 ________________________ + | # # | + | # # | + | # # | + | # # | + y1 |######### ########| + | | + | | + y2 |######################| + | | + | | + y3 |______________________| + It is more of a judgment call when the horizontal line is + single. We actually choose to cut off the line anyhow, as + shown in the first diagram above. + */ + bool shorten_y1_lines = top == OUTP_L_DOUBLE; + bool shorten_y2_lines = bottom == OUTP_L_DOUBLE; + bool shorten_yc_line = shorten_y1_lines && shorten_y2_lines; + int horz_line_ofs = double_vert ? double_line_ofs : 0; + int xc = (x0 + x3) / 2; + int x1 = xc - horz_line_ofs; + int x2 = xc + horz_line_ofs; + + bool shorten_x1_lines = left == OUTP_L_DOUBLE; + bool shorten_x2_lines = right == OUTP_L_DOUBLE; + bool shorten_xc_line = shorten_x1_lines && shorten_x2_lines; + int vert_line_ofs = double_horz ? double_line_ofs : 0; + int yc = (y0 + y3) / 2; + int y1 = yc - vert_line_ofs; + int y2 = yc + vert_line_ofs; + + if (!double_horz) + horz_line (this, x0, x1, x2, x3, yc, left, right, shorten_yc_line); + else + { + horz_line (this, x0, x1, x2, x3, y1, left, right, shorten_y1_lines); + horz_line (this, x0, x1, x2, x3, y2, left, right, shorten_y2_lines); + } + + if (!double_vert) + vert_line (this, y0, y1, y2, y3, xc, top, bottom, shorten_xc_line); + else + { + vert_line (this, y0, y1, y2, y3, x1, top, bottom, shorten_x1_lines); + vert_line (this, y0, y1, y2, y3, x2, top, bottom, shorten_x2_lines); + } +} + +/* Writes STRING at location (X,Y) trimmed to the given MAX_WIDTH + and with the given JUSTIFICATION for THIS driver. */ +static int +draw_text (struct outp_driver *this, + const char *string, int x, int y, int max_width, + enum outp_justification justification) +{ + struct outp_text text; + int width; + + text.font = OUTP_PROPORTIONAL; + text.justification = justification; + text.string = ss_cstr (string); + text.h = max_width; + text.v = this->font_height; + text.x = x; + text.y = y; + this->class->text_metrics (this, &text, &width, NULL); + this->class->text_draw (this, &text); + return width; +} + +/* Writes STRING at location (X,Y) trimmed to the given MAX_WIDTH + and with the given JUSTIFICATION for THIS driver. */ +static int +text_width (struct outp_driver *this, const char *string, enum outp_font font) +{ + struct outp_text text; + int width; + + text.font = font; + text.justification = OUTP_LEFT; + text.string = ss_cstr (string); + text.h = INT_MAX; + text.v = this->font_height; + text.x = 0; + text.y = 0; + this->class->text_metrics (this, &text, &width, NULL); + return width; +} + +/* Writes LEFT left-justified and RIGHT right-justified within + (X0...X1) at Y. LEFT or RIGHT or both may be null. */ +static void +draw_header_line (struct outp_driver *this, + const char *left, const char *right, + int x0, int x1, int y) +{ + int right_width = 0; + if (right != NULL) + right_width = (draw_text (this, right, x0, y, x1 - x0, OUTP_RIGHT) + + this->prop_em_width); + if (left != NULL) + draw_text (this, left, x0, y, x1 - x0 - right_width, OUTP_LEFT); +} + +/* Draw top of page headers for THIS driver. */ +static void +draw_headers (struct outp_driver *this) +{ + struct xr_driver_ext *ext = this->ext; + char *r1, *r2; + int x0, x1; + int y; + + y = -3 * this->font_height; + x0 = this->prop_em_width; + x1 = this->width - this->prop_em_width; + + /* Draw box. */ + cairo_rectangle (ext->cairo, 0, xr_to_pt (y), xr_to_pt (this->width), + xr_to_pt (2 * (this->font_height + + ext->line_width + ext->line_gutter))); + cairo_save (ext->cairo); + cairo_set_source_rgb (ext->cairo, 0.9, 0.9, 0.9); + cairo_fill_preserve (ext->cairo); + cairo_restore (ext->cairo); + cairo_stroke (ext->cairo); + + y += ext->line_width + ext->line_gutter; + + r1 = xasprintf (_("%s - Page %d"), get_start_date (), ext->page_number); + r2 = xasprintf ("%s - %s", version, host_system); + + draw_header_line (this, outp_title, r1, x0, x1, y); + y += this->font_height; + + draw_header_line (this, outp_subtitle, r2, x0, x1, y); + + free (r1); + free (r2); +} + +/* Format TEXT on THIS driver. + If DRAW is nonzero, draw the text. + The width of the widest line is stored into *WIDTH, if WIDTH + is nonnull. + The total height of the text written is stored into *HEIGHT, + if HEIGHT is nonnull. */ +static void +text (struct outp_driver *this, const struct outp_text *text, bool draw, + int *width, int *height) +{ + struct xr_driver_ext *ext = this->ext; + struct xr_font *font = &ext->fonts[text->font]; + + pango_layout_set_text (font->layout, + text->string.string, text->string.length); + pango_layout_set_alignment ( + font->layout, + (text->justification == OUTP_RIGHT ? PANGO_ALIGN_RIGHT + : text->justification == OUTP_LEFT ? PANGO_ALIGN_LEFT + : PANGO_ALIGN_CENTER)); + pango_layout_set_width (font->layout, text->h == INT_MAX ? -1 : text->h); + pango_layout_set_wrap (font->layout, PANGO_WRAP_WORD_CHAR); + /* XXX need to limit number of lines to those that fit in text->v. */ + + if (draw) + { + int x = text->x; + if (text->justification != OUTP_LEFT && text->h != INT_MAX) + { + int w, h, excess; + pango_layout_get_size (font->layout, &w, &h); + excess = text->h - w; + if (excess > 0) + { + if (text->justification == OUTP_CENTER) + x += excess / 2; + else + x += excess; + } + } + cairo_save (ext->cairo); + cairo_translate (ext->cairo, xr_to_pt (text->x), xr_to_pt (text->y)); + pango_cairo_show_layout (ext->cairo, font->layout); + cairo_restore (ext->cairo); + } + + if (width != NULL || height != NULL) + { + int w, h; + pango_layout_get_size (font->layout, &w, &h); + if (width != NULL) + *width = w; + if (height != NULL) + *height = h; + } +} + +static void +xr_text_metrics (struct outp_driver *this, const struct outp_text *t, + int *width, int *height) +{ + text (this, t, false, width, height); +} + +static void +xr_text_draw (struct outp_driver *this, const struct outp_text *t) +{ + text (this, t, true, NULL, NULL); +} + +/* Attempts to load FONT, initializing its other members based on + its 'string' member and the information in THIS. Returns true + if successful, otherwise false. */ +static bool +load_font (struct outp_driver *this, struct xr_font *font) +{ + struct xr_driver_ext *x = this->ext; + PangoContext *context; + PangoLanguage *language; + + font->desc = pango_font_description_from_string (font->string); + if (font->desc == NULL) + { + error (0, 0, _("\"%s\": bad font specification"), font->string); + return false; + } + pango_font_description_set_absolute_size (font->desc, this->font_height); + + font->layout = pango_cairo_create_layout (x->cairo); + pango_layout_set_font_description (font->layout, font->desc); + + language = pango_language_get_default (); + context = pango_layout_get_context (font->layout); + font->metrics = pango_context_get_metrics (context, font->desc, language); + + return true; +} + +/* Frees FONT. */ +static void +free_font (struct xr_font *font) +{ + free (font->string); + if (font->desc != NULL) + pango_font_description_free (font->desc); + pango_font_metrics_unref (font->metrics); + g_object_unref (font->layout); +} + +/* Cairo driver class. */ +const struct outp_class cairo_class = +{ + "cairo", + 0, + + xr_open_driver, + xr_close_driver, + + xr_open_page, + xr_close_page, + NULL, + + xr_output_chart, + + NULL, + + xr_line, + xr_text_metrics, + xr_text_draw, +}; diff --git a/src/output/cairo.h b/src/output/cairo.h new file mode 100644 index 00000000..c4f8a813 --- /dev/null +++ b/src/output/cairo.h @@ -0,0 +1,24 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef OUTPUT_CAIRO_H +#define OUTPUT_CAIRO_H 1 + +#include + +struct outp_driver *xr_create_driver (cairo_t *); + +#endif /* output/cairo.h */ diff --git a/src/output/chart-provider.h b/src/output/chart-provider.h new file mode 100644 index 00000000..9becb6f5 --- /dev/null +++ b/src/output/chart-provider.h @@ -0,0 +1,89 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2004, 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef OUTPUT_CHART_PROVIDER_H +#define OUTPUT_CHART_PROVIDER_H 1 + +#include +#include +#include +#include + +struct chart_colour + { + uint8_t red; + uint8_t green; + uint8_t blue; + }; + +/* The geometry of a chart. */ +struct chart_geometry + { + int data_top ; + int data_right ; + int data_bottom; + int data_left ; + + int abscissa_top; + + int ordinate_right ; + + int title_bottom ; + + /* Legend. */ + int legend_left ; + int legend_right ; + const char **dataset; + int n_datasets; + + /* Default font size for the plot. */ + double font_size; + + struct chart_colour fill_colour; + + /* Stuff Particular to Cartesians (and Boxplots ) */ + double ordinate_scale; + double abscissa_scale; + double x_min; + double x_max; + double y_min; + double y_max; + bool in_path; + }; + +struct chart_class + { + void (*draw) (const struct chart *, cairo_t *, struct chart_geometry *); + void (*destroy) (struct chart *); + }; + +struct chart + { + const struct chart_class *class; + int ref_cnt; + }; + +void chart_init (struct chart *, const struct chart_class *); + +void chart_geometry_init (cairo_t *, struct chart_geometry *, + double width, double length); +void chart_geometry_free (cairo_t *, struct chart_geometry *); + +void chart_draw (const struct chart *, cairo_t *, struct chart_geometry *); +char *chart_draw_png (const struct chart *, const char *file_name_template, + int number); + +#endif /* output/chart-provider.h */ diff --git a/src/output/chart.c b/src/output/chart.c index e324901c..e31422bc 100644 --- a/src/output/chart.c +++ b/src/output/chart.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,8 +17,10 @@ #include #include +#include #include +#include #include #include #include @@ -27,8 +29,6 @@ #include #include -#include - #include #include #include @@ -41,128 +41,141 @@ extern struct som_table_class tab_table_class; -struct chart * -chart_create(void) +void +chart_init (struct chart *chart, const struct chart_class *class) { - struct chart *chart; - struct outp_driver *d; - - d = outp_drivers (NULL); - if (d == NULL) - return NULL; - - chart = xmalloc (sizeof *chart); - chart->lp = NULL; - d->class->initialise_chart(d, chart); - if (!chart->lp) - { - free (chart); - return NULL; - } - - if (pl_openpl_r (chart->lp) < 0) /* open Plotter */ - return NULL; - - pl_fspace_r (chart->lp, 0.0, 0.0, 1000.0, 1000.0); /* set coordinate system */ - pl_flinewidth_r (chart->lp, 0.25); /* set line thickness */ - pl_pencolorname_r (chart->lp, "black"); - - pl_erase_r (chart->lp); /* erase graphics display */ - pl_filltype_r(chart->lp,0); - - pl_savestate_r(chart->lp); - - /* Set default chartetry */ - chart->data_top = 900; - chart->data_right = 800; - chart->data_bottom = 120; - chart->data_left = 150; - chart->abscissa_top = 70; - chart->ordinate_right = 120; - chart->title_bottom = 920; - chart->legend_left = 810; - chart->legend_right = 1000; - chart->font_size = 0; - chart->in_path = false; - chart->dataset = NULL; - chart->n_datasets = 0; - strcpy(chart->fill_colour,"red"); - - /* Get default font size */ - if ( !chart->font_size) - chart->font_size = pl_fontsize_r(chart->lp, -1); - - /* Draw the data area */ - pl_box_r(chart->lp, - chart->data_left, chart->data_bottom, - chart->data_right, chart->data_top); + chart->class = class; + chart->ref_cnt = 1; +} - return chart; +void +chart_geometry_init (cairo_t *cr, struct chart_geometry *geom, + double width, double length) +{ + /* Set default chartetry. */ + geom->data_top = 0.900 * length; + geom->data_right = 0.800 * width; + geom->data_bottom = 0.120 * length; + geom->data_left = 0.150 * width; + geom->abscissa_top = 0.070 * length; + geom->ordinate_right = 0.120 * width; + geom->title_bottom = 0.920 * length; + geom->legend_left = 0.810 * width; + geom->legend_right = width; + geom->font_size = 15.0; + geom->in_path = false; + geom->dataset = NULL; + geom->n_datasets = 0; + + geom->fill_colour.red = 255; + geom->fill_colour.green = 0; + geom->fill_colour.blue = 0; + + cairo_set_line_width (cr, 1.0); + + cairo_rectangle (cr, geom->data_left, geom->data_bottom, + geom->data_right - geom->data_left, + geom->data_top - geom->data_bottom); + cairo_stroke (cr); } void -chart_submit(struct chart *chart) +chart_geometry_free (cairo_t *cr UNUSED, struct chart_geometry *geom) { int i; - struct som_entity s; - struct outp_driver *d; - - if ( ! chart ) - return ; - - pl_restorestate_r(chart->lp); - - s.class = &tab_table_class; - s.ext = chart; - s.type = SOM_CHART; - som_submit (&s); - if (pl_closepl_r (chart->lp) < 0) /* close Plotter */ - { - fprintf (stderr, "Couldn't close Plotter\n"); - } - - pl_deletepl_r(chart->lp); + for (i = 0 ; i < geom->n_datasets; ++i) + free (geom->dataset[i]); + free (geom->dataset); +} - pl_deleteplparams(chart->pl_params); +void +chart_draw (const struct chart *chart, cairo_t *cr, + struct chart_geometry *geom) +{ + chart->class->draw (chart, cr, geom); +} - d = outp_drivers (NULL); - d->class->finalise_chart(d, chart); +char * +chart_draw_png (const struct chart *chart, const char *file_name_template, + int number) +{ + const int width = 640; + const int length = 480; + + struct chart_geometry geom; + cairo_surface_t *surface; + cairo_status_t status; + const char *number_pos; + char *file_name; + cairo_t *cr; + + number_pos = strchr (file_name_template, '#'); + if (number_pos != NULL) + file_name = xasprintf ("%.*s%d%s", (int) (number_pos - file_name_template), + file_name_template, number, number_pos + 1); + else + file_name = xstrdup (file_name_template); + + surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, length); + cr = cairo_create (surface); + + cairo_translate (cr, 0.0, length); + cairo_scale (cr, 1.0, -1.0); + + cairo_save (cr); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_rectangle (cr, 0, 0, width, length); + cairo_fill (cr); + cairo_restore (cr); + + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + + chart_geometry_init (cr, &geom, width, length); + chart_draw (chart, cr, &geom); + chart_geometry_free (cr, &geom); + + status = cairo_surface_write_to_png (surface, file_name); + if (status != CAIRO_STATUS_SUCCESS) + error (0, 0, _("writing output file \"%s\": %s"), + file_name, cairo_status_to_string (status)); + + cairo_destroy (cr); + cairo_surface_destroy (surface); + + return file_name; +} - for (i = 0 ; i < chart->n_datasets; ++i) - free (chart->dataset[i]); - free (chart->dataset); - free(chart); +struct chart * +chart_ref (const struct chart *chart_) +{ + struct chart *chart = CONST_CAST (struct chart *, chart_); + chart->ref_cnt++; + return chart; } void -chart_init_separate (struct chart *ch, const char *type, - const char *file_name_tmpl, int number) +chart_unref (struct chart *chart) { - FILE *fp; - int number_pos; - - number_pos = strchr (file_name_tmpl, '#') - file_name_tmpl; - ch->file_name = xasprintf ("%.*s%d%s", - number_pos, file_name_tmpl, - number, - file_name_tmpl + number_pos + 1); - fp = fopen (ch->file_name, "wb"); - if (fp == NULL) + if (chart != NULL) { - error (0, errno, _("creating \"%s\""), ch->file_name); - free (ch->file_name); - ch->file_name = NULL; - return; + assert (chart->ref_cnt > 0); + if (--chart->ref_cnt == 0) + chart->class->destroy (chart); } - - ch->pl_params = pl_newplparams (); - ch->lp = pl_newpl_r (type, 0, fp, stderr, ch->pl_params); } void -chart_finalise_separate (struct chart *ch) +chart_submit (struct chart *chart) { - free (ch->file_name); +#ifdef HAVE_CAIRO + struct outp_driver *d; + + for (d = outp_drivers (NULL); d; d = outp_drivers (d)) + if (d->class->output_chart != NULL) + d->class->output_chart (d, chart); +#endif + + chart_unref (chart); } diff --git a/src/output/chart.h b/src/output/chart.h index 4da12ecf..d6b9b3d4 100644 --- a/src/output/chart.h +++ b/src/output/chart.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,85 +14,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include -#include -#include -#include -#include -#include -#include +#ifndef OUTPUT_CHART_H +#define OUTPUT_CHART_H 1 -#include -#include -#include "manager.h" -#include "output.h" +#include -#include "xalloc.h" +struct chart; -#ifndef CHART_H -#define CHART_H +struct chart *chart_ref (const struct chart *); +void chart_unref (struct chart *); -#ifndef NO_CHARTS -#include -#endif +void chart_submit (struct chart *); -struct chart { - -#ifndef NO_CHARTS - plPlotter *lp ; - plPlotterParams *pl_params; -#else - void *lp; -#endif - char *file_name; - FILE *file; - - /* The geometry of the chart - See diagram at the foot of this file. - */ - - int data_top ; - int data_right ; - int data_bottom; - int data_left ; - - int abscissa_top; - - int ordinate_right ; - - int title_bottom ; - - int legend_left ; - int legend_right ; - const char **dataset; - int n_datasets; - - - /* Default font size for the plot (if zero, then use plotter default) */ - int font_size; - - char fill_colour[10]; - - /* Stuff Particular to Cartesians (and Boxplots ) */ - double ordinate_scale; - double abscissa_scale; - double x_min; - double x_max; - double y_min; - double y_max; - bool in_path; -}; - - - -struct chart * chart_create(void); -void chart_submit(struct chart *ch); - -/* Helper functions for output drivers that put each chart into a - separate file. */ -void chart_init_separate (struct chart *, const char *type, - const char *file_name_tmpl, int number); - -void chart_finalise_separate (struct chart *); - -#endif +#endif /* output/chart.h */ diff --git a/src/output/charts/Makefile b/src/output/charts/Makefile deleted file mode 100644 index c1a052e8..00000000 --- a/src/output/charts/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - $(MAKE) -C /home/res/jmd/PSPP/pspp diff --git a/src/output/charts/automake.mk b/src/output/charts/automake.mk deleted file mode 100644 index ab0ff510..00000000 --- a/src/output/charts/automake.mk +++ /dev/null @@ -1,34 +0,0 @@ -## Process this file with automake to produce Makefile.in -*- makefile -*- - -noinst_LTLIBRARIES += src/output/charts/libcharts.la - -chart_sources = \ - src/output/charts/barchart.c \ - src/output/charts/barchart.h \ - src/output/charts/box-whisker.c \ - src/output/charts/box-whisker.h \ - src/output/charts/cartesian.c \ - src/output/charts/cartesian.h \ - src/output/charts/piechart.c \ - src/output/charts/piechart.h \ - src/output/charts/plot-chart.h \ - src/output/charts/plot-chart.c \ - src/output/charts/plot-hist.c \ - src/output/charts/plot-hist.h - -if WITHCHARTS -src_output_charts_libcharts_la_SOURCES = \ - $(chart_sources) - -EXTRA_DIST += src/output/charts/dummy-chart.c -else -src_output_charts_libcharts_la_SOURCES = \ - src/output/charts/dummy-chart.c - -EXTRA_DIST += $(chart_sources) - -AM_CPPFLAGS += -DNO_CHARTS - -endif - -EXTRA_DIST += src/output/charts/OChangeLog diff --git a/src/output/charts/barchart.c b/src/output/charts/barchart.c deleted file mode 100644 index f3b10011..00000000 --- a/src/output/charts/barchart.c +++ /dev/null @@ -1,252 +0,0 @@ -/* PSPP - a program for statistical analysis. - Copyright (C) 2004, 2009 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - - -#include - -#include -#include -#include -#include -#include -#include -#include - -#define CATAGORIES 6 -#define SUB_CATAGORIES 3 - -static const double x_min = 0; -static const double x_max = 15.0; - -static const char *cat_labels[] = - { - "Age", - "Intelligence", - "Wealth", - "Emotional", - "cat 5", - "cat 6", - "cat 7", - "cat 8", - "cat 9", - "cat 10", - "cat 11" - }; - - - - -/* Subcatagories */ -static const double data1[] = -{ - 28,83, - 34, - 29,13, - 9,4, - 3,3, - 2,0, - 1,0, - 0, - 1,1 -}; - - -static const double data2[] = -{ - 45,13, - 9,4, - 3,43, - 2,0, - 1,20, - 0,0, - 1,1, - 0,0 -}; - -static const double data3[] = - { - 23,18, - 0, 45,23, 9, 40, 24,4, 8 - }; - - -static const char subcat_name[]="Gender"; - - -struct subcat { - const double *data; - const char *label; -}; - -static const struct subcat sub_catagory[SUB_CATAGORIES] = - { - {data1, "male"}, - {data2, "female"}, - {data3, "47xxy"} - }; - - - -static const double y_min = 0; -static const double y_max = 120.0; -static const double y_tick = 20.0; - - - -static void write_legend(struct chart *chart) ; - - -void -draw_barchart(struct chart *ch, const char *title, - const char *xlabel, const char *ylabel, enum bar_opts opt) -{ - double d; - int i; - - double interval_size = fabs(ch->data_right - ch->data_left) / ( CATAGORIES ); - - double bar_width = interval_size / 1.1 ; - - double ordinate_scale = fabs(ch->data_top - ch->data_bottom) / - fabs(y_max - y_min) ; - - if ( opt != BAR_STACKED ) - bar_width /= SUB_CATAGORIES; - - /* Move to data bottom-left */ - pl_move_r(ch->lp, ch->data_left, ch->data_bottom); - - pl_savestate_r(ch->lp); - pl_filltype_r(ch->lp,1); - - /* Draw the data */ - for (i = 0 ; i < CATAGORIES ; ++i ) - { - int sc; - double ystart=0.0; - double x = i * interval_size; - - pl_savestate_r(ch->lp); - - draw_tick (ch, TICK_ABSCISSA, x + (interval_size/2 ), "%s", - cat_labels[i]); - - for(sc = 0 ; sc < SUB_CATAGORIES ; ++sc ) - { - - pl_savestate_r(ch->lp); - pl_fillcolorname_r(ch->lp,data_colour[sc % N_CHART_COLOURS]); - - switch ( opt ) - { - case BAR_GROUPED: - pl_fboxrel_r(ch->lp, - x + (sc * bar_width ), 0, - x + (sc + 1) * bar_width, - sub_catagory[sc].data[i] * ordinate_scale ); - break; - - - case BAR_STACKED: - - pl_fboxrel_r(ch->lp, - x, ystart, - x + bar_width, - ystart + sub_catagory[sc].data[i] * ordinate_scale ); - - ystart += sub_catagory[sc].data[i] * ordinate_scale ; - - break; - - default: - break; - } - pl_restorestate_r(ch->lp); - } - - pl_restorestate_r(ch->lp); - } - pl_restorestate_r(ch->lp); - - for ( d = y_min; d <= y_max ; d += y_tick ) - { - - draw_tick (ch, TICK_ORDINATE, - (d - y_min ) * ordinate_scale, "%g", d); - - } - - /* Write the abscissa label */ - pl_move_r(ch->lp,ch->data_left, ch->abscissa_top); - pl_alabel_r(ch->lp,0,'t',xlabel); - - - /* Write the ordinate label */ - pl_savestate_r(ch->lp); - pl_move_r(ch->lp,ch->data_bottom, ch->ordinate_right); - pl_textangle_r(ch->lp,90); - pl_alabel_r(ch->lp,0,0,ylabel); - pl_restorestate_r(ch->lp); - - - chart_write_title(ch, "%s", title); - - write_legend(ch); - - -} - - - - - -static void -write_legend(struct chart *chart) -{ - int sc; - - pl_savestate_r(chart->lp); - - pl_filltype_r(chart->lp,1); - - pl_move_r(chart->lp, chart->legend_left, - chart->data_bottom + chart->font_size * SUB_CATAGORIES * 1.5); - - pl_alabel_r(chart->lp,0,'b',subcat_name); - - for (sc = 0 ; sc < SUB_CATAGORIES ; ++sc ) - { - pl_fmove_r(chart->lp, - chart->legend_left, - chart->data_bottom + chart->font_size * sc * 1.5); - - pl_savestate_r(chart->lp); - pl_fillcolorname_r(chart->lp,data_colour[sc]); - pl_fboxrel_r (chart->lp, - 0,0, - chart->font_size, chart->font_size); - pl_restorestate_r(chart->lp); - - pl_fmove_r(chart->lp, - chart->legend_left + chart->font_size * 1.5, - chart->data_bottom + chart->font_size * sc * 1.5); - - pl_alabel_r(chart->lp,'l','b',sub_catagory[sc].label); - } - - - pl_restorestate_r(chart->lp); -} diff --git a/src/output/charts/barchart.h b/src/output/charts/barchart.h deleted file mode 100644 index 09832726..00000000 --- a/src/output/charts/barchart.h +++ /dev/null @@ -1,31 +0,0 @@ -/* PSPP - a program for statistical analysis. - Copyright (C) 2004 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef BARCHART_H -#define BARCHART_H - -#include - -enum bar_opts { - BAR_GROUPED = 0, - BAR_STACKED, - BAR_RANGE -}; - -void draw_barchart(struct chart *ch, const char *title, - const char *xlabel, const char *ylabel, enum bar_opts opt); - -#endif diff --git a/src/output/charts/box-whisker.c b/src/output/charts/box-whisker.c deleted file mode 100644 index 33c445b0..00000000 --- a/src/output/charts/box-whisker.c +++ /dev/null @@ -1,184 +0,0 @@ -/* PSPP - a program for statistical analysis. - Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - - -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include - -/* Draw a box-and-whiskers plot -*/ - -/* Draw an OUTLIER on the plot CH - * at CENTRELINE - */ -static void -draw_case (struct chart *ch, double centreline, - const struct outlier *outlier) -{ - -#define MARKER_CIRCLE 4 -#define MARKER_STAR 3 - - pl_fmarker_r(ch->lp, - centreline, - ch->data_bottom + (outlier->value - ch->y_min) * ch->ordinate_scale, - outlier->extreme ? MARKER_STAR : MARKER_CIRCLE, - 20); - - pl_moverel_r(ch->lp, 10,0); - - pl_alabel_r(ch->lp, 'l', 'c', ds_cstr (&outlier->label)); -} - - -void -boxplot_draw_boxplot (struct chart *ch, - double box_centre, - double box_width, - const struct box_whisker *bw, - const char *name) -{ - double whisker[2]; - double hinge[3]; - struct ll *ll; - - const struct ll_list *outliers; - - const double box_left = box_centre - box_width / 2.0; - - const double box_right = box_centre + box_width / 2.0; - - double box_bottom ; - double box_top ; - double bottom_whisker ; - double top_whisker ; - - box_whisker_whiskers (bw, whisker); - box_whisker_hinges (bw, hinge); - - box_bottom = ch->data_bottom + (hinge[0] - ch->y_min ) * ch->ordinate_scale; - - box_top = ch->data_bottom + (hinge[2] - ch->y_min ) * ch->ordinate_scale; - - bottom_whisker = ch->data_bottom + (whisker[0] - ch->y_min) * - ch->ordinate_scale; - - top_whisker = ch->data_bottom + (whisker[1] - ch->y_min) * ch->ordinate_scale; - - pl_savestate_r(ch->lp); - - /* Draw the box */ - pl_savestate_r (ch->lp); - pl_fillcolorname_r (ch->lp, ch->fill_colour); - pl_filltype_r (ch->lp,1); - pl_fbox_r (ch->lp, - box_left, - box_bottom, - box_right, - box_top); - - pl_restorestate_r (ch->lp); - - /* Draw the median */ - pl_savestate_r (ch->lp); - pl_linewidth_r (ch->lp, 5); - pl_fline_r (ch->lp, - box_left, - ch->data_bottom + (hinge[1] - ch->y_min) * ch->ordinate_scale, - box_right, - ch->data_bottom + (hinge[1] - ch->y_min) * ch->ordinate_scale); - pl_restorestate_r (ch->lp); - - /* Draw the bottom whisker */ - pl_fline_r (ch->lp, - box_left, - bottom_whisker, - box_right, - bottom_whisker); - - /* Draw top whisker */ - pl_fline_r (ch->lp, - box_left, - top_whisker, - box_right, - top_whisker); - - - /* Draw centre line. - (bottom half) */ - pl_fline_r (ch->lp, - box_centre, bottom_whisker, - box_centre, box_bottom); - - /* (top half) */ - pl_fline_r (ch->lp, - box_centre, top_whisker, - box_centre, box_top); - - outliers = box_whisker_outliers (bw); - for (ll = ll_head (outliers); - ll != ll_null (outliers); ll = ll_next (ll)) - { - const struct outlier *outlier = ll_data (ll, struct outlier, ll); - draw_case (ch, box_centre, outlier); - } - - /* Draw tick mark on x axis */ - draw_tick(ch, TICK_ABSCISSA, box_centre - ch->data_left, "%s", name); - - pl_restorestate_r(ch->lp); -} - -void -boxplot_draw_yscale (struct chart *ch, double y_max, double y_min) -{ - double y_tick; - double d; - - if ( !ch ) - return ; - - ch->y_max = y_max; - ch->y_min = y_min; - - y_tick = chart_rounded_tick (fabs(ch->y_max - ch->y_min) / 5.0); - - ch->y_min = (ceil( ch->y_min / y_tick ) - 1.0 ) * y_tick; - - ch->y_max = ( floor( ch->y_max / y_tick ) + 1.0 ) * y_tick; - - ch->ordinate_scale = fabs(ch->data_top - ch->data_bottom) - / fabs(ch->y_max - ch->y_min) ; - - /* Move to data bottom-left */ - pl_move_r(ch->lp, - ch->data_left, ch->data_bottom); - - for ( d = ch->y_min; d <= ch->y_max ; d += y_tick ) - { - draw_tick (ch, TICK_ORDINATE, (d - ch->y_min ) * ch->ordinate_scale, "%g", d); - } -} diff --git a/src/output/charts/box-whisker.h b/src/output/charts/box-whisker.h deleted file mode 100644 index 7b2c4b8f..00000000 --- a/src/output/charts/box-whisker.h +++ /dev/null @@ -1,32 +0,0 @@ -/* PSPP - a program for statistical analysis. - Copyright (C) 2004 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef BOX_WHISKER_H -#define BOX_WHISKER_H - -struct chart ; -struct box_whisker; - -void boxplot_draw_boxplot (struct chart *ch, - double box_centre, - double box_width, - const struct box_whisker *w, - const char *name); - - -void boxplot_draw_yscale (struct chart *ch , double y_max, double y_min); - -#endif diff --git a/src/output/charts/boxplot.c b/src/output/charts/boxplot.c new file mode 100644 index 00000000..015385e7 --- /dev/null +++ b/src/output/charts/boxplot.c @@ -0,0 +1,263 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Draw a box-and-whiskers plot +*/ + +struct box + { + struct box_whisker *bw; + char *label; + }; + +struct boxplot + { + struct chart chart; + double y_min; + double y_max; + char *title; + struct box *boxes; + size_t n_boxes, boxes_allocated; + }; + +static const struct chart_class boxplot_chart_class; + +struct boxplot * +boxplot_create (double y_min, double y_max, const char *title) +{ + struct boxplot *boxplot = xmalloc (sizeof *boxplot); + chart_init (&boxplot->chart, &boxplot_chart_class); + boxplot->y_min = y_min; + boxplot->y_max = y_max; + boxplot->title = xstrdup (title); + boxplot->boxes = NULL; + boxplot->n_boxes = boxplot->boxes_allocated = 0; + return boxplot; +} + +void +boxplot_add_box (struct boxplot *boxplot, + struct box_whisker *bw, const char *label) +{ + struct box *box; + if (boxplot->n_boxes >= boxplot->boxes_allocated) + boxplot->boxes = x2nrealloc (boxplot->boxes, &boxplot->boxes_allocated, + sizeof *boxplot->boxes); + box = &boxplot->boxes[boxplot->n_boxes++]; + box->bw = bw; + box->label = xstrdup (label); +} + +struct chart * +boxplot_get_chart (struct boxplot *boxplot) +{ + return &boxplot->chart; +} + +/* Draw an OUTLIER on the plot CH + * at CENTRELINE + */ +static void +draw_case (cairo_t *cr, const struct chart_geometry *geom, double centreline, + const struct outlier *outlier) +{ + double y = geom->data_bottom + (outlier->value - geom->y_min) * geom->ordinate_scale; + chart_draw_marker (cr, centreline, y, + outlier->extreme ? MARKER_ASTERISK : MARKER_CIRCLE, + 20); + + cairo_move_to (cr, centreline + 10, y); + chart_label (cr, 'l', 'c', geom->font_size, ds_cstr (&outlier->label)); +} + +static void +boxplot_draw_box (cairo_t *cr, const struct chart_geometry *geom, + double box_centre, + double box_width, + const struct box_whisker *bw, + const char *name) +{ + double whisker[2]; + double hinge[3]; + struct ll *ll; + + const struct ll_list *outliers; + + const double box_left = box_centre - box_width / 2.0; + + const double box_right = box_centre + box_width / 2.0; + + double box_bottom ; + double box_top ; + double bottom_whisker ; + double top_whisker ; + + box_whisker_whiskers (bw, whisker); + box_whisker_hinges (bw, hinge); + + box_bottom = geom->data_bottom + (hinge[0] - geom->y_min ) * geom->ordinate_scale; + + box_top = geom->data_bottom + (hinge[2] - geom->y_min ) * geom->ordinate_scale; + + bottom_whisker = geom->data_bottom + (whisker[0] - geom->y_min) * + geom->ordinate_scale; + + top_whisker = geom->data_bottom + (whisker[1] - geom->y_min) * geom->ordinate_scale; + + /* Draw the box */ + cairo_rectangle (cr, + box_left, + box_bottom, + box_right - box_left, + box_top - box_bottom); + cairo_save (cr); + cairo_set_source_rgb (cr, + geom->fill_colour.red / 255.0, + geom->fill_colour.green / 255.0, + geom->fill_colour.blue / 255.0); + cairo_fill (cr); + cairo_restore (cr); + cairo_stroke (cr); + + /* Draw the median */ + cairo_save (cr); + cairo_set_line_width (cr, cairo_get_line_width (cr) * 5); + cairo_move_to (cr, + box_left, + geom->data_bottom + (hinge[1] - geom->y_min) * geom->ordinate_scale); + cairo_line_to (cr, + box_right, + geom->data_bottom + (hinge[1] - geom->y_min) * geom->ordinate_scale); + cairo_stroke (cr); + cairo_restore (cr); + + /* Draw the bottom whisker */ + cairo_move_to (cr, box_left, bottom_whisker); + cairo_line_to (cr, box_right, bottom_whisker); + cairo_stroke (cr); + + /* Draw top whisker */ + cairo_move_to (cr, box_left, top_whisker); + cairo_line_to (cr, box_right, top_whisker); + cairo_stroke (cr); + + /* Draw centre line. + (bottom half) */ + cairo_move_to (cr, box_centre, bottom_whisker); + cairo_line_to (cr, box_centre, box_bottom); + cairo_stroke (cr); + + /* (top half) */ + cairo_move_to (cr, box_centre, top_whisker); + cairo_line_to (cr, box_centre, box_top); + cairo_stroke (cr); + + outliers = box_whisker_outliers (bw); + for (ll = ll_head (outliers); + ll != ll_null (outliers); ll = ll_next (ll)) + { + const struct outlier *outlier = ll_data (ll, struct outlier, ll); + draw_case (cr, geom, box_centre, outlier); + } + + /* Draw tick mark on x axis */ + draw_tick(cr, geom, TICK_ABSCISSA, box_centre - geom->data_left, "%s", name); +} + +static void +boxplot_draw_yscale (cairo_t *cr, struct chart_geometry *geom, + double y_max, double y_min) +{ + double y_tick; + double d; + + geom->y_max = y_max; + geom->y_min = y_min; + + y_tick = chart_rounded_tick (fabs (geom->y_max - geom->y_min) / 5.0); + + geom->y_min = (ceil (geom->y_min / y_tick) - 1.0) * y_tick; + + geom->y_max = (floor (geom->y_max / y_tick) + 1.0) * y_tick; + + geom->ordinate_scale = (fabs (geom->data_top - geom->data_bottom) + / fabs (geom->y_max - geom->y_min)); + + for (d = geom->y_min; d <= geom->y_max; d += y_tick) + draw_tick (cr, geom, TICK_ORDINATE, + (d - geom->y_min) * geom->ordinate_scale, "%g", d); +} + +static void +boxplot_chart_draw (const struct chart *chart, cairo_t *cr, + struct chart_geometry *geom) +{ + const struct boxplot *boxplot = UP_CAST (chart, struct boxplot, chart); + double box_width; + size_t i; + + boxplot_draw_yscale (cr, geom, boxplot->y_max, boxplot->y_min); + chart_write_title (cr, geom, "%s", boxplot->title); + + box_width = (geom->data_right - geom->data_left) / boxplot->n_boxes / 2.0; + for (i = 0; i < boxplot->n_boxes; i++) + { + const struct box *box = &boxplot->boxes[i]; + const double box_centre = (i * 2 + 1) * box_width + geom->data_left; + boxplot_draw_box (cr, geom, box_centre, box_width, box->bw, box->label); + } +} + +static void +boxplot_chart_destroy (struct chart *chart) +{ + struct boxplot *boxplot = UP_CAST (chart, struct boxplot, chart); + size_t i; + + free (boxplot->title); + for (i = 0; i < boxplot->n_boxes; i++) + { + struct box *box = &boxplot->boxes[i]; + struct statistic *statistic = &box->bw->parent.parent; + statistic->destroy (statistic); + free (box->label); + } + free (boxplot->boxes); + free (boxplot); +} + +static const struct chart_class boxplot_chart_class = + { + boxplot_chart_draw, + boxplot_chart_destroy + }; diff --git a/src/output/charts/boxplot.h b/src/output/charts/boxplot.h new file mode 100644 index 00000000..1e9d0070 --- /dev/null +++ b/src/output/charts/boxplot.h @@ -0,0 +1,27 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2004, 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef OUTPUT_CHARTS_BOXPLOT_H +#define OUTPUT_CHARTS_BOXPLOT_H 1 + +struct box_whisker; + +struct boxplot *boxplot_create (double y_min, double y_max, const char *title); +void boxplot_add_box (struct boxplot *, + struct box_whisker *, const char *label); +struct chart *boxplot_get_chart (struct boxplot *); + +#endif /* output/charts/boxplot.h */ diff --git a/src/output/charts/cartesian.c b/src/output/charts/cartesian.c index cb2f346b..eabcf516 100644 --- a/src/output/charts/cartesian.c +++ b/src/output/charts/cartesian.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,86 +17,76 @@ #include +#include + +#include #include #include #include - +#include #include -#include #include +#include "xalloc.h" /* Start a new vector called NAME */ void -chart_vector_start (struct chart *ch, const char *name) +chart_vector_start (cairo_t *cr, struct chart_geometry *geom, const char *name) { - if ( ! ch ) - return ; + const struct chart_colour *colour; - pl_savestate_r (ch->lp); + cairo_save (cr); - pl_colorname_r (ch->lp, data_colour [ch->n_datasets % N_CHART_COLOURS]); + colour = &data_colour[geom->n_datasets % N_CHART_COLOURS]; + cairo_set_source_rgb (cr, + colour->red / 255.0, + colour->green / 255.0, + colour->blue / 255.0); - ch->n_datasets++; - ch->dataset = xrealloc (ch->dataset, ch->n_datasets * sizeof (*ch->dataset)); + geom->n_datasets++; + geom->dataset = xrealloc (geom->dataset, + geom->n_datasets * sizeof (*geom->dataset)); - ch->dataset[ch->n_datasets - 1] = strdup (name); + geom->dataset[geom->n_datasets - 1] = strdup (name); } /* Plot a data point */ void -chart_datum (struct chart *ch, int dataset UNUSED, double x, double y) +chart_datum (cairo_t *cr, const struct chart_geometry *geom, + int dataset UNUSED, double x, double y) { - if ( ! ch ) - return ; - - { - const double x_pos = - (x - ch->x_min) * ch->abscissa_scale + ch->data_left ; + double x_pos = (x - geom->x_min) * geom->abscissa_scale + geom->data_left; + double y_pos = (y - geom->y_min) * geom->ordinate_scale + geom->data_bottom; - const double y_pos = - (y - ch->y_min) * ch->ordinate_scale + ch->data_bottom ; - - pl_savestate_r(ch->lp); - - pl_fmarker_r(ch->lp, x_pos, y_pos, 6, 15); - - pl_restorestate_r(ch->lp); - } + chart_draw_marker (cr, x_pos, y_pos, MARKER_SQUARE, 15); } void -chart_vector_end (struct chart *ch) +chart_vector_end (cairo_t *cr, struct chart_geometry *geom) { - pl_endpath_r (ch->lp); - pl_colorname_r (ch->lp, "black"); - ch->in_path = false; - pl_restorestate_r (ch->lp); + cairo_stroke (cr); + cairo_restore (cr); + geom->in_path = false; } /* Plot a data point */ void -chart_vector (struct chart *ch, double x, double y) +chart_vector (cairo_t *cr, struct chart_geometry *geom, double x, double y) { - if ( ! ch ) - return ; - - { - const double x_pos = - (x - ch->x_min) * ch->abscissa_scale + ch->data_left ; - - const double y_pos = - (y - ch->y_min) * ch->ordinate_scale + ch->data_bottom ; - - if ( ch->in_path) - pl_fcont_r (ch->lp, x_pos, y_pos); - else - { - pl_fmove_r (ch->lp, x_pos, y_pos); - ch->in_path = true; - } - } + const double x_pos = + (x - geom->x_min) * geom->abscissa_scale + geom->data_left ; + + const double y_pos = + (y - geom->y_min) * geom->ordinate_scale + geom->data_bottom ; + + if (geom->in_path) + cairo_line_to (cr, x_pos, y_pos); + else + { + cairo_move_to (cr, x_pos, y_pos); + geom->in_path = true; + } } @@ -107,20 +97,17 @@ chart_vector (struct chart *ch, double x, double y) y axis otherwise the x axis */ void -chart_line (struct chart *ch, double slope, double intercept, +chart_line(cairo_t *cr, const struct chart_geometry *geom, + double slope, double intercept, double limit1, double limit2, enum CHART_DIM lim_dim) { double x1, y1; - double x2, y2 ; - - if ( ! ch ) - return ; - + double x2, y2; if ( lim_dim == CHART_DIM_Y ) { - x1 = ( limit1 - intercept ) / slope ; - x2 = ( limit2 - intercept ) / slope ; + x1 = ( limit1 - intercept ) / slope; + x2 = ( limit2 - intercept ) / slope; y1 = limit1; y2 = limit2; } @@ -132,14 +119,12 @@ chart_line (struct chart *ch, double slope, double intercept, y2 = slope * x2 + intercept; } - y1 = (y1 - ch->y_min) * ch->ordinate_scale + ch->data_bottom ; - y2 = (y2 - ch->y_min) * ch->ordinate_scale + ch->data_bottom ; - x1 = (x1 - ch->x_min) * ch->abscissa_scale + ch->data_left ; - x2 = (x2 - ch->x_min) * ch->abscissa_scale + ch->data_left ; - - pl_savestate_r(ch->lp); - - pl_fline_r(ch->lp, x1, y1, x2, y2); + y1 = (y1 - geom->y_min) * geom->ordinate_scale + geom->data_bottom; + y2 = (y2 - geom->y_min) * geom->ordinate_scale + geom->data_bottom; + x1 = (x1 - geom->x_min) * geom->abscissa_scale + geom->data_left; + x2 = (x2 - geom->x_min) * geom->abscissa_scale + geom->data_left; - pl_restorestate_r(ch->lp); + cairo_move_to (cr, x1, y1); + cairo_line_to (cr, x2, y2); + cairo_stroke (cr); } diff --git a/src/output/charts/cartesian.h b/src/output/charts/cartesian.h index 0874b9cc..3c21db6e 100644 --- a/src/output/charts/cartesian.h +++ b/src/output/charts/cartesian.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,9 @@ #ifndef CARTESIAN_H #define CARTESIAN_H +#include +#include +#include enum CHART_DIM { @@ -26,20 +29,24 @@ enum CHART_DIM CHART_DIM_Y }; +struct chart_geometry; -void chart_vector_start (struct chart *ch, const char *name); -void chart_vector (struct chart *ch, double x, double y); -void chart_vector_end (struct chart *ch); +void chart_vector_start (cairo_t *, struct chart_geometry *, + const char *name); +void chart_vector_end (cairo_t *, struct chart_geometry *); +void chart_vector (cairo_t *, struct chart_geometry *, double x, double y); /* Plot a data point */ -void chart_datum (struct chart *ch, int dataset UNUSED, double x, double y); +void chart_datum(cairo_t *, const struct chart_geometry *, + int dataset UNUSED, double x, double y); /* Draw a line with slope SLOPE and intercept INTERCEPT. between the points limit1 and limit2. If lim_dim is CHART_DIM_Y then the limit{1,2} are on the y axis otherwise the x axis */ -void chart_line (struct chart *ch, double slope, double intercept, +void chart_line(cairo_t *, const struct chart_geometry *, + double slope, double intercept, double limit1, double limit2, enum CHART_DIM lim_dim); diff --git a/src/output/charts/dummy-chart.c b/src/output/charts/dummy-chart.c deleted file mode 100644 index e00a41f7..00000000 --- a/src/output/charts/dummy-chart.c +++ /dev/null @@ -1,139 +0,0 @@ -/* PSPP - a program for statistical analysis. - Copyright (C) 2005 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - - -/* Stubs for plotting routines. - This module is linked only when charts are not supported */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef NO_CHARTS -#error This file should be used only when compiling without charts. -#endif - -void -chart_write_legend (struct chart *ch UNUSED) -{ -} - -void -chart_vector (struct chart *ch UNUSED, double x UNUSED, double y UNUSED) -{ -} - -void -chart_vector_end (struct chart *ch UNUSED) -{ -} - -void -chart_vector_start (struct chart *ch UNUSED, const char *name UNUSED) -{ -} - -void -chart_write_title (struct chart *chart UNUSED, const char *title UNUSED, ...) -{ -} - - -void -chart_write_xscale (struct chart *ch UNUSED, - double min UNUSED, double max UNUSED, int ticks UNUSED) -{ -} - - -void -chart_write_yscale (struct chart *ch UNUSED UNUSED, - double smin UNUSED, double smax UNUSED, int ticks UNUSED) -{ -} - - -void -chart_write_xlabel (struct chart *ch UNUSED, const char *label UNUSED) -{ -} - -void -chart_write_ylabel (struct chart *ch UNUSED, const char *label UNUSED) -{ -} - - -void -chart_line (struct chart *ch UNUSED, - double slope UNUSED, double intercept UNUSED, - double limit1 UNUSED, double limit2 UNUSED, - enum CHART_DIM lim_dim UNUSED) -{ -} - - -void -chart_datum (struct chart *ch UNUSED, int dataset UNUSED UNUSED, - double x UNUSED, double y UNUSED) -{ -} - -void -histogram_plot (const struct histogram *hist UNUSED, - const char *label UNUSED, - const struct moments1 *m UNUSED) -{ -} - -void -histogram_plot_n (const struct histogram *hist UNUSED, - const char *label UNUSED, - double n UNUSED, double mean UNUSED, double stddev UNUSED, - bool show_normal UNUSED) -{ -} - - -void -boxplot_draw_yscale (struct chart *ch UNUSED, - double y_max UNUSED, double y_min UNUSED) -{ -} - -void -boxplot_draw_boxplot (struct chart *ch UNUSED, - double box_centre UNUSED, - double box_width UNUSED, - const struct box_whisker *w UNUSED, - const char *name UNUSED) -{ -} - - - - -void -piechart_plot (const char *title UNUSED, - const struct slice *slices UNUSED, int n_slices UNUSED) -{ -} diff --git a/src/output/charts/np-plot.c b/src/output/charts/np-plot.c new file mode 100644 index 00000000..c077b872 --- /dev/null +++ b/src/output/charts/np-plot.c @@ -0,0 +1,196 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gl/minmax.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +/* An NP or DNP plot. */ +struct np_plot_chart + { + struct chart chart; + char *label; + struct casereader *data; + + /* Copied directly from struct np. */ + double y_min, y_max; + double dns_min, dns_max; + + /* Calculated. */ + double slope, intercept; + double y_first, y_last; + double x_lower, x_upper; + double slack; + }; + +static const struct chart_class np_plot_chart_class; +static const struct chart_class dnp_plot_chart_class; + +static struct chart * +make_np_plot (const struct chart_class *class, + const struct np *np, const struct casereader *reader, + const char *label) +{ + struct np_plot_chart *npp; + + if (np->n < 1.0) + return NULL; + + npp = xmalloc (sizeof *npp); + chart_init (&npp->chart, class); + npp->label = xstrdup (label); + npp->data = casereader_clone (reader); + npp->y_min = np->y_min; + npp->y_max = np->y_max; + npp->dns_min = np->dns_min; + npp->dns_max = np->dns_max; + + /* Slope and intercept of the ideal normal probability line. */ + npp->slope = 1.0 / np->stddev; + npp->intercept = -np->mean / np->stddev; + + npp->y_first = gsl_cdf_ugaussian_Pinv (1 / (np->n + 1)); + npp->y_last = gsl_cdf_ugaussian_Pinv (np->n / (np->n + 1)); + + /* Need to make sure that both the scatter plot and the ideal fit into the + plot. */ + npp->x_lower = MIN (np->y_min, (npp->y_first - npp->intercept) / npp->slope); + npp->x_upper = MAX (np->y_max, (npp->y_last - npp->intercept) / npp->slope); + npp->slack = (npp->x_upper - npp->x_lower) * 0.05; + + return &npp->chart; +} + +/* Creates and returns a normal probability plot corresponding to + the calculations in NP and the data in READER, and label the + plot with LABEL. The data in READER must have Y-values in + value index NP_IDX_Y and NS-values in value index NP_IDX_NS. + + Returns a null pointer if the data set is empty. + + The caller retains ownership of NP and READER. */ +struct chart * +np_plot_create (const struct np *np, const struct casereader *reader, + const char *label) +{ + return make_np_plot (&np_plot_chart_class, np, reader, label); +} + +/* Creates and returns a detrended normal probability plot + corresponding to the calculations in NP and the data in + READER, and label the plot with LABEL. The data in READER + must have Y-values in value index NP_IDX_Y and DNS-values in + value index NP_IDX_DNS. + + Returns a null pointer if the data set is empty. + + The caller retains ownership of NP and READER. */ +struct chart * +dnp_plot_create (const struct np *np, const struct casereader *reader, + const char *label) +{ + return make_np_plot (&dnp_plot_chart_class, np, reader, label); +} + +static void +np_plot_chart_draw (const struct chart *chart, cairo_t *cr, + struct chart_geometry *geom) +{ + const struct np_plot_chart *npp = UP_CAST (chart, struct np_plot_chart, + chart); + struct casereader *data; + struct ccase *c; + + chart_write_title (cr, geom, _("Normal Q-Q Plot of %s"), npp->label); + chart_write_xlabel (cr, geom, _("Observed Value")); + chart_write_ylabel (cr, geom, _("Expected Normal")); + chart_write_xscale (cr, geom, + npp->x_lower - npp->slack, + npp->x_upper + npp->slack, 5); + chart_write_yscale (cr, geom, npp->y_first, npp->y_last, 5); + + data = casereader_clone (npp->data); + for (; (c = casereader_read (data)) != NULL; case_unref (c)) + chart_datum (cr, geom, 0, + case_data_idx (c, NP_IDX_Y)->f, + case_data_idx (c, NP_IDX_NS)->f); + casereader_destroy (data); + + chart_line (cr, geom, npp->slope, npp->intercept, + npp->y_first, npp->y_last, CHART_DIM_Y); +} + +static void +dnp_plot_chart_draw (const struct chart *chart, cairo_t *cr, + struct chart_geometry *geom) +{ + const struct np_plot_chart *dnpp = UP_CAST (chart, struct np_plot_chart, + chart); + struct casereader *data; + struct ccase *c; + + chart_write_title (cr, geom, _("Detrended Normal Q-Q Plot of %s"), + dnpp->label); + chart_write_xlabel (cr, geom, _("Observed Value")); + chart_write_ylabel (cr, geom, _("Dev from Normal")); + chart_write_xscale (cr, geom, dnpp->y_min, dnpp->y_max, 5); + chart_write_yscale (cr, geom, dnpp->dns_min, dnpp->dns_max, 5); + + data = casereader_clone (dnpp->data); + for (; (c = casereader_read (data)) != NULL; case_unref (c)) + chart_datum (cr, geom, 0, case_data_idx (c, NP_IDX_Y)->f, + case_data_idx (c, NP_IDX_DNS)->f); + casereader_destroy (data); + + chart_line (cr, geom, 0, 0, dnpp->y_min, dnpp->y_max, CHART_DIM_X); +} + +static void +np_plot_chart_destroy (struct chart *chart) +{ + struct np_plot_chart *npp = UP_CAST (chart, struct np_plot_chart, chart); + casereader_destroy (npp->data); + free (npp->label); + free (npp); +} + +static const struct chart_class np_plot_chart_class = + { + np_plot_chart_draw, + np_plot_chart_destroy + }; + +static const struct chart_class dnp_plot_chart_class = + { + dnp_plot_chart_draw, + np_plot_chart_destroy + }; diff --git a/src/output/charts/np-plot.h b/src/output/charts/np-plot.h new file mode 100644 index 00000000..c9742359 --- /dev/null +++ b/src/output/charts/np-plot.h @@ -0,0 +1,28 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef OUTPUT_CHARTS_NP_PLOT_H +#define OUTPUT_CHARTS_NP_PLOT_H 1 + +struct casereader; +struct np; + +struct chart *np_plot_create (const struct np *, const struct casereader *, + const char *label); +struct chart *dnp_plot_create (const struct np *, const struct casereader *, + const char *label); + +#endif /* output/charts/np-plot.h */ diff --git a/src/output/charts/piechart.c b/src/output/charts/piechart.c index d7db80e9..935c6eb0 100644 --- a/src/output/charts/piechart.c +++ b/src/output/charts/piechart.c @@ -17,78 +17,101 @@ #include -#include +#include + #include +#include +#include #include #include - -#include -#include - -#include -#include #include +#include +#include +#include +#include #include "minmax.h" +struct piechart + { + struct chart chart; + char *title; + struct slice *slices; + int n_slices; + }; -/* Pie charts of course need to know Pi :) */ -#ifndef M_PI -#define M_PI ( 22.0 / 7.0 ) -#endif - - +static const struct chart_class piechart_class; /* Draw a single slice of the pie */ static void -draw_segment(struct chart *ch, +draw_segment(cairo_t *, double centre_x, double centre_y, double radius, double start_angle, double segment_angle, - const char *colour) ; + const struct chart_colour *) ; -/* Draw a piechart */ -void -piechart_plot(const char *title, const struct slice *slices, int n_slices) +/* Creates and returns a chart that will render a piechart with + the given TITLE and the N_SLICES described in SLICES. */ +struct chart * +piechart_create (const char *title, const struct slice *slices, int n_slices) { + struct piechart *pie; int i; - double total_magnetude=0; - - struct chart *ch; - double left_label; - double right_label; + pie = xmalloc (sizeof *pie); + chart_init (&pie->chart, &piechart_class); + pie->title = xstrdup (title); + pie->slices = xnmalloc (n_slices, sizeof *pie->slices); + for (i = 0; i < n_slices; i++) + { + const struct slice *src = &slices[i]; + struct slice *dst = &pie->slices[i]; - double centre_x; - double centre_y; + ds_init_string (&dst->label, &src->label); + dst->magnitude = src->magnitude; + } + pie->n_slices = n_slices; + return &pie->chart; +} +static void +piechart_draw (const struct chart *chart, cairo_t *cr, + struct chart_geometry *geom) +{ + const struct piechart *pie = UP_CAST (chart, struct piechart, chart); + double total_magnitude; + double left_label, right_label; + double centre_x, centre_y; double radius; + double angle; + int i; - ch = chart_create (); - if (ch == NULL) - return; + centre_x = (geom->data_right + geom->data_left) / 2.0 ; + centre_y = (geom->data_top + geom->data_bottom) / 2.0 ; - left_label = ch->data_left + (ch->data_right - ch->data_left)/10.0; - right_label = ch->data_right - (ch->data_right - ch->data_left)/10.0; - centre_x = (ch->data_right + ch->data_left ) / 2.0; - centre_y = (ch->data_top + ch->data_bottom ) / 2.0; - radius = MIN (5.0 / 12.0 * (ch->data_top - ch->data_bottom), - 1.0 / 4.0 * (ch->data_right - ch->data_left)); + left_label = geom->data_left + (geom->data_right - geom->data_left)/10.0; + right_label = geom->data_right - (geom->data_right - geom->data_left)/10.0; - chart_write_title(ch, "%s", title); + radius = MIN (5.0 / 12.0 * (geom->data_top - geom->data_bottom), + 1.0 / 4.0 * (geom->data_right - geom->data_left)); - for (i = 0 ; i < n_slices ; ++i ) - total_magnetude += slices[i].magnetude; + radius = MIN (5.0 / 12.0 * (geom->data_top - geom->data_bottom), + 1.0 / 4.0 * (geom->data_right - geom->data_left)); - for (i = 0 ; i < n_slices ; ++i ) - { - static double angle=0.0; + chart_write_title (cr, geom, "%s", pie->title); + total_magnitude = 0.0; + for (i = 0; i < pie->n_slices; i++) + total_magnitude += pie->slices[i].magnitude; + + angle = 0.0; + for (i = 0; i < pie->n_slices ; ++i ) + { const double segment_angle = - slices[i].magnetude / total_magnetude * 2 * M_PI ; + pie->slices[i].magnitude / total_magnitude * 2 * M_PI ; const double label_x = centre_x - radius * sin(angle + segment_angle/2.0); @@ -97,120 +120,78 @@ piechart_plot(const char *title, const struct slice *slices, int n_slices) radius * cos(angle + segment_angle/2.0); /* Fill the segment */ - draw_segment(ch, - centre_x, centre_y, radius, - angle, segment_angle, - data_colour[i % N_CHART_COLOURS]); + draw_segment (cr, + centre_x, centre_y, radius, + angle, segment_angle, + &data_colour[i % N_CHART_COLOURS]); /* Now add the labels */ if ( label_x < centre_x ) { - pl_line_r(ch->lp, label_x, label_y, - left_label, label_y ); - pl_moverel_r(ch->lp,0,5); - pl_alabel_r (ch->lp, 0, 0, ds_cstr (&slices[i].label)); + cairo_move_to (cr, label_x, label_y); + cairo_line_to (cr, left_label, label_y); + cairo_stroke (cr); + cairo_move_to (cr, left_label, label_y + 5); + chart_label (cr, 'l', 'x', geom->font_size, + ds_cstr (&pie->slices[i].label)); } else { - pl_line_r(ch->lp, - label_x, label_y, - right_label, label_y - ); - pl_moverel_r(ch->lp,0,5); - pl_alabel_r (ch->lp, 'r', 0, ds_cstr (&slices[i].label)); + cairo_move_to (cr, label_x, label_y); + cairo_line_to (cr, right_label, label_y); + cairo_stroke (cr); + cairo_move_to (cr, right_label, label_y + 5); + chart_label (cr, 'r', 'x', geom->font_size, + ds_cstr (&pie->slices[i].label)); } angle += segment_angle; - } /* Draw an outline to the pie */ - pl_filltype_r(ch->lp,0); - pl_fcircle_r (ch->lp, centre_x, centre_y, radius); - - chart_submit(ch); + cairo_arc (cr, centre_x, centre_y, radius, 0, 2 * M_PI); + cairo_stroke (cr); } +/* Draw a single slice of the pie */ static void -fill_segment(struct chart *ch, - double x0, double y0, - double radius, - double start_angle, double segment_angle) ; - - -/* Fill a segment with the current fill colour */ -static void -fill_segment(struct chart *ch, +draw_segment(cairo_t *cr, double x0, double y0, double radius, - double start_angle, double segment_angle) + double start_angle, double segment_angle, + const struct chart_colour *colour) { - - const double start_x = x0 - radius * sin(start_angle); - const double start_y = y0 + radius * cos(start_angle); - - const double stop_x = - x0 - radius * sin(start_angle + segment_angle); - - const double stop_y = - y0 + radius * cos(start_angle + segment_angle); - - assert(segment_angle <= 2 * M_PI); - assert(segment_angle >= 0); - - if ( segment_angle > M_PI ) - { - /* Then we must draw it in two halves */ - fill_segment(ch, x0, y0, radius, start_angle, segment_angle / 2.0 ); - fill_segment(ch, x0, y0, radius, start_angle + segment_angle / 2.0, - segment_angle / 2.0 ); - } - else - { - pl_move_r(ch->lp, x0, y0); - - pl_cont_r(ch->lp, stop_x, stop_y); - pl_cont_r(ch->lp, start_x, start_y); - - pl_arc_r(ch->lp, - x0, y0, - stop_x, stop_y, - start_x, start_y - ); - - pl_endpath_r(ch->lp); - } + cairo_move_to (cr, x0, y0); + cairo_arc (cr, x0, y0, radius, start_angle, start_angle + segment_angle); + cairo_line_to (cr, x0, y0); + cairo_save (cr); + cairo_set_source_rgb (cr, + colour->red / 255.0, + colour->green / 255.0, + colour->blue / 255.0); + cairo_fill_preserve (cr); + cairo_restore (cr); + cairo_stroke (cr); } - - -/* Draw a single slice of the pie */ static void -draw_segment(struct chart *ch, - double x0, double y0, - double radius, - double start_angle, double segment_angle, - const char *colour) +piechart_destroy (struct chart *chart) { - const double start_x = x0 - radius * sin(start_angle); - const double start_y = y0 + radius * cos(start_angle); - - pl_savestate_r(ch->lp); - - pl_savestate_r(ch->lp); - pl_colorname_r(ch->lp, colour); - - pl_pentype_r(ch->lp,1); - pl_filltype_r(ch->lp,1); - - fill_segment(ch, x0, y0, radius, start_angle, segment_angle); - pl_restorestate_r(ch->lp); - - /* Draw line dividing segments */ - pl_pentype_r(ch->lp, 1); - pl_fline_r(ch->lp, x0, y0, start_x, start_y); - + struct piechart *pie = UP_CAST (chart, struct piechart, chart); + int i; - pl_restorestate_r(ch->lp); + free (pie->title); + for (i = 0; i < pie->n_slices; i++) + { + struct slice *slice = &pie->slices[i]; + ds_destroy (&slice->label); + } + free (pie->slices); + free (pie); } +static const struct chart_class piechart_class = + { + piechart_draw, + piechart_destroy + }; diff --git a/src/output/charts/piechart.h b/src/output/charts/piechart.h index 96540401..39a0c2d5 100644 --- a/src/output/charts/piechart.h +++ b/src/output/charts/piechart.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,12 +21,11 @@ struct slice { struct string label; - double magnetude; + double magnitude; }; -/* Draw a piechart */ -void piechart_plot(const char *title, - const struct slice *slices, int n_slices); +struct chart *piechart_create (const char *title, + const struct slice *, int n_slices); #endif diff --git a/src/output/charts/plot-chart.c b/src/output/charts/plot-chart.c index 5641db12..cda6d1ec 100644 --- a/src/output/charts/plot-chart.c +++ b/src/output/charts/plot-chart.c @@ -16,241 +16,341 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include - #include -#include - - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include #include +#include +#include +#include #include #include #include "xalloc.h" -const char *const data_colour[N_CHART_COLOURS] = +#if ! PANGO_VERSION_CHECK (2, 22, 0) +int pango_layout_get_baseline (PangoLayout *layout); + +/* Shamelessly copied from the pango source */ +int +pango_layout_get_baseline (PangoLayout *layout) +{ + int baseline; + + /* XXX this is so inefficient */ + PangoLayoutIter *iter = pango_layout_get_iter (layout); + baseline = pango_layout_iter_get_baseline (iter); + pango_layout_iter_free (iter); + + return baseline; +} +#endif + + + +const struct chart_colour data_colour[N_CHART_COLOURS] = { - "brown", - "red", - "orange", - "yellow", - "green", - "blue", - "violet", - "grey", - "pink" + { 165, 42, 42 }, /* brown */ + { 255, 0, 0 }, /* red */ + { 255, 165, 0 }, /* orange */ + { 255, 255, 0 }, /* yellow */ + { 0, 255, 0 }, /* green */ + { 0, 0, 255 }, /* blue */ + { 238, 130, 238 }, /* violet */ + { 190, 190, 190 }, /* grey */ + { 255, 192, 203 }, /* pink */ }; +void +chart_draw_marker (cairo_t *cr, double x, double y, enum marker_type marker, + double size) +{ + cairo_save (cr); + cairo_translate (cr, x, y); + cairo_scale (cr, size / 2.0, size / 2.0); + cairo_set_line_width (cr, cairo_get_line_width (cr) / (size / 2.0)); + switch (marker) + { + case MARKER_CIRCLE: + cairo_arc (cr, 0, 0, 1.0, 0, 2 * M_PI); + cairo_stroke (cr); + break; + + case MARKER_ASTERISK: + cairo_move_to (cr, 0, -1.0); /* | */ + cairo_line_to (cr, 0, 1.0); + cairo_move_to (cr, -M_SQRT1_2, -M_SQRT1_2); /* / */ + cairo_line_to (cr, M_SQRT1_2, M_SQRT1_2); + cairo_move_to (cr, -M_SQRT1_2, M_SQRT1_2); /* \ */ + cairo_line_to (cr, M_SQRT1_2, -M_SQRT1_2); + cairo_stroke (cr); + break; + + case MARKER_SQUARE: + cairo_rectangle (cr, -1.0, -1.0, 2.0, 2.0); + cairo_stroke (cr); + break; + } + cairo_restore (cr); +} +void +chart_label (cairo_t *cr, int horz_justify, int vert_justify, double font_size, + const char *string) +{ + PangoFontDescription *desc; + PangoLayout *layout; + double x, y; + + desc = pango_font_description_from_string ("sans serif"); + if (desc == NULL) + { + cairo_new_path (cr); + return; + } + pango_font_description_set_absolute_size (desc, font_size * PANGO_SCALE); + + cairo_save (cr); + cairo_get_current_point (cr, &x, &y); + cairo_translate (cr, x, y); + cairo_move_to (cr, 0, 0); + cairo_scale (cr, 1.0, -1.0); + + layout = pango_cairo_create_layout (cr); + pango_layout_set_font_description (layout, desc); + pango_layout_set_text (layout, string, -1); + if (horz_justify != 'l') + { + int width_pango; + double width; + + pango_layout_get_size (layout, &width_pango, NULL); + width = (double) width_pango / PANGO_SCALE; + if (horz_justify == 'r') + cairo_rel_move_to (cr, -width, 0); + else + cairo_rel_move_to (cr, -width / 2.0, 0); + } + if (vert_justify == 'x') + { + int baseline_pango = pango_layout_get_baseline (layout); + double baseline = (double) baseline_pango / PANGO_SCALE; + cairo_rel_move_to (cr, 0, -baseline); + } + else if (vert_justify != 't') + { + int height_pango; + double height; + + pango_layout_get_size (layout, NULL, &height_pango); + height = (double) height_pango / PANGO_SCALE; + if (vert_justify == 'b') + cairo_rel_move_to (cr, 0, -height); + else if (vert_justify == 'c') + cairo_rel_move_to (cr, 0, -height / 2.0); + } + pango_cairo_show_layout (cr, layout); + g_object_unref (layout); + + cairo_restore (cr); + + cairo_new_path (cr); + + pango_font_description_free (desc); +} /* Draw a tick mark at position If label is non zero, then print it at the tick mark */ void -draw_tick(struct chart *chart, - enum tick_orientation orientation, - double position, - const char *label, ...) +draw_tick (cairo_t *cr, const struct chart_geometry *geom, + enum tick_orientation orientation, + double position, + const char *label, ...) { const int tickSize = 10; + double x, y; - assert(chart); - - pl_savestate_r(chart->lp); + cairo_move_to (cr, geom->data_left, geom->data_bottom); - pl_move_r(chart->lp, chart->data_left, chart->data_bottom); - - if ( orientation == TICK_ABSCISSA ) - pl_flinerel_r(chart->lp, position, 0, position, -tickSize); - else if (orientation == TICK_ORDINATE ) - pl_flinerel_r(chart->lp, 0, position, -tickSize, position); + if (orientation == TICK_ABSCISSA) + { + cairo_rel_move_to (cr, position, 0); + cairo_rel_line_to (cr, 0, -tickSize); + } + else if (orientation == TICK_ORDINATE) + { + cairo_rel_move_to (cr, 0, position); + cairo_rel_line_to (cr, -tickSize, 0); + } else NOT_REACHED (); + cairo_get_current_point (cr, &x, &y); - if ( label ) { - char buf[10]; - va_list ap; - va_start(ap,label); - vsnprintf(buf,10,label,ap); + cairo_stroke (cr); - if ( orientation == TICK_ABSCISSA ) - pl_alabel_r(chart->lp, 'c','t', buf); - else if (orientation == TICK_ORDINATE ) - { - if ( fabs(position) < DBL_EPSILON ) - pl_moverel_r(chart->lp, 0, 10); - - pl_alabel_r(chart->lp, 'r','c', buf); - } - - va_end(ap); - } - - pl_restorestate_r(chart->lp); + if (label != NULL) + { + va_list ap; + char *s; + + cairo_move_to (cr, x, y); + + va_start (ap, label); + s = xvasprintf (label, ap); + if (orientation == TICK_ABSCISSA) + chart_label (cr, 'c', 't', geom->font_size, s); + else if (orientation == TICK_ORDINATE) + { + if (fabs (position) < DBL_EPSILON) + cairo_rel_move_to (cr, 0, 10); + chart_label (cr, 'r', 'c', geom->font_size, s); + } + free (s); + va_end (ap); + } } /* Write the title on a chart*/ void -chart_write_title(struct chart *chart, const char *title, ...) +chart_write_title (cairo_t *cr, const struct chart_geometry *geom, + const char *title, ...) { va_list ap; - char buf[100]; - - if ( ! chart ) - return ; + char *s; - pl_savestate_r(chart->lp); - pl_ffontsize_r(chart->lp,chart->font_size * 1.5); - pl_move_r(chart->lp,chart->data_left, chart->title_bottom); + cairo_save (cr); + cairo_move_to (cr, geom->data_left, geom->title_bottom); - va_start(ap,title); - vsnprintf(buf,100,title,ap); - pl_alabel_r(chart->lp,0,0,buf); - va_end(ap); + va_start(ap, title); + s = xvasprintf (title, ap); + chart_label (cr, 'l', 'x', geom->font_size * 1.5, s); + free (s); + va_end (ap); - pl_restorestate_r(chart->lp); + cairo_restore (cr); } /* Set the scale for the abscissa */ void -chart_write_xscale(struct chart *ch, double min, double max, int ticks) +chart_write_xscale (cairo_t *cr, struct chart_geometry *geom, + double min, double max, int ticks) { double x; const double tick_interval = - chart_rounded_tick( (max - min) / (double) ticks); + chart_rounded_tick ((max - min) / (double) ticks); - assert ( ch ); - - - ch->x_max = ceil( max / tick_interval ) * tick_interval ; - ch->x_min = floor ( min / tick_interval ) * tick_interval ; - - - ch->abscissa_scale = fabs(ch->data_right - ch->data_left) / - fabs(ch->x_max - ch->x_min); - - for(x = ch->x_min ; x <= ch->x_max; x += tick_interval ) - { - draw_tick (ch, TICK_ABSCISSA, - (x - ch->x_min) * ch->abscissa_scale, "%g", x); - } + geom->x_max = ceil (max / tick_interval) * tick_interval; + geom->x_min = floor (min / tick_interval) * tick_interval; + geom->abscissa_scale = fabs(geom->data_right - geom->data_left) / + fabs(geom->x_max - geom->x_min); + for (x = geom->x_min; x <= geom->x_max; x += tick_interval) + draw_tick (cr, geom, TICK_ABSCISSA, + (x - geom->x_min) * geom->abscissa_scale, "%g", x); } /* Set the scale for the ordinate */ void -chart_write_yscale(struct chart *ch, double smin, double smax, int ticks) +chart_write_yscale (cairo_t *cr, struct chart_geometry *geom, + double smin, double smax, int ticks) { double y; const double tick_interval = - chart_rounded_tick( (smax - smin) / (double) ticks); - - if ( !ch ) - return; + chart_rounded_tick ((smax - smin) / (double) ticks); - ch->y_max = ceil ( smax / tick_interval ) * tick_interval ; - ch->y_min = floor ( smin / tick_interval ) * tick_interval ; + geom->y_max = ceil (smax / tick_interval) * tick_interval; + geom->y_min = floor (smin / tick_interval) * tick_interval; - ch->ordinate_scale = - fabs(ch->data_top - ch->data_bottom) / fabs(ch->y_max - ch->y_min) ; + geom->ordinate_scale = + (fabs (geom->data_top - geom->data_bottom) + / fabs (geom->y_max - geom->y_min)); - for(y = ch->y_min ; y <= ch->y_max; y += tick_interval ) - { - draw_tick (ch, TICK_ORDINATE, - (y - ch->y_min) * ch->ordinate_scale, "%g", y); - } + for (y = geom->y_min; y <= geom->y_max; y += tick_interval) + draw_tick (cr, geom, TICK_ORDINATE, + (y - geom->y_min) * geom->ordinate_scale, "%g", y); } - /* Write the abscissa label */ void -chart_write_xlabel(struct chart *ch, const char *label) +chart_write_xlabel (cairo_t *cr, const struct chart_geometry *geom, + const char *label) { - if ( ! ch ) - return ; - - pl_savestate_r(ch->lp); - - pl_move_r(ch->lp,ch->data_left, ch->abscissa_top); - pl_alabel_r(ch->lp,0,'t',label); - - pl_restorestate_r(ch->lp); - + cairo_move_to (cr, geom->data_left, geom->abscissa_top); + chart_label (cr, 'l', 't', geom->font_size, label); } - - /* Write the ordinate label */ void -chart_write_ylabel(struct chart *ch, const char *label) +chart_write_ylabel (cairo_t *cr, const struct chart_geometry *geom, + const char *label) { - if ( ! ch ) - return ; - - pl_savestate_r(ch->lp); - - pl_move_r(ch->lp, ch->data_bottom, ch->ordinate_right); - pl_textangle_r(ch->lp, 90); - pl_alabel_r(ch->lp, 0, 0, label); - - pl_restorestate_r(ch->lp); + cairo_save (cr); + cairo_translate (cr, -geom->data_bottom, -geom->ordinate_right); + cairo_move_to (cr, 0, 0); + cairo_rotate (cr, M_PI / 2.0); + chart_label (cr, 'l', 'x', geom->font_size, label); + cairo_restore (cr); } void -chart_write_legend (struct chart *ch) +chart_write_legend (cairo_t *cr, const struct chart_geometry *geom) { int i; - const int vstep = ch->font_size * 2; + const int vstep = geom->font_size * 2; const int xpad = 10; const int ypad = 10; const int swatch = 20; - const int legend_top = ch->data_top; + const int legend_top = geom->data_top; const int legend_bottom = legend_top - - (vstep * ch->n_datasets + 2 * ypad ); - - if ( ! ch ) - return ; + (vstep * geom->n_datasets + 2 * ypad ); - pl_savestate_r (ch->lp); + cairo_save (cr); - pl_box_r (ch->lp, ch->legend_left, legend_top, - ch->legend_right - xpad, legend_bottom); + cairo_rectangle (cr, geom->legend_left, legend_top, + geom->legend_right - xpad - geom->legend_left, + legend_bottom - legend_top); + cairo_stroke (cr); - for (i = 0 ; i < ch->n_datasets ; ++i ) + for (i = 0 ; i < geom->n_datasets ; ++i ) { - const int ypos = vstep * (i + 1); - const int xpos = ch->legend_left + xpad; - pl_move_r (ch->lp, xpos, legend_top - ypos); - - pl_savestate_r(ch->lp); - pl_fillcolorname_r (ch->lp, data_colour [ i % N_CHART_COLOURS]); - - pl_pentype_r (ch->lp, 1); - pl_filltype_r (ch->lp, 1); - pl_boxrel_r (ch->lp, 0, 0, swatch, swatch); - - - pl_moverel_r (ch->lp, swatch, 0); - pl_alabel_r (ch->lp, 0, 0, ch->dataset[i]); - - pl_restorestate_r (ch->lp); + const int ypos = legend_top - vstep * (i + 1); + const int xpos = geom->legend_left + xpad; + const struct chart_colour *colour; + + cairo_move_to (cr, xpos, ypos); + + cairo_save (cr); + colour = &data_colour [ i % N_CHART_COLOURS]; + cairo_set_source_rgb (cr, + colour->red / 255.0, + colour->green / 255.0, + colour->blue / 255.0); + cairo_rectangle (cr, xpos, ypos, swatch, swatch); + cairo_fill_preserve (cr); + cairo_stroke (cr); + cairo_restore (cr); + + cairo_move_to (cr, xpos + swatch * 1.5, ypos); + chart_label (cr, 'l', 'x', geom->font_size, geom->dataset[i]); } - pl_restorestate_r (ch->lp); + cairo_restore (cr); } diff --git a/src/output/charts/plot-chart.h b/src/output/charts/plot-chart.h index cfbaa4df..896b630b 100644 --- a/src/output/charts/plot-chart.h +++ b/src/output/charts/plot-chart.h @@ -14,6 +14,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#ifndef PLOT_CHART_H +#define PLOT_CHART_H + +#include #include #include #include @@ -25,19 +29,15 @@ #include #include +#include #include #include #include #include -#include "xalloc.h" - -#ifndef PLOT_CHART_H -#define PLOT_CHART_H - #define N_CHART_COLOURS 9 -extern const char *const data_colour[]; +extern const struct chart_colour data_colour[]; enum tick_orientation { @@ -45,34 +45,54 @@ enum tick_orientation TICK_ORDINATE }; +struct chart_geometry; + + +enum marker_type + { + MARKER_CIRCLE, /* Hollow circle. */ + MARKER_ASTERISK, /* Asterisk (*). */ + MARKER_SQUARE /* Hollow square. */ + }; + +void chart_draw_marker (cairo_t *, double x, double y, enum marker_type, + double size); + +void chart_label (cairo_t *, int horz_justify, int vert_justify, + double font_size, const char *); /* Draw a tick mark at position If label is non zero, then print it at the tick mark */ -void draw_tick(struct chart *chart, +void draw_tick(cairo_t *, const struct chart_geometry *, enum tick_orientation orientation, double position, const char *label, ...) - PRINTF_FORMAT (4, 5); + PRINTF_FORMAT (5, 6); /* Write the title on a chart*/ -void chart_write_title(struct chart *chart, const char *title, ...) - PRINTF_FORMAT (2, 3); +void chart_write_title(cairo_t *, const struct chart_geometry *, + const char *title, ...) + PRINTF_FORMAT (3, 4); /* Set the scale for the abscissa */ -void chart_write_xscale(struct chart *ch, double min, double max, int ticks); +void chart_write_xscale(cairo_t *, struct chart_geometry *, + double min, double max, int ticks); /* Set the scale for the ordinate */ -void chart_write_yscale(struct chart *ch, double smin, double smax, int ticks); +void chart_write_yscale(cairo_t *, struct chart_geometry *, + double smin, double smax, int ticks); -void chart_write_xlabel(struct chart *ch, const char *label) ; +void chart_write_xlabel(cairo_t *, const struct chart_geometry *, + const char *label) ; /* Write the ordinate label */ -void chart_write_ylabel(struct chart *ch, const char *label); +void chart_write_ylabel(cairo_t *, const struct chart_geometry *, + const char *label); -void chart_write_legend (struct chart *ch); +void chart_write_legend (cairo_t *, const struct chart_geometry *); #endif diff --git a/src/output/charts/plot-hist.c b/src/output/charts/plot-hist.c index fbf1925e..334818b4 100644 --- a/src/output/charts/plot-hist.c +++ b/src/output/charts/plot-hist.c @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -26,8 +25,10 @@ #include #include +#include #include +#include #include #include #include @@ -36,157 +37,187 @@ #include "gettext.h" #define _(msgid) gettext (msgid) +static const struct chart_class histogram_chart_class; + /* Write the legend of the chart */ static void -histogram_write_legend (struct chart *ch, double n, double mean, double stddev) +histogram_write_legend (cairo_t *cr, const struct chart_geometry *geom, + double n, double mean, double stddev) { - char buf[100]; - - if (!ch) - return ; - - pl_savestate_r (ch->lp); + double y = geom->data_bottom; + cairo_save (cr); - sprintf (buf, "N = %.2f", n); - pl_move_r (ch->lp, ch->legend_left, ch->data_bottom); - pl_alabel_r (ch->lp, 0, 'b', buf); + if (n != SYSMIS) + { + char *buf = xasprintf ("N = %.2f", n); + cairo_move_to (cr, geom->legend_left, y); + chart_label (cr, 'l', 'b', geom->font_size, buf); + y += geom->font_size * 1.5; + free (buf); + } - sprintf (buf, "Mean = %.1f", mean); - pl_fmove_r (ch->lp,ch->legend_left,ch->data_bottom + ch->font_size * 1.5); - pl_alabel_r (ch->lp, 0, 'b', buf); + if (mean != SYSMIS) + { + char *buf = xasprintf ("Mean = %.1f", mean); + cairo_move_to (cr,geom->legend_left, y); + chart_label (cr, 'l', 'b', geom->font_size, buf); + y += geom->font_size * 1.5; + free (buf); + } - sprintf (buf, "Std. Dev = %.2f", stddev); - pl_fmove_r (ch->lp, ch->legend_left, ch->data_bottom + ch->font_size * 1.5 * 2); - pl_alabel_r (ch->lp, 0, 'b', buf); + if (stddev != SYSMIS) + { + char *buf = xasprintf ("Std. Dev = %.2f", stddev); + cairo_move_to (cr, geom->legend_left, y); + chart_label (cr, 'l', 'b', geom->font_size, buf); + free (buf); + } - pl_restorestate_r (ch->lp); + cairo_restore (cr); } -static void hist_draw_bar (struct chart *ch, const struct histogram *hist, int bar); - - static void -hist_draw_bar (struct chart *ch, const struct histogram *hist, int bar) +hist_draw_bar (cairo_t *cr, const struct chart_geometry *geom, + const gsl_histogram *h, int bar) { - if (!ch) - return ; - - { - double upper; - double lower; - double height; - - const size_t bins = gsl_histogram_bins (hist->gsl_hist); - const double x_pos = (ch->data_right - ch->data_left) * bar / (double) bins ; - const double width = (ch->data_right - ch->data_left) / (double) bins ; - - assert ( 0 == gsl_histogram_get_range (hist->gsl_hist, bar, &lower, &upper)); - - assert ( upper >= lower); - - height = gsl_histogram_get (hist->gsl_hist, bar) * - (ch->data_top - ch->data_bottom) / gsl_histogram_max_val (hist->gsl_hist); - - pl_savestate_r (ch->lp); - pl_move_r (ch->lp,ch->data_left, ch->data_bottom); - pl_fillcolorname_r (ch->lp, ch->fill_colour); - pl_filltype_r (ch->lp,1); - - - pl_fboxrel_r (ch->lp, - x_pos, 0, - x_pos + width, height); - - pl_restorestate_r (ch->lp); - - draw_tick (ch, TICK_ABSCISSA, - x_pos + width / 2.0, "%g", (upper + lower) / 2.0); - } + double upper; + double lower; + double height; + + const size_t bins = gsl_histogram_bins (h); + const double x_pos = (geom->data_right - geom->data_left) * bar / (double) bins ; + const double width = (geom->data_right - geom->data_left) / (double) bins ; + + assert ( 0 == gsl_histogram_get_range (h, bar, &lower, &upper)); + + assert ( upper >= lower); + + height = gsl_histogram_get (h, bar) * + (geom->data_top - geom->data_bottom) / gsl_histogram_max_val (h); + + cairo_rectangle (cr, geom->data_left + x_pos, geom->data_bottom, + width, height); + cairo_save (cr); + cairo_set_source_rgb (cr, + geom->fill_colour.red / 255.0, + geom->fill_colour.green / 255.0, + geom->fill_colour.blue / 255.0); + cairo_fill_preserve (cr); + cairo_restore (cr); + cairo_stroke (cr); + + draw_tick (cr, geom, TICK_ABSCISSA, + x_pos + width / 2.0, "%g", (upper + lower) / 2.0); } - - -void -histogram_plot (const struct histogram *hist, - const char *label, - const struct moments1 *m) +struct histogram_chart + { + struct chart chart; + gsl_histogram *gsl_hist; + char *label; + double n; + double mean; + double stddev; + bool show_normal; + }; + +/* Plots a histogram of the data in HIST with the given LABEL. + Labels the histogram with each of N, MEAN, and STDDEV that is + not SYSMIS. If all three are not SYSMIS and SHOW_NORMAL is + true, also draws a normal curve on the histogram. */ +struct chart * +histogram_chart_create (const struct histogram *hist, const char *label, + double n, double mean, double stddev, + bool show_normal) { - double mean, var, n; - - moments1_calculate (m, &n, &mean, &var, NULL, NULL); - - histogram_plot_n (hist, label, n, mean, sqrt(var), m); + struct histogram_chart *h; + + h = xmalloc (sizeof *h); + chart_init (&h->chart, &histogram_chart_class); + h->gsl_hist = hist->gsl_hist ? gsl_histogram_clone (hist->gsl_hist) : NULL; + h->label = xstrdup (label); + h->n = n; + h->mean = mean; + h->stddev = stddev; + h->show_normal = show_normal; + return &h->chart; } - -/* This function is deprecated. Don't use it in new code */ -void -histogram_plot_n (const struct histogram *hist, - const char *label, - double n, double mean, double stddev, - bool show_normal) +static void +histogram_chart_draw (const struct chart *chart, cairo_t *cr, + struct chart_geometry *geom) { + struct histogram_chart *h = UP_CAST (chart, struct histogram_chart, chart); int i; int bins; - struct chart *ch = chart_create (); - - chart_write_title (ch, _("HISTOGRAM")); + chart_write_title (cr, geom, _("HISTOGRAM")); - chart_write_ylabel (ch, _("Frequency")); - chart_write_xlabel (ch, label); + chart_write_ylabel (cr, geom, _("Frequency")); + chart_write_xlabel (cr, geom, h->label); - if ( ! hist ) /* If this happens, probably all values are SYSMIS */ + if (h->gsl_hist == NULL) { - chart_submit (ch); + /* Probably all values are SYSMIS. */ return; } - else - { - bins = gsl_histogram_bins (hist->gsl_hist); - } - chart_write_yscale (ch, 0, gsl_histogram_max_val (hist->gsl_hist), 5); + bins = gsl_histogram_bins (h->gsl_hist); + + chart_write_yscale (cr, geom, 0, gsl_histogram_max_val (h->gsl_hist), 5); - for ( i = 0 ; i < bins ; ++i ) - hist_draw_bar (ch, hist, i); + for (i = 0; i < bins; i++) + hist_draw_bar (cr, geom, h->gsl_hist, i); - histogram_write_legend (ch, n, mean, stddev); + histogram_write_legend (cr, geom, h->n, h->mean, h->stddev); - if (show_normal) + if (h->show_normal + && h->n != SYSMIS && h->mean != SYSMIS && h->stddev != SYSMIS) { /* Draw the normal curve */ + double d; + double x_min, x_max, not_used; + double abscissa_scale; + double ordinate_scale; + double range; - double d ; - double x_min, x_max, not_used ; - double abscissa_scale ; - double ordinate_scale ; - double range ; - - gsl_histogram_get_range (hist->gsl_hist, 0, &x_min, ¬_used); + gsl_histogram_get_range (h->gsl_hist, 0, &x_min, ¬_used); range = not_used - x_min; - gsl_histogram_get_range (hist->gsl_hist, bins - 1, ¬_used, &x_max); + gsl_histogram_get_range (h->gsl_hist, bins - 1, ¬_used, &x_max); - abscissa_scale = (ch->data_right - ch->data_left) / (x_max - x_min); - ordinate_scale = (ch->data_top - ch->data_bottom) / - gsl_histogram_max_val (hist->gsl_hist) ; + abscissa_scale = (geom->data_right - geom->data_left) / (x_max - x_min); + ordinate_scale = (geom->data_top - geom->data_bottom) / + gsl_histogram_max_val (h->gsl_hist); - pl_move_r (ch->lp, ch->data_left, ch->data_bottom); - for ( d = ch->data_left; - d <= ch->data_right ; - d += (ch->data_right - ch->data_left) / 100.0) + cairo_move_to (cr, geom->data_left, geom->data_bottom); + for (d = geom->data_left; + d <= geom->data_right; + d += (geom->data_right - geom->data_left) / 100.0) { - const double x = (d - ch->data_left) / abscissa_scale + x_min ; - const double y = n * range * - gsl_ran_gaussian_pdf (x - mean, stddev); + const double x = (d - geom->data_left) / abscissa_scale + x_min; + const double y = h->n * range * + gsl_ran_gaussian_pdf (x - h->mean, h->stddev); - pl_fcont_r (ch->lp, d, ch->data_bottom + y * ordinate_scale); + cairo_line_to (cr, d, geom->data_bottom + y * ordinate_scale); } - pl_endpath_r (ch->lp); + cairo_stroke (cr); } - - chart_submit (ch); } +static void +histogram_chart_destroy (struct chart *chart) +{ + struct histogram_chart *h = UP_CAST (chart, struct histogram_chart, chart); + if (h->gsl_hist != NULL) + gsl_histogram_free (h->gsl_hist); + free (h->label); + free (h); +} + +static const struct chart_class histogram_chart_class = + { + histogram_chart_draw, + histogram_chart_destroy + }; diff --git a/src/output/charts/plot-hist.h b/src/output/charts/plot-hist.h index 606206d5..1e5b59ed 100644 --- a/src/output/charts/plot-hist.h +++ b/src/output/charts/plot-hist.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,26 +14,22 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef PLOT_HIST_H -#define PLOT_HIST_H +#ifndef OUTPUT_PLOT_HIST_H +#define OUTPUT_PLOT_HIST_H #include struct chart; -struct moments1; struct histogram; -/* Plot M onto histogram HIST and label it with LABEL */ -void histogram_plot (const struct histogram *hist, - const char *label, const struct moments1 *m); - - -/* A wrapper aroud histogram_plot. - Don't use this function. It's legacy only */ -void histogram_plot_n (const struct histogram *hist, - const char *label, - double n, double mean, double var, - bool show_normal); - - -#endif +/* Creates and returns a new chart that depicts a histogram of + the data in HIST with the given LABEL. Labels the histogram + with each of N, MEAN, and STDDEV that is not SYSMIS. If all + three are not SYSMIS and SHOW_NORMAL is true, also draws a + normal curve on the histogram. */ +struct chart *histogram_chart_create (const struct histogram *hist, + const char *label, + double n, double mean, double stddev, + bool show_normal); + +#endif /* output/plot-hist.h */ diff --git a/src/output/charts/roc-chart.c b/src/output/charts/roc-chart.c new file mode 100644 index 00000000..2094ede5 --- /dev/null +++ b/src/output/charts/roc-chart.c @@ -0,0 +1,148 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "xalloc.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +struct roc_var + { + char *name; + struct casereader *cutpoint_reader; + }; + +struct roc_chart + { + struct chart chart; + bool reference; + struct roc_var *vars; + size_t n_vars; + size_t allocated_vars; + }; + +static const struct chart_class roc_chart_class; + +struct roc_chart * +roc_chart_create (bool reference) +{ + struct roc_chart *rc = xmalloc (sizeof *rc); + chart_init (&rc->chart, &roc_chart_class); + rc->reference = reference; + rc->vars = NULL; + rc->n_vars = 0; + rc->allocated_vars = 0; + return rc; +} + +void +roc_chart_add_var (struct roc_chart *rc, const char *var_name, + const struct casereader *cutpoint_reader) +{ + struct roc_var *rv; + + if (rc->n_vars >= rc->allocated_vars) + rc->vars = x2nrealloc (rc->vars, &rc->allocated_vars, sizeof *rc->vars); + + rv = &rc->vars[rc->n_vars++]; + rv->name = xstrdup (var_name); + rv->cutpoint_reader = casereader_clone (cutpoint_reader); +} + +struct chart * +roc_chart_get_chart (struct roc_chart *rc) +{ + return &rc->chart; +} + +static void +roc_chart_draw (const struct chart *chart, cairo_t *cr, + struct chart_geometry *geom) +{ + const struct roc_chart *rc = UP_CAST (chart, struct roc_chart, chart); + size_t i; + + chart_write_title (cr, geom, _("ROC Curve")); + chart_write_xlabel (cr, geom, _("1 - Specificity")); + chart_write_ylabel (cr, geom, _("Sensitivity")); + + chart_write_xscale (cr, geom, 0, 1, 5); + chart_write_yscale (cr, geom, 0, 1, 5); + + if ( rc->reference ) + { + chart_line (cr, geom, 1.0, 0, + 0.0, 1.0, + CHART_DIM_X); + } + + for (i = 0; i < rc->n_vars; ++i) + { + const struct roc_var *rv = &rc->vars[i]; + struct casereader *r = casereader_clone (rv->cutpoint_reader); + struct ccase *cc; + + chart_vector_start (cr, geom, rv->name); + for (; (cc = casereader_read (r)) != NULL; case_unref (cc)) + { + double se = case_data_idx (cc, ROC_TP)->f; + double sp = case_data_idx (cc, ROC_TN)->f; + + se /= case_data_idx (cc, ROC_FN)->f + case_data_idx (cc, ROC_TP)->f ; + sp /= case_data_idx (cc, ROC_TN)->f + case_data_idx (cc, ROC_FP)->f ; + + chart_vector (cr, geom, 1 - sp, se); + } + chart_vector_end (cr, geom); + casereader_destroy (r); + } + + chart_write_legend (cr, geom); +} + +static void +roc_chart_destroy (struct chart *chart) +{ + struct roc_chart *rc = UP_CAST (chart, struct roc_chart, chart); + size_t i; + + for (i = 0; i < rc->n_vars; i++) + { + struct roc_var *rv = &rc->vars[i]; + free (rv->name); + casereader_destroy (rv->cutpoint_reader); + } + free (rc->vars); + free (rc); +} + +static const struct chart_class roc_chart_class = + { + roc_chart_draw, + roc_chart_destroy + }; + + diff --git a/src/output/charts/roc-chart.h b/src/output/charts/roc-chart.h new file mode 100644 index 00000000..dca84207 --- /dev/null +++ b/src/output/charts/roc-chart.h @@ -0,0 +1,29 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef OUTPUT_CHARTS_ROC_CHART_H +#define OUTPUT_CHARTS_ROC_CHART_H 1 + +#include + +struct casereader; + +struct roc_chart *roc_chart_create (bool reference); +void roc_chart_add_var (struct roc_chart *, const char *var_name, + const struct casereader *cutpoint_reader); +struct chart *roc_chart_get_chart (struct roc_chart *); + +#endif /* output/charts/roc-chart.h */ diff --git a/src/output/html.c b/src/output/html.c index 893c1852..dfa524a7 100644 --- a/src/output/html.c +++ b/src/output/html.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,12 +27,13 @@ #include #include #include -#include "error.h" -#include "output.h" -#include "manager.h" -#include "table.h" +#include +#include +#include +#include #include +#include "error.h" #include "xalloc.h" #include "gettext.h" @@ -47,23 +48,25 @@ static void escape_string (FILE *file, const char *text, size_t length, const char *space); -static bool handle_option (struct outp_driver *this, +static bool handle_option (void *this, const char *key, const struct string *val); static void print_title_tag (FILE *file, const char *name, const char *content); static bool -html_open_driver (struct outp_driver *this, struct substring options) +html_open_driver (const char *name, int types, struct substring options) { + struct outp_driver *this; struct html_driver_ext *x; + this = outp_allocate_driver (&html_class, name, types); this->ext = x = xmalloc (sizeof *x); x->file_name = xstrdup ("pspp.html"); x->chart_file_name = xstrdup ("pspp-#.png"); x->file = NULL; - x->chart_cnt = 0; + x->chart_cnt = 1; - outp_parse_options (options, handle_option, this); + outp_parse_options (name, options, handle_option, this); x->file = fn_open (x->file_name, "w"); if (x->file == NULL) @@ -89,10 +92,12 @@ html_open_driver (struct outp_driver *this, struct substring options) print_title_tag (x->file, "H1", outp_title); print_title_tag (x->file, "H2", outp_subtitle); + outp_register_driver (this); return true; error: this->class->close_driver (this); + outp_free_driver (this); return false; } @@ -133,14 +138,6 @@ html_close_driver (struct outp_driver *this) return ok; } -/* Link the image contained in FILE_NAME to the - HTML stream in FILE. */ -static void -link_image (FILE *file, char *file_name) -{ - fprintf (file, "", file_name); - } - /* Generic option types. */ enum { @@ -157,9 +154,9 @@ static const struct outp_option option_tab[] = }; static bool -handle_option (struct outp_driver *this, - const char *key, const struct string *val) +handle_option (void *this_, const char *key, const struct string *val) { + struct outp_driver *this = this_; struct html_driver_ext *x = this->ext; int subcat; @@ -199,11 +196,21 @@ handle_option (struct outp_driver *this, static void output_tab_table (struct outp_driver *, struct tab_table *); +static void +html_output_chart (struct outp_driver *this, const struct chart *chart) +{ + struct html_driver_ext *x = this->ext; + char *file_name; + + file_name = chart_draw_png (chart, x->chart_file_name, x->chart_cnt++); + fprintf (x->file, "", file_name); + free (file_name); +} + static void html_submit (struct outp_driver *this, struct som_entity *s) { extern struct som_table_class tab_table_class; - struct html_driver_ext *x = this->ext; assert (s->class == &tab_table_class ) ; @@ -212,9 +219,6 @@ html_submit (struct outp_driver *this, struct som_entity *s) case SOM_TABLE: output_tab_table ( this, (struct tab_table *) s->ext); break; - case SOM_CHART: - link_image (x->file, ((struct chart *)s->ext)->file_name); - break; default: NOT_REACHED (); } @@ -289,7 +293,7 @@ output_tab_table (struct outp_driver *this, struct tab_table *t) { struct html_driver_ext *x = this->ext; - if (t->nr == 1 && t->nc == 1) + if (tab_nr (t) == 1 && tab_nc (t) == 1) { fputs ("

", x->file); html_put_cell_contents (this, t->ct[0], *t->cc); @@ -311,18 +315,18 @@ output_tab_table (struct outp_driver *this, struct tab_table *t) int r; unsigned char *ct = t->ct; - for (r = 0; r < t->nr; r++) + for (r = 0; r < tab_nr (t); r++) { int c; fputs (" \n", x->file); - for (c = 0; c < t->nc; c++, ct++) + for (c = 0; c < tab_nc (t); c++, ct++) { struct substring *cc; const char *tag; struct tab_joined_cell *j = NULL; - cc = t->cc + c + r * t->nc; + cc = t->cc + c + r * tab_nc (t); if (*ct & TAB_JOIN) { j = (struct tab_joined_cell *) ss_data (*cc); @@ -332,8 +336,8 @@ output_tab_table (struct outp_driver *this, struct tab_table *t) } /* Output or tag. */ - tag = (r < t->t || r >= t->nr - t->b - || c < t->l || c >= t->nc - t->r) ? "TH" : "TD"; + tag = (r < tab_t (t) || r >= tab_nr (t) - tab_b (t) + || c < tab_l (t) || c >= tab_nc (t) - tab_r (t)) ? "TH" : "TD"; fprintf (x->file, " <%s ALIGN=%s", tag, (*ct & TAB_ALIGN_MASK) == TAB_LEFT ? "LEFT" @@ -361,19 +365,6 @@ output_tab_table (struct outp_driver *this, struct tab_table *t) fputs ("\n\n", x->file); } -static void -html_initialise_chart (struct outp_driver *this UNUSED, struct chart *ch) -{ - struct html_driver_ext *x = this->ext; - chart_init_separate (ch, "png", x->chart_file_name, ++x->chart_cnt); -} - -static void -html_finalise_chart(struct outp_driver *d UNUSED, struct chart *ch) -{ - chart_finalise_separate (ch); -} - /* HTML driver class. */ @@ -389,11 +380,11 @@ const struct outp_class html_class = NULL, NULL, + html_output_chart, + html_submit, NULL, NULL, NULL, - html_initialise_chart, - html_finalise_chart }; diff --git a/src/output/manager.c b/src/output/manager.c index 0b2fdfe1..9b901393 100644 --- a/src/output/manager.c +++ b/src/output/manager.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,16 +15,42 @@ along with this program. If not, see . */ #include -#include "manager.h" + +#include + #include #include + #include -#include "output.h" +#include + +#include "gl/xalloc.h" /* Table. */ -int table_num = 1; -int subtable_num; +static int table_num = 1; +static int subtable_num; + +/* Name of PSPP's current command, or NULL if outside a command. */ +static char *command_name; +struct som_entity * +som_entity_clone (struct som_entity *entity) +{ + struct som_entity *copy = xmemdup (entity, sizeof *entity); + copy->command_name = xstrdup (entity->command_name); + return copy; +} + +void +som_entity_destroy (struct som_entity *entity) +{ + if (entity != NULL) + { + free (entity->command_name); + free (entity); + } +} + /* Increments table_num so different procedures' output can be distinguished. */ void @@ -37,6 +63,15 @@ som_new_series (void) } } +/* Sets COMMAND_NAME as the name of the current command, + for embedding in output. */ +void +som_set_command_name (const char *command_name_) +{ + free (command_name); + command_name = command_name_ ? xstrdup (command_name_) : NULL; +} + /* Ejects the paper for all active devices. */ void som_eject_page (void) @@ -68,30 +103,16 @@ som_blank_line (void) d->cp_y += d->font_height; } -/* Driver. */ -static struct outp_driver *d = 0; - -/* Table. */ -static struct som_entity *t = 0; - -/* Flags. */ -static unsigned flags; - -/* Number of columns, rows. */ -static int nc, nr; - -/* Number of columns or rows in left, right, top, bottom headers. */ -static int hl, hr, ht, hb; - -/* Column style. */ -static int cs; - -/* Table height, width. */ -static int th, tw; - -static void render_columns (void); -static void render_simple (void); -static void render_segments (void); +static void render_columns (void *r, struct outp_driver *, struct som_entity *, + int tw, int th, + int hl, int hr, int ht, int hb); +static void render_simple (void *r, struct outp_driver *, struct som_entity *, + int tw, int th, + int hl, int hr, int ht, int hb); +static void render_segments (void *r, struct outp_driver *, + struct som_entity *, + int tw, int th, + int hl, int hr, int ht, int hb); static void output_entity (struct outp_driver *, struct som_entity *); @@ -99,84 +120,132 @@ static void output_entity (struct outp_driver *, struct som_entity *); void som_submit (struct som_entity *t) { + struct outp_driver *d; + unsigned int flags; + #if DEBUGGING static int entry; assert (entry++ == 0); #endif - if ( t->type == SOM_TABLE) - { - t->class->table (t); - t->class->flags (&flags); - t->class->count (&nc, &nr); - t->class->headers (&hl, &hr, &ht, &hb); + t->class->flags (t, &flags); + if (!(flags & SOMF_NO_TITLE)) + subtable_num++; + t->table_num = table_num; + t->subtable_num = subtable_num; + t->command_name = command_name ? xstrdup (command_name) : NULL; + if (t->type == SOM_TABLE) + { + int hl, hr, ht, hb; + int nc, nr; -#if DEBUGGING + t->class->count (t, &nc, &nr); + t->class->headers (t, &hl, &hr, &ht, &hb); if (hl + hr > nc || ht + hb > nr) { - printf ("headers: (l,r)=(%d,%d), (t,b)=(%d,%d) in table size (%d,%d)\n", - hl, hr, ht, hb, nc, nr); + fprintf (stderr, "headers: (l,r)=(%d,%d), (t,b)=(%d,%d) " + "in table size (%d,%d)\n", + hl, hr, ht, hb, nc, nr); NOT_REACHED (); } else if (hl + hr == nc) - printf ("warning: headers (l,r)=(%d,%d) in table width %d\n", hl, hr, nc); + fprintf (stderr, "warning: headers (l,r)=(%d,%d) in table width %d\n", + hl, hr, nc); else if (ht + hb == nr) - printf ("warning: headers (t,b)=(%d,%d) in table height %d\n", ht, hb, nr); -#endif + fprintf (stderr, "warning: headers (t,b)=(%d,%d) in table height %d\n", + ht, hb, nr); + } + + for (d = outp_drivers (NULL); d; d = outp_drivers (d)) + output_entity (d, t); - t->class->columns (&cs); +#if DEBUGGING + assert (--entry == 0); +#endif +} - if (!(flags & SOMF_NO_TITLE)) - subtable_num++; +static bool +check_fits_width (struct som_entity *t, const struct outp_driver *d, void *r) +{ + int hl, hr, ht, hb; + int nc, nr; + int i; + t->class->headers (t, &hl, &hr, &ht, &hb); + t->class->count (t, &nc, &nr); + for (i = hl; i < nc - hr; i++) + { + int end, actual; + t->class->cumulate (r, SOM_COLUMNS, i, &end, d->width, &actual); + if (end == i) + return false; } - { - struct outp_driver *d; + return true; +} - for (d = outp_drivers (NULL); d; d = outp_drivers (d)) - output_entity (d, t); +static bool +check_fits_length (struct som_entity *t, const struct outp_driver *d, void *r) +{ + int hl, hr, ht, hb; + int nc, nr; + int i; - } + t->class->headers (t, &hl, &hr, &ht, &hb); + t->class->count (t, &nc, &nr); + for (i = ht; i < nr - hb; i++) + { + int end, actual; + t->class->cumulate (r, SOM_ROWS, i, &end, d->length, &actual); + if (end == i) + return false; + } -#if DEBUGGING - assert (--entry == 0); -#endif + return true; } -/* Output entity ENTITY to driver DRIVER. */ +/* Output entity T to driver D. */ static void -output_entity (struct outp_driver *driver, struct som_entity *entity) +output_entity (struct outp_driver *d, struct som_entity *t) { bool fits_width, fits_length; - d = driver; + unsigned int flags; + int hl, hr, ht, hb; + int tw, th; + int nc, nr; + int cs; + void *r; outp_open_page (d); - if (d->class->special || entity->type == SOM_CHART) + if (d->class->special) { - driver->class->submit (d, entity); + d->class->submit (d, t); return; } - t = entity; + t->class->headers (t, &hl, &hr, &ht, &hb); + t->class->count (t, &nc, &nr); + t->class->columns (t, &cs); + t->class->flags (t, &flags); + + r = t->class->render_init (t, d, hl, hr, ht, hb); - t->class->driver (d); - t->class->area (&tw, &th); - fits_width = t->class->fits_width (d->width); - fits_length = t->class->fits_length (d->length); + fits_width = check_fits_width (t, d, r); + fits_length = check_fits_length (t, d, r); if (!fits_width || !fits_length) { - int tl, tr, tt, tb; - tl = fits_width ? hl : 0; - tr = fits_width ? hr : 0; - tt = fits_length ? ht : 0; - tb = fits_length ? hb : 0; - t->class->set_headers (tl, tr, tt, tb); - t->class->driver (d); - t->class->area (&tw, &th); + t->class->render_free (r); + + if (!fits_width) + hl = hr = 0; + if (!fits_length) + ht = hb = 0; + + r = t->class->render_init (t, d, hl, hr, ht, hb); } + t->class->area (r, &tw, &th); if (!(flags & SOMF_NO_SPACING) && d->cp_y != 0) d->cp_y += d->font_height; @@ -184,22 +253,29 @@ output_entity (struct outp_driver *driver, struct som_entity *entity) if (cs != SOM_COL_NONE && 2 * (tw + d->prop_em_width) <= d->width && nr - (ht + hb) > 5) - render_columns (); + render_columns (r, d, t, tw, th, hl, hr, ht, hb); else if (tw < d->width && th + d->cp_y < d->length) - render_simple (); + render_simple (r, d, t, tw, th, hl, hr, ht, hb); else - render_segments (); + render_segments (r, d, t, tw, th, hl, hr, ht, hb); - t->class->set_headers (hl, hr, ht, hb); + t->class->render_free (r); } /* Render the table into multiple columns. */ static void -render_columns (void) +render_columns (void *r, struct outp_driver *d, struct som_entity *t, + int tw, int th UNUSED, + int hl UNUSED, int hr UNUSED, int ht, int hb) { int y0, y1; int max_len = 0; int index = 0; + int nc, nr; + int cs; + + t->class->count (t, &nc, &nr); + t->class->columns (t, &cs); assert (cs == SOM_COL_DOWN); assert (d->cp_x == 0); @@ -208,7 +284,7 @@ render_columns (void) { int len; - t->class->cumulate (SOM_ROWS, y0, &y1, d->length - d->cp_y, &len); + t->class->cumulate (r, SOM_ROWS, y0, &y1, d->length - d->cp_y, &len); if (y0 == y1) { @@ -220,8 +296,9 @@ render_columns (void) if (len > max_len) max_len = len; - t->class->title (index++, 0); - t->class->render (0, y0, nc, y1); + t->class->title (r, index++, 0, t->table_num, t->subtable_num, + t->command_name); + t->class->render (r, 0, y0, nc, y1); d->cp_x += tw + 2 * d->prop_em_width; if (d->cp_x + tw > d->width) @@ -242,33 +319,44 @@ render_columns (void) /* Render the table by itself on the current page. */ static void -render_simple (void) +render_simple (void *r, struct outp_driver *d, struct som_entity *t, + int tw, int th, + int hl, int hr, int ht, int hb) { + int nc, nr; + + t->class->count (t, &nc, &nr); + assert (d->cp_x == 0); assert (tw < d->width && th + d->cp_y < d->length); - t->class->title (0, 0); - t->class->render (hl, ht, nc - hr, nr - hb); + t->class->title (r, 0, 0, t->table_num, t->subtable_num, t->command_name); + t->class->render (r, hl, ht, nc - hr, nr - hb); d->cp_y += th; } /* General table breaking routine. */ static void -render_segments (void) +render_segments (void *r, struct outp_driver *d, struct som_entity *t, + int tw UNUSED, int th UNUSED, + int hl, int hr, int ht, int hb) { int count = 0; int x_index; int x0, x1; + int nc, nr; + assert (d->cp_x == 0); + t->class->count (t, &nc, &nr); for (x_index = 0, x0 = hl; x0 < nc - hr; x0 = x1, x_index++) { int y_index; int y0, y1; - t->class->cumulate (SOM_COLUMNS, x0, &x1, d->width, NULL); + t->class->cumulate (r, SOM_COLUMNS, x0, &x1, d->width, NULL); if (x_index == 0 && x1 != nc - hr) x_index++; @@ -279,7 +367,7 @@ render_segments (void) if (count++ != 0 && d->cp_y != 0) d->cp_y += d->font_height; - t->class->cumulate (SOM_ROWS, y0, &y1, d->length - d->cp_y, &len); + t->class->cumulate (r, SOM_ROWS, y0, &y1, d->length - d->cp_y, &len); if (y_index == 0 && y1 != nr - hb) y_index++; @@ -290,9 +378,10 @@ render_segments (void) } else { - t->class->title (x_index ? x_index : y_index, - x_index ? y_index : 0); - t->class->render (x0, y0, x1, y1); + t->class->title (r, x_index ? x_index : y_index, + x_index ? y_index : 0, + t->table_num, t->subtable_num, t->command_name); + t->class->render (r, x0, y0, x1, y1); d->cp_y += len; } diff --git a/src/output/manager.h b/src/output/manager.h index 58d0c12d..e7276982 100644 --- a/src/output/manager.h +++ b/src/output/manager.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,8 +37,7 @@ enum som_type { - SOM_TABLE, - SOM_CHART + SOM_TABLE } ; /* Entity (Table or Chart) . */ @@ -46,9 +45,15 @@ struct som_entity { const struct som_table_class *class; /* Table class. */ enum som_type type; /* Table or Chart */ - void *ext; /* Owned by */ + void *ext; /* Owned by table or chart class. */ + int table_num; /* Table number. */ + int subtable_num; /* Sub-table number. */ + char *command_name; /* Command that yielded this output. */ }; +struct som_entity *som_entity_clone (struct som_entity *); +void som_entity_destroy (struct som_entity *); + /* Group styles. */ enum { @@ -59,8 +64,8 @@ enum /* Cumulation types. */ enum { - SOM_ROWS, SOM_ROW = SOM_ROWS, /* Rows. */ - SOM_COLUMNS, SOM_COLUMN = SOM_COLUMNS /* Columns. */ + SOM_ROWS, /* Rows. */ + SOM_COLUMNS /* Columns. */ }; /* Flags. */ @@ -75,40 +80,29 @@ enum struct outp_driver; struct som_table_class { - /* Set table, driver. */ - void (*table) (struct som_entity *); - void (*driver) (struct outp_driver *); - - /* Query columns and rows. */ - void (*count) (int *n_columns, int *n_rows); - void (*area) (int *horiz, int *vert); - void (*width) (int *columns); - void (*height) (int *rows); - void (*columns) (int *style); - int (*breakable) (int row); /* ? */ - void (*headers) (int *l, int *r, int *t, int *b); - void (*join) (int *(column[2]), int *(row[2])); /* ? */ - void (*cumulate) (int cumtype, int start, int *end, int max, int *actual); - void (*flags) (unsigned *); - bool (*fits_width) (int width); - bool (*fits_length) (int length); - - /* Set columns and rows. */ - void (*set_width) (int column, int width); /* ? */ - void (*set_height) (int row, int height); /* ? */ - void (*set_headers) (int l, int r, int t, int b); - - /* Rendering. */ - void (*title) (int x, int y); - void (*render) (int x1, int y1, int x2, int y2); + /* Operations on tables. */ + void (*count) (struct som_entity *, int *n_columns, int *n_rows); + void (*columns) (struct som_entity *, int *style); + void (*headers) (struct som_entity *, int *l, int *r, int *t, int *b); + void (*flags) (struct som_entity *, unsigned *); + + /* Creating and freeing driver-specific table rendering data. */ + void *(*render_init) (struct som_entity *, struct outp_driver *, + int l, int r, int t, int b); + void (*render_free) (void *); + + /* Rendering operations. */ + void (*area) (void *, int *horiz, int *vert); + void (*cumulate) (void *, int cumtype, int start, int *end, + int max, int *actual); + void (*title) (void *, int x, int y, int table_num, int subtable_num, + const char *command_name); + void (*render) (void *, int x1, int y1, int x2, int y2); }; -/* Table indexes. */ -extern int table_num; -extern int subtable_num; - /* Submission. */ void som_new_series (void); +void som_set_command_name (const char *); void som_submit (struct som_entity *t); /* Miscellaneous. */ diff --git a/src/output/odt.c b/src/output/odt.c new file mode 100644 index 00000000..8471b6b3 --- /dev/null +++ b/src/output/odt.c @@ -0,0 +1,583 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +/* A driver for creating OpenDocument Format text files from PSPP's output */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "xalloc.h" + +#include "error.h" + +#define _xml(X) (const xmlChar *)(X) + + +struct odf_driver_options +{ + struct outp_driver *driver; + + char *file_name; /* Output file name. */ + bool debug; +}; + + +struct odt_driver_ext +{ + /* The name of the temporary directory used to construct the ODF */ + char *dirname; + + /* Writer for the content.xml file */ + xmlTextWriterPtr content_wtr; + + /* Writer fot the manifest.xml file */ + xmlTextWriterPtr manifest_wtr; + + struct odf_driver_options opts; +}; + + + +/* Create the "mimetype" file needed by ODF */ +static void +create_mimetype (const char *dirname) +{ + FILE *fp; + struct string filename; + ds_init_cstr (&filename, dirname); + ds_put_cstr (&filename, "/mimetype"); + fp = fopen (ds_cstr (&filename), "w"); + ds_destroy (&filename); + + assert (fp); + fprintf (fp, "application/vnd.oasis.opendocument.text"); + fclose (fp); +} + +/* Create a new XML file called FILENAME in the temp directory, and return a writer for it */ +static xmlTextWriterPtr +create_writer (const struct odt_driver_ext *driver, const char *filename) +{ + char *copy = NULL; + xmlTextWriterPtr w; + struct string str; + ds_init_cstr (&str, driver->dirname); + ds_put_cstr (&str, "/"); + ds_put_cstr (&str, filename); + + /* dirname modifies its argument, so we must copy it */ + copy = xstrdup (ds_cstr (&str)); + mkdir (dirname (copy), 0700); + free (copy); + + w = xmlNewTextWriterFilename (ds_cstr (&str), 0); + + ds_destroy (&str); + + xmlTextWriterStartDocument (w, NULL, "UTF-8", NULL); + + return w; +} + + +static void +register_file (struct odt_driver_ext *x, const char *filename) +{ + assert (x->manifest_wtr); + xmlTextWriterStartElement (x->manifest_wtr, _xml("manifest:file-entry")); + xmlTextWriterWriteAttribute (x->manifest_wtr, _xml("manifest:media-type"), _xml("text/xml")); + xmlTextWriterWriteAttribute (x->manifest_wtr, _xml("manifest:full-path"), _xml (filename)); + xmlTextWriterEndElement (x->manifest_wtr); +} + +static void +write_style_data (struct odt_driver_ext *x) +{ + xmlTextWriterPtr w = create_writer (x, "styles.xml"); + register_file (x, "styles.xml"); + + xmlTextWriterStartElement (w, _xml ("office:document-styles")); + xmlTextWriterWriteAttribute (w, _xml ("xmlns:office"), + _xml ("urn:oasis:names:tc:opendocument:xmlns:office:1.0")); + + xmlTextWriterWriteAttribute (w, _xml ("xmlns:style"), + _xml ("urn:oasis:names:tc:opendocument:xmlns:style:1.0")); + + xmlTextWriterWriteAttribute (w, _xml ("xmlns:fo"), + _xml ("urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0") ); + + xmlTextWriterWriteAttribute (w, _xml ("office:version"), _xml ("1.1")); + + + + xmlTextWriterStartElement (w, _xml ("office:styles")); + + + { + xmlTextWriterStartElement (w, _xml ("style:style")); + xmlTextWriterWriteAttribute (w, _xml ("style:name"), + _xml ("Standard")); + + xmlTextWriterWriteAttribute (w, _xml ("style:family"), + _xml ("paragraph")); + + xmlTextWriterWriteAttribute (w, _xml ("style:class"), + _xml ("text")); + + xmlTextWriterEndElement (w); /* style:style */ + } + + { + xmlTextWriterStartElement (w, _xml ("style:style")); + xmlTextWriterWriteAttribute (w, _xml ("style:name"), + _xml ("Table_20_Contents")); + + xmlTextWriterWriteAttribute (w, _xml ("style:display-name"), + _xml ("Table Contents")); + + xmlTextWriterWriteAttribute (w, _xml ("style:family"), + _xml ("paragraph")); + + xmlTextWriterWriteAttribute (w, _xml ("style:parent-style-name"), + _xml ("Standard")); + + xmlTextWriterWriteAttribute (w, _xml ("style:class"), + _xml ("extra")); + + xmlTextWriterEndElement (w); /* style:style */ + } + + { + xmlTextWriterStartElement (w, _xml ("style:style")); + xmlTextWriterWriteAttribute (w, _xml ("style:name"), + _xml ("Table_20_Heading")); + + xmlTextWriterWriteAttribute (w, _xml ("style:display-name"), + _xml ("Table Heading")); + + xmlTextWriterWriteAttribute (w, _xml ("style:family"), + _xml ("paragraph")); + + xmlTextWriterWriteAttribute (w, _xml ("style:parent-style-name"), + _xml ("Table_20_Contents")); + + xmlTextWriterWriteAttribute (w, _xml ("style:class"), + _xml ("extra")); + + + xmlTextWriterStartElement (w, _xml ("style:text-properties")); + xmlTextWriterWriteAttribute (w, _xml ("fo:font-weight"), _xml ("bold")); + xmlTextWriterWriteAttribute (w, _xml ("style:font-weight-asian"), _xml ("bold")); + xmlTextWriterWriteAttribute (w, _xml ("style:font-weight-complex"), _xml ("bold")); + xmlTextWriterEndElement (w); /* style:text-properties */ + + xmlTextWriterEndElement (w); /* style:style */ + } + + + xmlTextWriterEndElement (w); /* office:styles */ + xmlTextWriterEndElement (w); /* office:document-styles */ + + xmlTextWriterEndDocument (w); + xmlFreeTextWriter (w); +} + +static void +write_meta_data (struct odt_driver_ext *x) +{ + xmlTextWriterPtr w = create_writer (x, "meta.xml"); + register_file (x, "meta.xml"); + + xmlTextWriterStartElement (w, _xml ("office:document-meta")); + xmlTextWriterWriteAttribute (w, _xml ("xmlns:office"), _xml ("urn:oasis:names:tc:opendocument:xmlns:office:1.0")); + xmlTextWriterWriteAttribute (w, _xml ("xmlns:dc"), _xml ("http://purl.org/dc/elements/1.1/")); + xmlTextWriterWriteAttribute (w, _xml ("xmlns:meta"), _xml ("urn:oasis:names:tc:opendocument:xmlns:meta:1.0")); + xmlTextWriterWriteAttribute (w, _xml ("xmlns:ooo"), _xml("http://openoffice.org/2004/office")); + xmlTextWriterWriteAttribute (w, _xml ("office:version"), _xml("1.1")); + + xmlTextWriterStartElement (w, _xml ("office:meta")); + { + xmlTextWriterStartElement (w, _xml ("meta:generator")); + xmlTextWriterWriteString (w, _xml (stat_version)); + xmlTextWriterEndElement (w); + } + + + { + char buf[30]; + struct passwd *pw = getpwuid (getuid ()); + time_t t = time (NULL); + struct tm *tm = localtime (&t); + + strftime (buf, 30, "%Y-%m-%dT%H:%M:%S", tm); + + xmlTextWriterStartElement (w, _xml ("meta:initial-creator")); + xmlTextWriterWriteString (w, _xml (strtok (pw->pw_gecos, ","))); + xmlTextWriterEndElement (w); + + xmlTextWriterStartElement (w, _xml ("meta:creation-date")); + xmlTextWriterWriteString (w, _xml (buf)); + xmlTextWriterEndElement (w); + + xmlTextWriterStartElement (w, _xml ("dc:creator")); + xmlTextWriterWriteString (w, _xml (strtok (pw->pw_gecos, ","))); + + xmlTextWriterEndElement (w); + + xmlTextWriterStartElement (w, _xml ("dc:date")); + xmlTextWriterWriteString (w, _xml (buf)); + xmlTextWriterEndElement (w); + } + + xmlTextWriterEndElement (w); + xmlTextWriterEndElement (w); + xmlTextWriterEndDocument (w); + xmlFreeTextWriter (w); +} + +enum +{ + output_file_arg, + boolean_arg, +}; + +static const struct outp_option option_tab[] = +{ + {"output-file", output_file_arg,0}, + + {"debug", boolean_arg, 1}, + + {NULL, 0, 0}, +}; + +static bool +handle_option (void *options_, const char *key, const struct string *val) +{ + struct odf_driver_options *options = options_; + struct outp_driver *this = options->driver; + int subcat; + char *value = ds_cstr (val); + + switch (outp_match_keyword (key, option_tab, &subcat)) + { + case -1: + error (0, 0, + _("unknown configuration parameter `%s' for %s device " + "driver"), key, this->class->name); + break; + case output_file_arg: + free (options->file_name); + options->file_name = xstrdup (value); + break; + case boolean_arg: + if (!strcmp (value, "on") || !strcmp (value, "true") + || !strcmp (value, "yes") || atoi (value)) + options->debug = true; + else if (!strcmp (value, "off") || !strcmp (value, "false") + || !strcmp (value, "no") || !strcmp (value, "0")) + options->debug = false; + else + { + error (0, 0, _("boolean value expected for %s"), key); + return false; + } + break; + + default: + NOT_REACHED (); + } + + return true; +} + + +static bool +odt_open_driver (const char *name, int types, struct substring option_string) +{ + struct odt_driver_ext *x; + struct outp_driver *this = outp_allocate_driver (&odt_class, name, types); + + this->ext = x = xmalloc (sizeof *x); + + x->opts.driver = this; + x->opts.file_name = xstrdup ("pspp.pdt"); + x->opts.debug = false; + + outp_parse_options (this->name, option_string, handle_option, &x->opts); + + outp_register_driver (this); + + x->dirname = xstrdup ("odt-XXXXXX"); + mkdtemp (x->dirname); + + create_mimetype (x->dirname); + + /* Create the manifest */ + x->manifest_wtr = create_writer (x, "META-INF/manifest.xml"); + + xmlTextWriterStartElement (x->manifest_wtr, _xml("manifest:manifest")); + xmlTextWriterWriteAttribute (x->manifest_wtr, _xml("xmlns:manifest"), + _xml("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0")); + + + /* Add a manifest entry for the document as a whole */ + xmlTextWriterStartElement (x->manifest_wtr, _xml("manifest:file-entry")); + xmlTextWriterWriteAttribute (x->manifest_wtr, _xml("manifest:media-type"), _xml("application/vnd.oasis.opendocument.text")); + xmlTextWriterWriteAttribute (x->manifest_wtr, _xml("manifest:full-path"), _xml("/")); + xmlTextWriterEndElement (x->manifest_wtr); + + + write_meta_data (x); + write_style_data (x); + + x->content_wtr = create_writer (x, "content.xml"); + register_file (x, "content.xml"); + + + /* Some necessary junk at the start */ + xmlTextWriterStartElement (x->content_wtr, _xml("office:document-content")); + xmlTextWriterWriteAttribute (x->content_wtr, _xml("xmlns:office"), + _xml("urn:oasis:names:tc:opendocument:xmlns:office:1.0")); + + xmlTextWriterWriteAttribute (x->content_wtr, _xml("xmlns:text"), + _xml("urn:oasis:names:tc:opendocument:xmlns:text:1.0")); + + xmlTextWriterWriteAttribute (x->content_wtr, _xml("xmlns:table"), + _xml("urn:oasis:names:tc:opendocument:xmlns:table:1.0")); + + xmlTextWriterWriteAttribute (x->content_wtr, _xml("office:version"), _xml("1.1")); + + xmlTextWriterStartElement (x->content_wtr, _xml("office:body")); + xmlTextWriterStartElement (x->content_wtr, _xml("office:text")); + + + + /* Close the manifest */ + xmlTextWriterEndElement (x->manifest_wtr); + xmlTextWriterEndDocument (x->manifest_wtr); + xmlFreeTextWriter (x->manifest_wtr); + + return true; +} + +static bool +odt_close_driver (struct outp_driver *this) +{ + struct string zip_cmd; + struct string rm_cmd; + struct odt_driver_ext *x = this->ext; + + xmlTextWriterEndElement (x->content_wtr); /* office:text */ + xmlTextWriterEndElement (x->content_wtr); /* office:body */ + xmlTextWriterEndElement (x->content_wtr); /* office:document-content */ + + xmlTextWriterEndDocument (x->content_wtr); + xmlFreeTextWriter (x->content_wtr); + + /* Zip up the directory */ + ds_init_empty (&zip_cmd); + ds_put_format (&zip_cmd, + "cd %s ; rm -f ../%s; zip -q -X ../%s mimetype; zip -q -X -u -r ../pspp.odt .", + x->dirname, x->opts.file_name, x->opts.file_name); + system (ds_cstr (&zip_cmd)); + ds_destroy (&zip_cmd); + + + if ( !x->opts.debug ) + { + /* Remove the temp dir */ + ds_init_empty (&rm_cmd); + ds_put_format (&rm_cmd, "rm -r %s", x->dirname); + system (ds_cstr (&rm_cmd)); + ds_destroy (&rm_cmd); + } + else + fprintf (stderr, "Not removing directory %s\n", x->dirname); + + free (x->dirname); + free (x); + + return true; +} + +static void +odt_open_page (struct outp_driver *this UNUSED) +{ +} + +static void +odt_close_page (struct outp_driver *this UNUSED) +{ +} + +static void +odt_output_chart (struct outp_driver *this UNUSED, const struct chart *chart UNUSED) +{ + printf ("%s\n", __FUNCTION__); +} + + +/* Submit a table to the ODT driver */ +static void +odt_submit (struct outp_driver *this, struct som_entity *e) +{ + int r, c; + + struct odt_driver_ext *x = this->ext; + struct tab_table *tab = e->ext; + + + /* Write a heading for the table */ + xmlTextWriterStartElement (x->content_wtr, _xml("text:h")); + xmlTextWriterWriteFormatAttribute (x->content_wtr, _xml("text:level"), "%d", e->subtable_num == 1 ? 2 : 3); + xmlTextWriterWriteString (x->content_wtr, _xml (tab->title) ); + xmlTextWriterEndElement (x->content_wtr); + + /* Start table */ + xmlTextWriterStartElement (x->content_wtr, _xml("table:table")); + xmlTextWriterWriteFormatAttribute (x->content_wtr, _xml("table:name"), + "TABLE-%d.%d", e->table_num, e->subtable_num); + + + /* Start column definitions */ + xmlTextWriterStartElement (x->content_wtr, _xml("table:table-column")); + xmlTextWriterWriteFormatAttribute (x->content_wtr, _xml("table:number-columns-repeated"), "%d", tab_nc (tab)); + xmlTextWriterEndElement (x->content_wtr); + + + /* Deal with row headers */ + if ( tab_t (tab) > 0) + xmlTextWriterStartElement (x->content_wtr, _xml("table:table-header-rows")); + + + /* Write all the rows */ + for (r = 0 ; r < tab_nr (tab); ++r) + { + int spanned_columns = 0; + /* Start row definition */ + xmlTextWriterStartElement (x->content_wtr, _xml("table:table-row")); + + /* Write all the columns */ + for (c = 0 ; c < tab_nc (tab) ; ++c) + { + char *s = NULL; + unsigned int opts = tab->ct[tab_nc (tab) * r + c]; + struct substring ss = tab->cc[tab_nc (tab) * r + c]; + + if (opts & TAB_EMPTY) + { + xmlTextWriterStartElement (x->content_wtr, _xml("table:table-cell")); + xmlTextWriterEndElement (x->content_wtr); + continue; + } + + if ( opts & TAB_JOIN) + { + if ( spanned_columns == 0) + { + struct tab_joined_cell *j = (struct tab_joined_cell*) ss_data (ss); + s = ss_xstrdup (j->contents); + } + } + else + s = ss_xstrdup (ss); + + if ( spanned_columns == 0 ) + { + xmlTextWriterStartElement (x->content_wtr, _xml("table:table-cell")); + xmlTextWriterWriteAttribute (x->content_wtr, _xml("office:value-type"), _xml("string")); + + if ( opts & TAB_JOIN ) + { + struct tab_joined_cell *j = (struct tab_joined_cell*) ss_data (ss); + spanned_columns = j->x2 - j->x1; + + xmlTextWriterWriteFormatAttribute (x->content_wtr, + _xml("table:number-columns-spanned"), + "%d", spanned_columns); + } + + xmlTextWriterStartElement (x->content_wtr, _xml("text:p")); + + if ( r < tab_t (tab) || c < tab_l (tab) ) + xmlTextWriterWriteAttribute (x->content_wtr, _xml("text:style-name"), _xml("Table_20_Heading")); + else + xmlTextWriterWriteAttribute (x->content_wtr, _xml("text:style-name"), _xml("Table_20_Contents")); + + xmlTextWriterWriteString (x->content_wtr, _xml (s)); + + xmlTextWriterEndElement (x->content_wtr); /* text:p */ + xmlTextWriterEndElement (x->content_wtr); /* table:table-cell */ + } + else + { + xmlTextWriterStartElement (x->content_wtr, _xml("table:covered-table-cell")); + xmlTextWriterEndElement (x->content_wtr); + } + if ( opts & TAB_JOIN ) + spanned_columns --; + + free (s); + } + + xmlTextWriterEndElement (x->content_wtr); /* row */ + + if ( tab_t (tab) > 0 && r == tab_t (tab) - 1) + xmlTextWriterEndElement (x->content_wtr); /* table-header-rows */ + } + + xmlTextWriterEndElement (x->content_wtr); /* table */ +} + + +/* ODT driver class. */ +const struct outp_class odt_class = +{ + "odf", + 1, + + odt_open_driver, + odt_close_driver, + + odt_open_page, + odt_close_page, + NULL, + + odt_output_chart, + odt_submit, + + NULL, + NULL, + NULL, +}; diff --git a/src/output/output.c b/src/output/output.c index 843b0d4e..2f4788f9 100644 --- a/src/output/output.c +++ b/src/output/output.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,12 +39,6 @@ #include "gettext.h" #define _(msgid) gettext (msgid) -/* FIXME? Should the output configuration format be changed to - drivername:classname:devicetype:options, where devicetype is zero - or more of screen, printer, listing? */ - -/* FIXME: Have the reentrancy problems been solved? */ - /* Where the output driver name came from. */ enum { @@ -79,7 +73,7 @@ struct outp_driver_class_list }; static struct outp_driver_class_list *outp_class_list; -static struct outp_driver *outp_driver_list; +static struct ll_list outp_driver_list = LL_INITIALIZER (outp_driver_list); char *outp_title; char *outp_subtitle; @@ -224,18 +218,26 @@ find_defn_value (const char *key) return getenv (key); } +static void +insert_defn_value (const char *var, struct string *dst, void *aux UNUSED) +{ + const char *value = find_defn_value (var); + if (value != NULL) + ds_put_cstr (dst, value); +} + /* Initializes global variables. */ void outp_init (void) { - extern struct outp_class ascii_class; - extern struct outp_class postscript_class; - char def[] = "default"; add_class (&html_class); - add_class (&postscript_class); add_class (&ascii_class); +#ifdef HAVE_CAIRO + add_class (&cairo_class); +#endif + add_class (&odt_class); add_name (def, &def[strlen (def)], OUTP_S_INIT_FILE); } @@ -345,13 +347,13 @@ exit: if (result) { - if (outp_driver_list == NULL) + if (ll_is_empty (&outp_driver_list)) error (0, 0, _("no active output drivers")); } else error (0, 0, _("error reading device definition file")); - if (!result || outp_driver_list == NULL) + if (!result || ll_is_empty (&outp_driver_list)) init_default_drivers (); } @@ -413,7 +415,7 @@ outp_configure_macro (char *bp) ep++; ds_init_cstr (&d->value, ep); - fn_interp_vars (ds_ss (&d->value), find_defn_value, &d->value); + fn_interp_vars (ds_ss (&d->value), insert_defn_value, NULL, &d->value); d->next = outp_macros; d->prev = NULL; if (outp_macros) @@ -421,29 +423,18 @@ outp_configure_macro (char *bp) outp_macros = d; } -/* Destroys all the drivers in driver list *DL and sets *DL to - NULL. */ -static void -destroy_list (struct outp_driver ** dl) -{ - struct outp_driver *d, *next; - - for (d = *dl; d; d = next) - { - destroy_driver (d); - next = d->next; - free (d); - } - *dl = NULL; -} - /* Closes all the output drivers. */ void outp_done (void) { struct outp_driver_class_list *n = outp_class_list ; outp_configure_clear (); - destroy_list (&outp_driver_list); + while (!ll_is_empty (&outp_driver_list)) + { + struct outp_driver *d = ll_data (ll_head (&outp_driver_list), + struct outp_driver, node); + destroy_driver (d); + } while (n) { @@ -611,10 +602,9 @@ get_option_token (struct substring *s, const char *driver_name, } bool -outp_parse_options (struct substring options, - bool (*callback) (struct outp_driver *, const char *key, - const struct string *value), - struct outp_driver *driver) +outp_parse_options (const char *driver_name, struct substring options, + bool (*callback) (void *aux, const char *key, + const struct string *value), void *aux) { struct string key = DS_EMPTY_INITIALIZER; struct string value = DS_EMPTY_INITIALIZER; @@ -627,7 +617,7 @@ outp_parse_options (struct substring options, if (ss_is_empty (left)) break; - if (!get_option_token (&left, driver->name, &key)) + if (!get_option_token (&left, driver_name, &key)) break; ss_ltrim (&left, ss_cstr (CC_SPACES)); @@ -635,15 +625,15 @@ outp_parse_options (struct substring options, { error (0, 0, _("syntax error expecting `=' " "parsing options for driver \"%s\""), - driver->name); + driver_name); break; } ss_ltrim (&left, ss_cstr (CC_SPACES)); - if (!get_option_token (&left, driver->name, &value)) + if (!get_option_token (&left, driver_name, &value)) break; - ok = callback (driver, ds_cstr (&key), &value); + ok = callback (aux, ds_cstr (&key), &value); } while (ok); @@ -658,8 +648,7 @@ static struct outp_driver * find_driver (char *name) { struct outp_driver *d; - - for (d = outp_driver_list; d; d = d->next) + ll_for_each (d, struct outp_driver, node, &outp_driver_list) if (!strcmp (d->name, name)) return d; return NULL; @@ -671,11 +660,10 @@ static void configure_driver (struct substring driver_name, struct substring class_name, struct substring device_type, struct substring options) { - struct outp_driver *d, *iter; struct outp_driver_class_list *c; - struct substring token; size_t save_idx = 0; + char *name; int device; /* Find class. */ @@ -702,38 +690,67 @@ configure_driver (struct substring driver_name, struct substring class_name, error (0, 0, _("unknown device type `%.*s'"), (int) ss_length (token), ss_data (token)); - /* Open the device. */ - d = xmalloc (sizeof *d); - d->next = d->prev = NULL; - d->class = c->class; - d->name = ss_xstrdup (driver_name); + /* Open driver. */ + name = ss_xstrdup (driver_name); + if (!c->class->open_driver (name, device, options)) + error (0, 0, _("cannot initialize output driver `%s' of class `%s'"), + name, c->class->name); + free (name); +} + +/* Allocates and returns a new outp_driver for a device with the + given NAME and CLASS and the OUTP_DEV_* type(s) in TYPES + + This function is intended to be used by output drivers, not + by their clients. */ +struct outp_driver * +outp_allocate_driver (const struct outp_class *class, + const char *name, int types) +{ + struct outp_driver *d = xmalloc (sizeof *d); + d->class = class; + d->name = xstrdup (name); d->page_open = false; - d->device = device; + d->device = types; d->cp_x = d->cp_y = 0; d->ext = NULL; - d->prc = NULL; + return d; +} - /* Open driver. */ - if (!d->class->open_driver (d, options)) - { - error (0, 0, _("cannot initialize output driver `%s' of class `%s'"), - d->name, d->class->name); - free (d->name); - free (d); - return; - } +/* Frees driver D and the data that it owns directly. The + driver's class must already have unregistered D (if it was + registered) and freed data private to its class. + + This function is intended to be used by output drivers, not + by their clients. */ +void +outp_free_driver (struct outp_driver *d) +{ + free (d->name); + free (d); +} + +/* Adds D to the list of drivers that will be used for output. */ +void +outp_register_driver (struct outp_driver *d) +{ + struct outp_driver *victim; /* Find like-named driver and delete. */ - iter = find_driver (d->name); - if (iter != NULL) - destroy_driver (iter); + victim = find_driver (d->name); + if (victim != NULL) + destroy_driver (victim); - /* Add to list. */ - d->next = outp_driver_list; - d->prev = NULL; - if (outp_driver_list != NULL) - outp_driver_list->prev = d; - outp_driver_list = d; + /* Add D to list. */ + ll_push_tail (&outp_driver_list, &d->node); +} + +/* Remove driver D from the list of drivers that will be used for + output. */ +void +outp_unregister_driver (struct outp_driver *d) +{ + ll_remove (&d->node); } /* String LINE is in format: @@ -748,7 +765,7 @@ outp_configure_driver_line (struct substring line_) size_t save_idx; size_t i; - fn_interp_vars (line_, find_defn_value, &line); + fn_interp_vars (line_, insert_defn_value, NULL, &line); save_idx = 0; for (i = 0; i < 4; i++) @@ -772,26 +789,10 @@ static void destroy_driver (struct outp_driver *d) { outp_close_page (d); - if (d->class) - { - struct outp_driver_class_list *c; - - d->class->close_driver (d); - - for (c = outp_class_list; c; c = c->next) - if (c->class == d->class) - break; - assert (c != NULL); - } - free (d->name); - - /* Remove this driver from the global driver list. */ - if (d->prev) - d->prev->next = d->next; - if (d->next) - d->next->prev = d->prev; - if (d == outp_driver_list) - outp_driver_list = d->next; + if (d->class && d->class->close_driver) + d->class->close_driver (d); + outp_unregister_driver (d); + outp_free_driver (d); } /* Tries to match S as one of the keywords in TAB, with @@ -1087,17 +1088,17 @@ outp_get_paper_size (const char *size, int *h, int *v) struct outp_driver * outp_drivers (struct outp_driver *d) { - for (;;) + do { - if (d == NULL) - d = outp_driver_list; - else - d = d->next; + struct ll *next; + + next = d == NULL ? ll_head (&outp_driver_list) : ll_next (&d->node); + if (next == ll_null (&outp_driver_list)) + return NULL; - if (d == NULL - || (d->device == 0 || (d->device & disabled_devices) != d->device)) - break; + d = ll_data (next, struct outp_driver, node); } + while (d->device != 0 && (d->device & disabled_devices) == d->device); return d; } diff --git a/src/output/output.h b/src/output/output.h index fc668740..398781f0 100644 --- a/src/output/output.h +++ b/src/output/output.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,9 +17,9 @@ #ifndef OUTPUT_OUTPUT_H #define OUTPUT_OUTPUT_H 1 +#include #include - /* Line styles. */ enum outp_line_style { @@ -65,7 +65,8 @@ struct outp_class const char *name; /* Name of this driver class. */ int special; /* Boolean value. */ - bool (*open_driver) (struct outp_driver *, struct substring options); + bool (*open_driver) (const char *name, int types, + struct substring options); bool (*close_driver) (struct outp_driver *); void (*open_page) (struct outp_driver *); @@ -73,6 +74,8 @@ struct outp_class void (*flush) (struct outp_driver *); + void (*output_chart) (struct outp_driver *, const struct chart *); + /* special != 0 only. */ void (*submit) (struct outp_driver *, struct som_entity *); @@ -83,8 +86,6 @@ struct outp_class void (*text_metrics) (struct outp_driver *, const struct outp_text *, int *width, int *height); void (*text_draw) (struct outp_driver *, const struct outp_text *); - void (*initialise_chart)(struct outp_driver *, struct chart *); - void (*finalise_chart)(struct outp_driver *, struct chart *); }; /* Device types. */ @@ -99,7 +100,7 @@ enum /* Defines the configuration of an output driver. */ struct outp_driver { - struct outp_driver *next, *prev; /* List of drivers. */ + struct ll node; /* Node in list of drivers. */ const struct outp_class *class; /* Driver class. */ char *name; /* Name of this driver. */ bool page_open; /* 1=page is open, 0=page is closed. */ @@ -114,7 +115,6 @@ struct outp_driver int vert_line_width[OUTP_L_COUNT]; /* Width of vertical lines. */ void *ext; /* Private extension record. */ - void *prc; /* Per-procedure extension record. */ }; /* Option structure for the keyword recognizer. */ @@ -131,9 +131,15 @@ extern char *outp_title; extern char *outp_subtitle; void outp_init (void); +void outp_done (void); void outp_read_devices (void); void outp_configure_driver_line (struct substring); -void outp_done (void); + +struct outp_driver *outp_allocate_driver (const struct outp_class *class, + const char *name, int types); +void outp_free_driver (struct outp_driver *); +void outp_register_driver (struct outp_driver *); +void outp_unregister_driver (struct outp_driver *); void outp_configure_clear (void); void outp_configure_add (char *); @@ -144,10 +150,10 @@ void outp_list_classes (void); void outp_enable_device (bool enable, int device); struct outp_driver *outp_drivers (struct outp_driver *); -bool outp_parse_options (struct substring options, - bool (*) (struct outp_driver *, const char *key, - const struct string *value), - struct outp_driver *); +bool outp_parse_options (const char *driver_name, struct substring options, + bool (*callback) (void *aux, const char *key, + const struct string *value), + void *aux); int outp_match_keyword (const char *, const struct outp_option *, int *); int outp_evaluate_dimension (const char *); @@ -163,4 +169,11 @@ int outp_string_width (struct outp_driver *, const char *, enum outp_font); /* Imported from som-frnt.c. */ void som_destroy_driver (struct outp_driver *); +/* Common drivers. */ +extern const struct outp_class ascii_class; +#ifdef HAVE_CAIRO +extern const struct outp_class cairo_class; +#endif +extern const struct outp_class odt_class; + #endif /* output/output.h */ diff --git a/src/output/postscript.c b/src/output/postscript.c deleted file mode 100644 index 11116b9b..00000000 --- a/src/output/postscript.c +++ /dev/null @@ -1,1446 +0,0 @@ -/* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "afm.h" -#include "chart.h" -#include "error.h" -#include "manager.h" -#include "output.h" - -#include "intprops.h" -#include "minmax.h" -#include "xalloc.h" - -#include "gettext.h" -#define _(msgid) gettext (msgid) - -/* PostScript driver options: (defaults listed first) - - output-file="pspp.ps" - - paper-size=letter (see "papersize" file) - orientation=portrait|landscape - headers=on|off - - left-margin=0.5in - right-margin=0.5in - top-margin=0.5in - bottom-margin=0.5in - - prop-font=Times-Roman - emph-font=Times-Italic - fixed-font=Courier - font-size=10000 - - line-gutter=1pt - line-spacing=1pt - line-width=0.5pt - */ - -/* The number of `psus' (PostScript driver UnitS) per inch. */ -#define PSUS 72000 - -/* A PostScript font. */ -struct font - { - struct afm *metrics; /* Metrics. */ - char *embed_fn; /* Name of file to embed. */ - char *encoding_fn; /* Name of file with encoding. */ - }; - -/* PostScript output driver extension record. */ -struct ps_driver_ext - { - char *file_name; /* Output file name. */ - FILE *file; /* Output file. */ - - bool draw_headers; /* Draw headers at top of page? */ - int page_number; /* Current page number. */ - - bool portrait; /* Portrait mode? */ - int paper_width; /* Width of paper before dropping margins. */ - int paper_length; /* Length of paper before dropping margins. */ - int left_margin; /* Left margin in psus. */ - int right_margin; /* Right margin in psus. */ - int top_margin; /* Top margin in psus. */ - int bottom_margin; /* Bottom margin in psus. */ - - int line_gutter; /* Space around lines. */ - int line_space; /* Space between lines. */ - int line_width; /* Width of lines. */ - - struct font *fonts[OUTP_FONT_CNT]; - int last_font; /* Index of last font set with setfont. */ - }; - -/* Transform logical y-ordinate Y into a page ordinate. */ -#define YT(Y) (this->length - (Y)) - -static bool handle_option (struct outp_driver *this, const char *key, - const struct string *val); -static void draw_headers (struct outp_driver *this); - -static void write_ps_prologue (struct outp_driver *); - -static char *quote_ps_name (const char *string); - -static struct font *load_font (const char *string); -static void free_font (struct font *); -static void setup_font (struct outp_driver *this, struct font *, int index); - -/* Driver initialization. */ - -static bool -ps_open_driver (struct outp_driver *this, struct substring options) -{ - struct ps_driver_ext *x; - size_t i; - - this->width = this->length = 0; - this->font_height = PSUS * 10 / 72; - - this->ext = x = xmalloc (sizeof *x); - x->file_name = xstrdup ("pspp.ps"); - x->file = NULL; - x->draw_headers = true; - x->page_number = 0; - x->portrait = true; - outp_get_paper_size ("", &x->paper_width, &x->paper_length); - x->left_margin = PSUS / 2; - x->right_margin = PSUS / 2; - x->top_margin = PSUS / 2; - x->bottom_margin = PSUS / 2; - x->line_gutter = PSUS / 72; - x->line_space = PSUS / 72; - x->line_width = PSUS / 144; - for (i = 0; i < OUTP_FONT_CNT; i++) - x->fonts[i] = NULL; - - outp_parse_options (options, handle_option, this); - - x->file = fn_open (x->file_name, "w"); - if (x->file == NULL) - { - error (0, errno, _("opening PostScript output file \"%s\""), - x->file_name); - goto error; - } - - if (x->portrait) - { - this->width = x->paper_width; - this->length = x->paper_length; - } - else - { - this->width = x->paper_length; - this->length = x->paper_width; - } - this->width -= x->left_margin + x->right_margin; - this->length -= x->top_margin + x->bottom_margin; - if (x->draw_headers) - { - int header_length = 3 * this->font_height; - this->length -= header_length; - x->top_margin += header_length; - } - - for (i = 0; i < OUTP_FONT_CNT; i++) - if (x->fonts[i] == NULL) - { - const char *default_fonts[OUTP_FONT_CNT]; - default_fonts[OUTP_FIXED] = "Courier.afm"; - default_fonts[OUTP_PROPORTIONAL] = "Times-Roman.afm"; - default_fonts[OUTP_EMPHASIS] = "Times-Italic.afm"; - x->fonts[i] = load_font (default_fonts[i]); - if (x->fonts[i] == NULL) - goto error; - } - - if (this->length / this->font_height < 15) - { - error (0, 0, _("The defined PostScript page is not long " - "enough to hold margins and headers, plus least 15 " - "lines of the default fonts. In fact, there's only " - "room for %d lines of each font at the default size " - "of %d.%03d points."), - this->length / this->font_height, - this->font_height / 1000, this->font_height % 1000); - goto error; - } - - this->fixed_width = - afm_get_character (x->fonts[OUTP_FIXED]->metrics, '0')->width - * this->font_height / 1000; - this->prop_em_width = - afm_get_character (x->fonts[OUTP_PROPORTIONAL]->metrics, '0')->width - * this->font_height / 1000; - - this->horiz_line_width[OUTP_L_NONE] = 0; - this->horiz_line_width[OUTP_L_SINGLE] = 2 * x->line_gutter + x->line_width; - this->horiz_line_width[OUTP_L_DOUBLE] = (2 * x->line_gutter + x->line_space - + 2 * x->line_width); - memcpy (this->vert_line_width, this->horiz_line_width, - sizeof this->vert_line_width); - - write_ps_prologue (this); - - return true; - - error: - this->class->close_driver (this); - return false; -} - -static bool -ps_close_driver (struct outp_driver *this) -{ - struct ps_driver_ext *x = this->ext; - bool ok = true; - size_t i; - - if (x->file != NULL) - { - fprintf (x->file, - "%%%%Trailer\n" - "%%%%Pages: %d\n" - "%%%%EOF\n", - x->page_number); - - ok = fn_close (x->file_name, x->file) == 0; - if (!ok) - error (0, errno, _("closing PostScript output file \"%s\""), - x->file_name); - } - - free (x->file_name); - for (i = 0; i < OUTP_FONT_CNT; i++) - free_font (x->fonts[i]); - free (x); - - return ok; -} - -/* Generic option types. */ -enum -{ - output_file_arg, - paper_size_arg, - orientation_arg, - line_style_arg, - boolean_arg, - pos_int_arg, - dimension_arg, - string_arg, - nonneg_int_arg -}; - -/* All the options that the PostScript driver supports. */ -static const struct outp_option option_tab[] = -{ - {"output-file", output_file_arg,0}, - {"paper-size", paper_size_arg, 0}, - {"orientation", orientation_arg,0}, - - {"headers", boolean_arg, 1}, - - {"prop-font", string_arg, OUTP_PROPORTIONAL}, - {"emph-font", string_arg, OUTP_EMPHASIS}, - {"fixed-font", string_arg, OUTP_FIXED}, - - {"left-margin", pos_int_arg, 0}, - {"right-margin", pos_int_arg, 1}, - {"top-margin", pos_int_arg, 2}, - {"bottom-margin", pos_int_arg, 3}, - {"font-size", pos_int_arg, 4}, - - {"line-width", dimension_arg, 0}, - {"line-gutter", dimension_arg, 1}, - {"line-width", dimension_arg, 2}, - {NULL, 0, 0}, -}; - -static bool -handle_option (struct outp_driver *this, const char *key, - const struct string *val) -{ - struct ps_driver_ext *x = this->ext; - int subcat; - char *value = ds_cstr (val); - - switch (outp_match_keyword (key, option_tab, &subcat)) - { - case -1: - error (0, 0, - _("unknown configuration parameter `%s' for PostScript device " - "driver"), key); - break; - case output_file_arg: - free (x->file_name); - x->file_name = xstrdup (value); - break; - case paper_size_arg: - outp_get_paper_size (value, &this->width, &this->length); - break; - case orientation_arg: - if (!strcmp (value, "portrait")) - x->portrait = true; - else if (!strcmp (value, "landscape")) - x->portrait = false; - else - error (0, 0, _("unknown orientation `%s' (valid orientations are " - "`portrait' and `landscape')"), value); - break; - case boolean_arg: - if (!strcmp (value, "on") || !strcmp (value, "true") - || !strcmp (value, "yes") || atoi (value)) - x->draw_headers = true; - else if (!strcmp (value, "off") || !strcmp (value, "false") - || !strcmp (value, "no") || !strcmp (value, "0")) - x->draw_headers = false; - else - { - error (0, 0, _("boolean value expected for %s"), key); - return false; - } - break; - case pos_int_arg: - { - char *tail; - int arg; - - errno = 0; - arg = strtol (value, &tail, 0); - if (arg < 1 || errno == ERANGE || *tail) - { - error (0, 0, _("positive integer value required for `%s'"), key); - break; - } - if ((subcat == 4 || subcat == 5) && arg < 1000) - { - error (0, 0, _("default font size must be at least 1 point (value " - "of 1000 for key `%s')"), key); - break; - } - switch (subcat) - { - case 0: - x->left_margin = arg; - break; - case 1: - x->right_margin = arg; - break; - case 2: - x->top_margin = arg; - break; - case 3: - x->bottom_margin = arg; - break; - case 4: - this->font_height = arg; - break; - default: - NOT_REACHED (); - } - } - break; - case dimension_arg: - { - int dimension = outp_evaluate_dimension (value); - - if (dimension <= 0) - break; - switch (subcat) - { - case 0: - x->line_width = dimension; - break; - case 1: - x->line_gutter = dimension; - break; - case 2: - x->line_width = dimension; - break; - default: - NOT_REACHED (); - } - } - break; - case string_arg: - { - struct font *font = load_font (value); - if (font != NULL) - { - struct font **dst = &x->fonts[subcat]; - if (*dst != NULL) - free_font (*dst); - *dst = font; - } - } - break; - default: - NOT_REACHED (); - } - - return true; -} - -/* Looks for a PostScript font file or config file in all the - appropriate places. Returns the file name on success, NULL on - failure. */ -static char * -find_ps_file (const char *name) -{ - if (fn_is_absolute (name)) - return xstrdup (name); - else - { - char *base_name = xasprintf ("psfonts/%s", name); - char *file_name = fn_search_path (base_name, config_path); - free (base_name); - return file_name; - } -} - -/* Basic file operations. */ - -/* Writes the PostScript prologue to file F. */ -static void -write_ps_prologue (struct outp_driver *this) -{ - struct ps_driver_ext *x = this->ext; - size_t embedded_cnt, preloaded_cnt; - size_t i; - - fputs ("%!PS-Adobe-3.0\n", x->file); - fputs ("%%Pages: (atend)\n", x->file); - - embedded_cnt = preloaded_cnt = 0; - for (i = 0; i < OUTP_FONT_CNT; i++) - { - bool embed = x->fonts[i]->embed_fn != NULL; - embedded_cnt += embed; - preloaded_cnt += !embed; - } - if (preloaded_cnt > 0) - { - fputs ("%%DocumentNeededResources: font", x->file); - for (i = 0; i < OUTP_FONT_CNT; i++) - { - struct font *f = x->fonts[i]; - if (f->embed_fn == NULL) - fprintf (x->file, " %s", afm_get_findfont_name (f->metrics)); - } - fputs ("\n", x->file); - } - if (embedded_cnt > 0) - { - fputs ("%%DocumentSuppliedResources: font", x->file); - for (i = 0; i < OUTP_FONT_CNT; i++) - { - struct font *f = x->fonts[i]; - if (f->embed_fn != NULL) - fprintf (x->file, " %s", afm_get_findfont_name (f->metrics)); - } - fputs ("\n", x->file); - } - fputs ("%%Copyright: This prologue is public domain.\n", x->file); - fprintf (x->file, "%%%%Creator: %s\n", version); - fprintf (x->file, "%%%%DocumentMedia: Plain %g %g 75 white ()\n", - x->paper_width / (PSUS / 72.0), x->paper_length / (PSUS / 72.0)); - fprintf (x->file, "%%%%Orientation: %s\n", - x->portrait ? "Portrait" : "Landscape"); - fputs ("%%EndComments\n", x->file); - fputs ("%%BeginDefaults\n", x->file); - fputs ("%%PageResources: font", x->file); - for (i = 0; i < OUTP_FONT_CNT; i++) - fprintf (x->file, " %s", afm_get_findfont_name (x->fonts[i]->metrics)); - fputs ("\n", x->file); - fputs ("%%EndDefaults\n", x->file); - fputs ("%%BeginProlog\n", x->file); - fputs ("/ED{exch def}bind def\n", x->file); - fputs ("/L{moveto lineto stroke}bind def\n", x->file); - fputs ("/D{moveto lineto moveto lineto stroke}bind def\n", x->file); - fputs ("/S{show}bind def\n", x->file); - fputs ("/GS{glyphshow}def\n", x->file); - fputs ("/RF{\n", x->file); - fputs (" exch dup maxlength 1 add dict begin\n", x->file); - fputs (" {\n", x->file); - fputs (" 1 index/FID ne{def}{pop pop}ifelse\n", x->file); - fputs (" }forall\n", x->file); - fputs (" /Encoding ED\n", x->file); - fputs (" currentdict end\n", x->file); - fputs ("}bind def\n", x->file); - fputs ("/F{setfont}bind def\n", x->file); - fputs ("/EP{\n", x->file); - fputs (" pg restore\n", x->file); - fputs (" showpage\n", x->file); - fputs ("}bind def\n", x->file); - fputs ("/GB{\n", x->file); - fputs (" /y2 ED/x2 ED/y1 ED/x1 ED\n", x->file); - fputs (" x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto closepath\n", - x->file); - fputs (" gsave 0.9 setgray fill grestore stroke\n", x->file); - fputs ("}bind def\n", x->file); - fputs ("/K{0 rmoveto}bind def\n", x->file); - fputs ("%%EndProlog\n", x->file); - fputs ("%%BeginSetup\n", x->file); - for (i = 0; i < OUTP_FONT_CNT; i++) - setup_font (this, x->fonts[i], i); - fputs ("%%EndSetup\n", x->file); -} - -/* Returns STRING as a Postscript name, which is just '/' - followed by STRING unless characters need to be quoted. - The caller must free the string. */ -static char * -quote_ps_name (const char *string) -{ - const char *cp; - - for (cp = string; *cp != '\0'; cp++) - { - unsigned char c = *cp; - if (!isalpha (c) && strchr ("^_|!$&:;.,-+", c) == NULL - && (cp == string || !isdigit (c))) - { - struct string out = DS_EMPTY_INITIALIZER; - ds_put_char (&out, '<'); - for (cp = string; *cp != '\0'; cp++) - { - c = *cp; - ds_put_format (&out, "%02x", c); - } - ds_put_cstr (&out, ">cvn"); - return ds_cstr (&out); - } - } - return xasprintf ("/%s", string); -} - -static void -ps_open_page (struct outp_driver *this) -{ - struct ps_driver_ext *x = this->ext; - - /* Assure page independence. */ - x->last_font = -1; - - x->page_number++; - - fprintf (x->file, - "%%%%Page: %d %d\n" - "%%%%BeginPageSetup\n" - "/pg save def 0.001 dup scale\n", - x->page_number, x->page_number); - - if (!x->portrait) - fprintf (x->file, - "%d 0 translate 90 rotate\n", - x->paper_width); - - if (x->bottom_margin != 0 || x->left_margin != 0) - fprintf (x->file, - "%d %d translate\n", - x->left_margin, x->bottom_margin); - - fprintf (x->file, - "/LW %d def %d setlinewidth\n" - "%%%%EndPageSetup\n", - x->line_width, x->line_width); - - if (x->draw_headers) - draw_headers (this); -} - -static void -ps_close_page (struct outp_driver *this) -{ - struct ps_driver_ext *x = this->ext; - fputs ("%%PageTrailer\n" - "EP\n", - x->file); -} - -static void -ps_submit (struct outp_driver *this UNUSED, struct som_entity *s) -{ - switch (s->type) - { - case SOM_CHART: - break; - default: - NOT_REACHED (); - } -} - -/* Draws a line from (x0,y0) to (x1,y1). */ -static void -dump_line (struct outp_driver *this, int x0, int y0, int x1, int y1) -{ - struct ps_driver_ext *ext = this->ext; - fprintf (ext->file, "%d %d %d %d L\n", x0, YT (y0), x1, YT (y1)); -} - -/* Draws a horizontal line X0...X2 at Y if LEFT says so, - shortening it to X0...X1 if SHORTEN is true. - Draws a horizontal line X1...X3 at Y if RIGHT says so, - shortening it to X2...X3 if SHORTEN is true. */ -static void -horz_line (struct outp_driver *this, - int x0, int x1, int x2, int x3, int y, - enum outp_line_style left, enum outp_line_style right, - bool shorten) -{ - if (left != OUTP_L_NONE && right != OUTP_L_NONE && !shorten) - dump_line (this, x0, y, x3, y); - else - { - if (left != OUTP_L_NONE) - dump_line (this, x0, y, shorten ? x1 : x2, y); - if (right != OUTP_L_NONE) - dump_line (this, shorten ? x2 : x1, y, x3, y); - } -} - -/* Draws a vertical line Y0...Y2 at X if TOP says so, - shortening it to Y0...Y1 if SHORTEN is true. - Draws a vertical line Y1...Y3 at X if BOTTOM says so, - shortening it to Y2...Y3 if SHORTEN is true. */ -static void -vert_line (struct outp_driver *this, - int y0, int y1, int y2, int y3, int x, - enum outp_line_style top, enum outp_line_style bottom, - bool shorten) -{ - if (top != OUTP_L_NONE && bottom != OUTP_L_NONE && !shorten) - dump_line (this, x, y0, x, y3); - else - { - if (top != OUTP_L_NONE) - dump_line (this, x, y0, x, shorten ? y1 : y2); - if (bottom != OUTP_L_NONE) - dump_line (this, x, shorten ? y2 : y1, x, y3); - } -} - -/* Draws a generalized intersection of lines in the rectangle - (X0,Y0)-(X3,Y3). The line coming from the top to the center - is of style TOP, from left to center of style LEFT, from - bottom to center of style BOTTOM, and from right to center of - style RIGHT. */ -static void -ps_line (struct outp_driver *this, - int x0, int y0, int x3, int y3, - enum outp_line_style top, enum outp_line_style left, - enum outp_line_style bottom, enum outp_line_style right) -{ - /* The algorithm here is somewhat subtle, to allow it to handle - all the kinds of intersections that we need. - - Three additional ordinates are assigned along the x axis. The - first is xc, midway between x0 and x3. The others are x1 and - x2; for a single vertical line these are equal to xc, and for - a double vertical line they are the ordinates of the left and - right half of the double line. - - yc, y1, and y2 are assigned similarly along the y axis. - - The following diagram shows the coordinate system and output - for double top and bottom lines, single left line, and no - right line: - - x0 x1 xc x2 x3 - y0 ________________________ - | # # | - | # # | - | # # | - | # # | - | # # | - y1 = y2 = yc |######### # | - | # # | - | # # | - | # # | - | # # | - y3 |________#_____#_______| - */ - struct ps_driver_ext *ext = this->ext; - - /* Offset from center of each line in a pair of double lines. */ - int double_line_ofs = (ext->line_space + ext->line_width) / 2; - - /* Are the lines along each axis single or double? - (It doesn't make sense to have different kinds of line on the - same axis, so we don't try to gracefully handle that case.) */ - bool double_vert = top == OUTP_L_DOUBLE || bottom == OUTP_L_DOUBLE; - bool double_horz = left == OUTP_L_DOUBLE || right == OUTP_L_DOUBLE; - - /* When horizontal lines are doubled, - the left-side line along y1 normally runs from x0 to x2, - and the right-side line along y1 from x3 to x1. - If the top-side line is also doubled, we shorten the y1 lines, - so that the left-side line runs only to x1, - and the right-side line only to x2. - Otherwise, the horizontal line at y = y1 below would cut off - the intersection, which looks ugly: - x0 x1 x2 x3 - y0 ________________________ - | # # | - | # # | - | # # | - | # # | - y1 |######### ########| - | | - | | - y2 |######################| - | | - | | - y3 |______________________| - It is more of a judgment call when the horizontal line is - single. We actually choose to cut off the line anyhow, as - shown in the first diagram above. - */ - bool shorten_y1_lines = top == OUTP_L_DOUBLE; - bool shorten_y2_lines = bottom == OUTP_L_DOUBLE; - bool shorten_yc_line = shorten_y1_lines && shorten_y2_lines; - int horz_line_ofs = double_vert ? double_line_ofs : 0; - int xc = (x0 + x3) / 2; - int x1 = xc - horz_line_ofs; - int x2 = xc + horz_line_ofs; - - bool shorten_x1_lines = left == OUTP_L_DOUBLE; - bool shorten_x2_lines = right == OUTP_L_DOUBLE; - bool shorten_xc_line = shorten_x1_lines && shorten_x2_lines; - int vert_line_ofs = double_horz ? double_line_ofs : 0; - int yc = (y0 + y3) / 2; - int y1 = yc - vert_line_ofs; - int y2 = yc + vert_line_ofs; - - if (!double_horz) - horz_line (this, x0, x1, x2, x3, yc, left, right, shorten_yc_line); - else - { - horz_line (this, x0, x1, x2, x3, y1, left, right, shorten_y1_lines); - horz_line (this, x0, x1, x2, x3, y2, left, right, shorten_y2_lines); - } - - if (!double_vert) - vert_line (this, y0, y1, y2, y3, xc, top, bottom, shorten_xc_line); - else - { - vert_line (this, y0, y1, y2, y3, x1, top, bottom, shorten_x1_lines); - vert_line (this, y0, y1, y2, y3, x2, top, bottom, shorten_x2_lines); - } -} - -/* Writes STRING at location (X,Y) trimmed to the given MAX_WIDTH - and with the given JUSTIFICATION for THIS driver. */ -static int -draw_text (struct outp_driver *this, - const char *string, int x, int y, int max_width, - enum outp_justification justification) -{ - struct outp_text text; - int width; - - text.font = OUTP_PROPORTIONAL; - text.justification = justification; - text.string = ss_cstr (string); - text.h = max_width; - text.v = this->font_height; - text.x = x; - text.y = y; - this->class->text_metrics (this, &text, &width, NULL); - this->class->text_draw (this, &text); - return width; -} - -/* Writes LEFT left-justified and RIGHT right-justified within - (X0...X1) at Y. LEFT or RIGHT or both may be null. */ -static void -draw_header_line (struct outp_driver *this, - const char *left, const char *right, - int x0, int x1, int y) -{ - int right_width = 0; - if (right != NULL) - right_width = (draw_text (this, right, x0, y, x1 - x0, OUTP_RIGHT) - + this->prop_em_width); - if (left != NULL) - draw_text (this, left, x0, y, x1 - x0 - right_width, OUTP_LEFT); -} - -/* Draw top of page headers for THIS driver. */ -static void -draw_headers (struct outp_driver *this) -{ - struct ps_driver_ext *ext = this->ext; - char *r1, *r2; - int x0, x1; - int y; - - y = -3 * this->font_height; - x0 = this->prop_em_width; - x1 = this->width - this->prop_em_width; - - /* Draw box. */ - fprintf (ext->file, "%d %d %d %d GB\n", - 0, YT (y), - this->width, YT (y + 2 * this->font_height + ext->line_gutter)); - y += ext->line_width + ext->line_gutter; - - r1 = xasprintf (_("%s - Page %d"), get_start_date (), ext->page_number); - r2 = xasprintf ("%s - %s", version, host_system); - - draw_header_line (this, outp_title, r1, x0, x1, y); - y += this->font_height; - - draw_header_line (this, outp_subtitle, r2, x0, x1, y); - - free (r1); - free (r2); -} - -/* Writes the CHAR_CNT characters in CHARS at (X0,Y0), using the - given FONT. - The characters are justified according to JUSTIFICATION in a - field that has WIDTH_LEFT space remaining after the characters - themselves are accounted for. - Before character I is written, its x-position is adjusted by - KERNS[I]. */ -static void -write_text (struct outp_driver *this, - int x0, int y0, - enum outp_font font, - enum outp_justification justification, - const struct afm_character **chars, int *kerns, size_t char_cnt, - int width_left) -{ - struct ps_driver_ext *ext = this->ext; - struct afm *afm = ext->fonts[font]->metrics; - struct string out; - size_t i, j; - - if (justification == OUTP_RIGHT) - x0 += width_left; - else if (justification == OUTP_CENTER) - x0 += width_left / 2; - y0 += afm_get_ascent (afm) * this->font_height / 1000; - - fprintf (ext->file, "\n%d %d moveto\n", x0, YT (y0)); - - if (ext->last_font != font) - { - ext->last_font = font; - fprintf (ext->file, "F%d setfont\n", font); - } - - ds_init_empty (&out); - for (i = 0; i < char_cnt; i = j) - { - for (j = i + 1; j < char_cnt; j++) - if (kerns[j] != 0) - break; - - if (kerns[i] != 0) - fprintf (ext->file, "%d K", kerns[i]); - while (i < j) - { - size_t encoded = afm_encode_string (afm, chars + i, j - i, &out); - if (encoded > 0) - { - fprintf (ext->file, "%sS\n", ds_cstr (&out)); - ds_clear (&out); - i += encoded; - } - - if (i < j) - { - fprintf (ext->file, "/%s GS\n", chars[i]->name); - i++; - } - } - } - ds_destroy (&out); -} - -/* State of a text formatting operation. */ -struct text_state - { - /* Input. */ - const struct outp_text *text; - bool draw; - - /* Output. */ - const struct afm_character **glyphs; - int *glyph_kerns; - - /* State. */ - size_t glyph_cnt; /* Number of glyphs output. */ - int width_left; /* Width left over. */ - int height_left; /* Height left over. */ - - /* State as of last space. */ - const char *space_char; /* Just past last space. */ - size_t space_glyph_cnt; /* Number of glyphs as of last space. */ - int space_width_left; /* Width left over as of last space. */ - - /* Statistics. */ - int max_width; /* Widest line so far. */ - }; - -/* Adjusts S to complete a line of text, - and draws the current line if appropriate. */ -static void -finish_line (struct outp_driver *this, struct text_state *s) -{ - int width; - - if (s->draw) - { - write_text (this, - s->text->x, s->text->y + (s->text->v - s->height_left), - s->text->font, - s->text->justification, - s->glyphs, s->glyph_kerns, s->glyph_cnt, - s->width_left); - s->glyph_cnt = 0; - } - - /* Update maximum width. */ - width = s->text->h - s->width_left; - if (width > s->max_width) - s->max_width = width; - - /* Move to next line. */ - s->width_left = s->text->h; - s->height_left -= this->font_height; - - /* No spaces on this line yet. */ - s->space_char = NULL; -} - -/* Format TEXT on THIS driver. - If DRAW is nonzero, draw the text. - The width of the widest line is stored into *WIDTH, if WIDTH - is nonnull. - The total height of the text written is stored into *HEIGHT, - if HEIGHT is nonnull. */ -static void -text (struct outp_driver *this, const struct outp_text *text, bool draw, - int *width, int *height) -{ - struct ps_driver_ext *ext = this->ext; - struct afm *afm = ext->fonts[text->font]->metrics; - const char *cp; - size_t glyph_cap; - struct text_state s; - - s.text = text; - s.draw = draw; - - s.glyphs = NULL; - s.glyph_kerns = NULL; - glyph_cap = 0; - - s.glyph_cnt = 0; - s.width_left = s.text->h; - s.height_left = s.text->v; - - s.space_char = 0; - - s.max_width = 0; - - cp = ss_data (s.text->string); - while (s.height_left >= this->font_height && cp < ss_end (s.text->string)) - { - const struct afm_character *cur; - int char_width; - int kern_adjust; - - if (*cp == '\n') - { - finish_line (this, &s); - cp++; - continue; - } - - /* Get character and resolve ligatures. */ - cur = afm_get_character (afm, *cp); - while (++cp < ss_end (s.text->string)) - { - const struct afm_character *next = afm_get_character (afm, *cp); - const struct afm_character *ligature = afm_get_ligature (cur, next); - if (ligature == NULL) - break; - cur = ligature; - } - char_width = cur->width * this->font_height / 1000; - - /* Get kern adjustment. */ - if (s.glyph_cnt > 0) - kern_adjust = (afm_get_kern_adjustment (s.glyphs[s.glyph_cnt - 1], cur) - * this->font_height / 1000); - else - kern_adjust = 0; - - /* Record the current status if this is a space character. */ - if (cur->code == ' ' && cp > ss_data (s.text->string)) - { - s.space_char = cp; - s.space_glyph_cnt = s.glyph_cnt; - s.space_width_left = s.width_left; - } - - /* Enough room on this line? */ - if (char_width + kern_adjust > s.width_left) - { - if (s.space_char == NULL) - { - finish_line (this, &s); - kern_adjust = 0; - } - else - { - cp = s.space_char; - s.glyph_cnt = s.space_glyph_cnt; - s.width_left = s.space_width_left; - finish_line (this, &s); - continue; - } - } - - if (s.glyph_cnt >= glyph_cap) - { - glyph_cap = 2 * (glyph_cap + 8); - s.glyphs = xnrealloc (s.glyphs, glyph_cap, sizeof *s.glyphs); - s.glyph_kerns = xnrealloc (s.glyph_kerns, - glyph_cap, sizeof *s.glyph_kerns); - } - s.glyphs[s.glyph_cnt] = cur; - s.glyph_kerns[s.glyph_cnt] = kern_adjust; - s.glyph_cnt++; - - s.width_left -= char_width + kern_adjust; - } - if (s.height_left >= this->font_height && s.glyph_cnt > 0) - finish_line (this, &s); - - if (width != NULL) - *width = s.max_width; - if (height != NULL) - *height = text->v - s.height_left; - free (s.glyphs); - free (s.glyph_kerns); -} - -static void -ps_text_metrics (struct outp_driver *this, const struct outp_text *t, - int *width, int *height) -{ - text (this, t, false, width, height); -} - -static void -ps_text_draw (struct outp_driver *this, const struct outp_text *t) -{ - assert (this->page_open); - text (this, t, true, NULL, NULL); -} - -static void -ps_chart_initialise (struct outp_driver *this UNUSED, struct chart *ch) -{ -#ifdef NO_CHARTS - ch->lp = NULL; -#else - struct ps_driver_ext *x = this->ext; - char page_size[128]; - int size; - int x_origin, y_origin; - - ch->file = tmpfile (); - if (ch->file == NULL) - { - ch->lp = NULL; - return; - } - - size = this->width < this->length ? this->width : this->length; - x_origin = x->left_margin + (size - this->width) / 2; - y_origin = x->bottom_margin + (size - this->length) / 2; - - snprintf (page_size, sizeof page_size, - "a,xsize=%.3f,ysize=%.3f,xorigin=%.3f,yorigin=%.3f", - (double) size / PSUS, (double) size / PSUS, - (double) x_origin / PSUS, (double) y_origin / PSUS); - - ch->pl_params = pl_newplparams (); - pl_setplparam (ch->pl_params, "PAGESIZE", page_size); - ch->lp = pl_newpl_r ("ps", NULL, ch->file, stderr, ch->pl_params); -#endif -} - -static void -ps_chart_finalise (struct outp_driver *this UNUSED, struct chart *ch UNUSED) -{ -#ifndef NO_CHARTS - struct ps_driver_ext *x = this->ext; - char buf[BUFSIZ]; - static int doc_num = 0; - - outp_eject_page (this); - fprintf (x->file, - "/sp save def\n" - "%d %d translate 1000 dup scale\n" - "userdict begin\n" - "/showpage { } def\n" - "0 setgray 0 setlinecap 1 setlinewidth\n" - "0 setlinejoin 10 setmiterlimit [ ] 0 setdash newpath clear\n" - "%%%%BeginDocument: %d\n", - -x->left_margin, -x->bottom_margin, - doc_num++); - - rewind (ch->file); - while (fwrite (buf, 1, fread (buf, 1, sizeof buf, ch->file), x->file)) - continue; - fclose (ch->file); - - fputs ("%%EndDocument\n" - "end\n" - "sp restore\n", - x->file); - outp_close_page (this); -#endif -} - -static void embed_font (struct outp_driver *this, struct font *font); -static void reencode_font (struct outp_driver *this, struct font *font); - -/* Loads and returns the font for STRING, which has the format - "AFM,PFA,ENC", where AFM is the AFM file's name, PFA is the - PFA or PFB file's name, and ENC is the encoding file's name. - PFA and ENC are optional. - Returns a null pointer if unsuccessful. */ -static struct font * -load_font (const char *string_) -{ - char *string = xstrdup (string_); - struct font *font; - char *position = string; - char *token; - char *afm_file_name; - - font = xmalloc (sizeof *font); - font->metrics = NULL; - font->embed_fn = NULL; - font->encoding_fn = NULL; - - token = strsep (&position, ","); - if (token == NULL) - { - error (0, 0, _("\"%s\": bad font specification"), string); - goto error; - } - - /* Read AFM file. */ - afm_file_name = find_ps_file (token); - if (afm_file_name == NULL) - { - error (0, 0, _("could not find AFM file \"%s\""), token); - goto error; - } - font->metrics = afm_open (afm_file_name); - free (afm_file_name); - if (font->metrics == NULL) - goto error; - - /* Find font file to embed. */ - token = strsep (&position, ","); - if (token != NULL && *token != '\0') - { - font->embed_fn = find_ps_file (token); - if (font->embed_fn == NULL) - error (0, 0, _("could not find font \"%s\""), token); - } - - /* Find encoding. */ - token = strsep (&position, ","); - if (token != NULL && *token == '\0') - { - font->encoding_fn = find_ps_file (token); - if (font->encoding_fn == NULL) - error (0, 0, _("could not find encoding \"%s\""), token); - } - - free (string); - return font; - - error: - free (string); - free_font (font); - return NULL; -} - -/* Frees FONT. */ -static void -free_font (struct font *font) -{ - if (font != NULL) - { - afm_close (font->metrics); - free (font->embed_fn); - free (font->encoding_fn); - free (font); - } -} - -/* Emits PostScript code to embed FONT (if necessary), scale it - to the proper size, re-encode it (if necessary), and store the - resulting font as an object named F#, where INDEX is - substituted for #. */ -static void -setup_font (struct outp_driver *this, struct font *font, int index) -{ - struct ps_driver_ext *x = this->ext; - char *ps_name; - - if (font->embed_fn != NULL) - embed_font (this, font); - else - fprintf (x->file, "%%%%IncludeResource: font %s\n", - afm_get_findfont_name (font->metrics)); - - ps_name = quote_ps_name (afm_get_findfont_name (font->metrics)); - fprintf (x->file, "%s findfont %d scalefont\n", ps_name, this->font_height); - free (ps_name); - - if (font->encoding_fn != NULL) - reencode_font (this, font); - - fprintf (x->file, "/F%d ED\n", index); -} - -/* Copies up to COPY_BYTES bytes from SRC to DST, stopping at - end-of-file or on error. */ -static void -copy_bytes_literally (FILE *src, FILE *dst, unsigned long copy_bytes) -{ - while (copy_bytes > 0) - { - char buffer[BUFSIZ]; - unsigned long chunk_bytes = MIN (copy_bytes, sizeof buffer); - size_t read_bytes = fread (buffer, 1, chunk_bytes, src); - size_t write_bytes = fwrite (buffer, 1, read_bytes, dst); - if (write_bytes != chunk_bytes) - break; - copy_bytes -= chunk_bytes; - } -} - -/* Copies up to COPY_BYTES bytes from SRC to DST, stopping at - end-of-file or on error. The bytes are translated into - hexadecimal during copying and broken into lines with - new-line characters. */ -static void -copy_bytes_as_hex (FILE *src, FILE *dst, unsigned long copy_bytes) -{ - unsigned long i; - - for (i = 0; i < copy_bytes; i++) - { - int c = getc (src); - if (c == EOF) - break; - if (i > 0 && i % 36 == 0) - putc ('\n', dst); - fprintf (dst, "%02X", c); - } - putc ('\n', dst); -} - -/* Embeds the given FONT into THIS driver's output stream. */ -static void -embed_font (struct outp_driver *this, struct font *font) -{ - struct ps_driver_ext *x = this->ext; - FILE *file; - int c; - - file = fopen (font->embed_fn, "rb"); - if (file == NULL) - { - error (errno, 0, _("cannot open font file \"%s\""), font->embed_fn); - return; - } - - fprintf (x->file, "%%%%BeginResource: font %s\n", - afm_get_findfont_name (font->metrics)); - - c = getc (file); - ungetc (c, file); - if (c != 128) - { - /* PFA file. Copy literally. */ - copy_bytes_literally (file, x->file, ULONG_MAX); - } - else - { - /* PFB file. Translate as specified in Adobe Technical - Note #5040. */ - while ((c = getc (file)) == 128) - { - int type; - unsigned long length; - - type = getc (file); - if (type == 3) - break; - - length = getc (file); - length |= (unsigned long) getc (file) << 8; - length |= (unsigned long) getc (file) << 16; - length |= (unsigned long) getc (file) << 24; - - if (type == 1) - copy_bytes_literally (file, x->file, length); - else if (type == 2) - copy_bytes_as_hex (file, x->file, length); - else - break; - } - } - if (freaderror (file)) - error (errno, 0, _("reading font file \"%s\""), font->embed_fn); - fputs ("%%EndResource\n", x->file); -} - -/* Re-encodes FONT according to the specified encoding. */ -static void -reencode_font (struct outp_driver *this, struct font *font) -{ - struct ps_driver_ext *x = this->ext; - - struct string line; - - int line_number; - FILE *file; - - char *tab[256]; - - int i; - - file = fopen (font->encoding_fn, "r"); - if (file == NULL) - { - error (errno, 0, _("cannot open font encoding file \"%s\""), - font->encoding_fn); - return; - } - - for (i = 0; i < 256; i++) - tab[i] = NULL; - - line_number = 0; - - ds_init_empty (&line); - while (ds_read_config_line (&line, &line_number, file)) - { - char *pschar, *code; - char *save_ptr, *tail; - int code_val; - - if (ds_is_empty (&line) == 0) - continue; - - pschar = strtok_r (ds_cstr (&line), " \t\r\n", &save_ptr); - code = strtok_r (NULL, " \t\r\n", &save_ptr); - if (pschar == NULL || code == NULL) - continue; - - code_val = strtol (code, &tail, 0); - if (*tail) - { - error_at_line (0, 0, font->encoding_fn, line_number, - _("invalid numeric format")); - continue; - } - if (code_val < 0 || code_val > 255) - continue; - if (tab[code_val] != 0) - free (tab[code_val]); - tab[code_val] = xstrdup (pschar); - } - ds_destroy (&line); - - fputs ("[", x->file); - for (i = 0; i < 256; i++) - { - char *name = quote_ps_name (tab[i] != NULL ? tab[i] : ".notdef"); - fprintf (x->file, "%s\n", name); - free (name); - free (tab[i]); - } - fputs ("] RF\n", x->file); - - if (freaderror (file) != 0) - error (errno, 0, _("closing Postscript encoding \"%s\""), - font->encoding_fn); -} - -/* PostScript driver class. */ -const struct outp_class postscript_class = -{ - "postscript", - 0, - - ps_open_driver, - ps_close_driver, - - ps_open_page, - ps_close_page, - NULL, - - ps_submit, - - ps_line, - ps_text_metrics, - ps_text_draw, - - ps_chart_initialise, - ps_chart_finalise -}; diff --git a/src/output/table.c b/src/output/table.c index 72edf17f..f8736e62 100644 --- a/src/output/table.c +++ b/src/output/table.c @@ -37,6 +37,7 @@ #include +#include "error.h" #include "minmax.h" #include "xalloc.h" @@ -44,7 +45,6 @@ #define _(msgid) gettext (msgid) const struct som_table_class tab_table_class; -static char *command_name; /* Returns the font to use for a cell with the given OPTIONS. */ static enum outp_font @@ -57,13 +57,13 @@ options_to_font (unsigned options) /* Creates a table with NC columns and NR rows. */ struct tab_table * -tab_create (int nc, int nr, int reallocable UNUSED) +tab_create (int nc, int nr) { struct tab_table *t; t = pool_create_container (struct tab_table, container); + t->ref_cnt = 1; t->col_style = TAB_COL_NONE; - t->col_group = 0; t->title = NULL; t->flags = SOMF_NONE; t->nr = nr; @@ -81,21 +81,33 @@ tab_create (int nc, int nr, int reallocable UNUSED) memset (t->rv, UCHAR_MAX, nr * (nc + 1)); t->dim = NULL; - t->w = t->h = NULL; t->col_ofs = t->row_ofs = 0; return t; } -/* Destroys table T. */ +/* Increases T's reference count and, if this causes T's + reference count to reach 0, destroys T. */ void tab_destroy (struct tab_table *t) { - assert (t != NULL); + assert (t->ref_cnt > 0); + if (--t->ref_cnt > 0) + return; + if (t->dim_free != NULL) + t->dim_free (t->dim_aux); free (t->title); pool_destroy (t->container); } +/* Increases T's reference count. */ +void +tab_ref (struct tab_table *t) +{ + assert (t->ref_cnt > 0); + t->ref_cnt++; +} + /* Sets the width and height of a table, in columns and rows, respectively. Use only to reduce the size of a table, since it does not change the amount of allocated memory. */ @@ -110,7 +122,7 @@ tab_resize (struct tab_table *t, int nc, int nr) } if (nr != -1) { - assert (nr + t->row_ofs <= t->nr); + assert (nr + t->row_ofs <= tab_nr (t)); t->nr = nr + t->row_ofs; } } @@ -133,16 +145,16 @@ tab_realloc (struct tab_table *t, int nc, int nr) tab_offset (t, 0, 0); if (nc == -1) - nc = t->nc; + nc = tab_nc (t); if (nr == -1) - nr = t->nr; + nr = tab_nr (t); - assert (nc == t->nc); + assert (nc == tab_nc (t)); if (nc > t->cf) { - int mr1 = MIN (nr, t->nr); - int mc1 = MIN (nc, t->nc); + int mr1 = MIN (nr, tab_nr (t)); + int mc1 = MIN (nc, tab_nc (t)); struct substring *new_cc; unsigned char *new_ct; @@ -152,9 +164,9 @@ tab_realloc (struct tab_table *t, int nc, int nr) new_ct = pool_malloc (t->container, nr * nc); for (r = 0; r < mr1; r++) { - memcpy (&new_cc[r * nc], &t->cc[r * t->nc], mc1 * sizeof *t->cc); - memcpy (&new_ct[r * nc], &t->ct[r * t->nc], mc1); - memset (&new_ct[r * nc + t->nc], TAB_EMPTY, nc - t->nc); + memcpy (&new_cc[r * nc], &t->cc[r * tab_nc (t)], mc1 * sizeof *t->cc); + memcpy (&new_ct[r * nc], &t->ct[r * tab_nc (t)], mc1); + memset (&new_ct[r * nc + tab_nc (t)], TAB_EMPTY, nc - tab_nc (t)); } pool_free (t->container, t->cc); pool_free (t->container, t->ct); @@ -162,7 +174,7 @@ tab_realloc (struct tab_table *t, int nc, int nr) t->ct = new_ct; t->cf = nc; } - else if (nr != t->nr) + else if (nr != tab_nr (t)) { t->cc = pool_nrealloc (t->container, t->cc, nr * nc, sizeof *t->cc); t->ct = pool_realloc (t->container, t->ct, nr * nc); @@ -170,15 +182,15 @@ tab_realloc (struct tab_table *t, int nc, int nr) t->rh = pool_nrealloc (t->container, t->rh, nc, nr + 1); t->rv = pool_nrealloc (t->container, t->rv, nr, nc + 1); - if (nr > t->nr) + if (nr > tab_nr (t)) { - memset (&t->rh[nc * (t->nr + 1)], TAL_0, (nr - t->nr) * nc); - memset (&t->rv[(nc + 1) * t->nr], UCHAR_MAX, - (nr - t->nr) * (nc + 1)); + memset (&t->rh[nc * (tab_nr (t) + 1)], TAL_0, (nr - tab_nr (t)) * nc); + memset (&t->rv[(nc + 1) * tab_nr (t)], UCHAR_MAX, + (nr - tab_nr (t)) * (nc + 1)); } } - memset (&t->ct[nc * t->nr], TAB_EMPTY, nc * (nr - t->nr)); + memset (&t->ct[nc * tab_nr (t)], TAB_EMPTY, nc * (nr - tab_nr (t))); t->nr = nr; t->nc = nc; @@ -210,14 +222,12 @@ tab_headers (struct tab_table *table, int l, int r, int t, int b) /* Set up table T so that, when it is an appropriate size, it will be displayed across the page in columns. - STYLE is a TAB_COL_* constant. GROUP is the number of rows to take - as a unit. */ + STYLE is a TAB_COL_* constant. */ void -tab_columns (struct tab_table *t, int style, int group) +tab_columns (struct tab_table *t, int style) { assert (t != NULL); t->col_style = style; - t->col_group = group; } /* Rules. */ @@ -230,16 +240,16 @@ tab_vline (struct tab_table *t, int style, int x, int y1, int y2) assert (t != NULL); #if DEBUGGING - if (x + t->col_ofs < 0 || x + t->col_ofs > t->nc - || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= t->nr - || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= t->nr) + if (x + t->col_ofs < 0 || x + t->col_ofs > tab_nc (t) + || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t) + || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t)) { printf (_("bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in " "table size (%d,%d)\n"), x, t->col_ofs, x + t->col_ofs, y1, t->row_ofs, y1 + t->row_ofs, y2, t->row_ofs, y2 + t->row_ofs, - t->nc, t->nr); + tab_nc (t), tab_nr (t)); return; } #endif @@ -249,10 +259,10 @@ tab_vline (struct tab_table *t, int style, int x, int y1, int y2) y2 += t->row_ofs; assert (x > 0); - assert (x < t->nc); + assert (x < tab_nc (t)); assert (y1 >= 0); assert (y2 >= y1); - assert (y2 <= t->nr); + assert (y2 <= tab_nr (t)); if (style != -1) { @@ -274,10 +284,10 @@ tab_hline (struct tab_table * t, int style, int x1, int x2, int y) y += t->row_ofs; assert (y >= 0); - assert (y <= t->nr); + assert (y <= tab_nr (t)); assert (x2 >= x1 ); assert (x1 >= 0 ); - assert (x2 < t->nc); + assert (x2 < tab_nc (t)); if (style != -1) { @@ -300,10 +310,10 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v, assert (t != NULL); #if DEBUGGING - if (x1 + t->col_ofs < 0 || x1 + t->col_ofs >= t->nc - || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= t->nc - || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= t->nr - || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= t->nr) + if (x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t) + || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t) + || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t) + || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t)) { printf (_("bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) " "in table size (%d,%d)\n"), @@ -311,7 +321,7 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v, y1, t->row_ofs, y1 + t->row_ofs, x2, t->col_ofs, x2 + t->col_ofs, y2, t->row_ofs, y2 + t->row_ofs, - t->nc, t->nr); + tab_nc (t), tab_nr (t)); NOT_REACHED (); } #endif @@ -325,8 +335,8 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v, assert (y2 >= y1); assert (x1 >= 0); assert (y1 >= 0); - assert (x2 < t->nc); - assert (y2 < t->nr); + assert (x2 < tab_nc (t)); + assert (y2 < tab_nr (t)); if (f_h != -1) { @@ -386,12 +396,22 @@ tab_title (struct tab_table *t, const char *title, ...) va_end (args); } -/* Set DIM_FUNC as the dimension function for table T. */ +/* Set DIM_FUNC, which will be passed auxiliary data AUX, as the + dimension function for table T. + + DIM_FUNC must not assume that it is called from the same + context as tab_dim; for example, table T might be kept in + memory and, thus, DIM_FUNC might be called after the currently + running command completes. If it is non-null, FREE_FUNC is + called when the table is destroyed, to allow any data + allocated for use by DIM_FUNC to be freed. */ void -tab_dim (struct tab_table *t, tab_dim_func *dim_func, void *aux) +tab_dim (struct tab_table *t, + tab_dim_func *dim_func, tab_dim_free_func *free_func, void *aux) { - assert (t != NULL && t->dim == NULL); + assert (t->dim == NULL); t->dim = dim_func; + t->dim_free = free_func; t->dim_aux = aux; } @@ -400,85 +420,76 @@ tab_dim (struct tab_table *t, tab_dim_func *dim_func, void *aux) wrapping. The width will be no larger than the page width minus left and right rule widths. */ int -tab_natural_width (struct tab_table *t, struct outp_driver *d, int c) +tab_natural_width (const struct tab_rendering *r, int col) { - int width; + const struct tab_table *t = r->table; + int width, row, max_width; - assert (t != NULL && c >= 0 && c < t->nc); - { - int r; + assert (col >= 0 && col < tab_nc (t)); - for (width = r = 0; r < t->nr; r++) - { - struct outp_text text; - unsigned char opt = t->ct[c + r * t->cf]; - int w; + width = 0; + for (row = 0; row < tab_nr (t); row++) + { + struct outp_text text; + unsigned char opt = t->ct[col + row * t->cf]; + int w; - if (opt & (TAB_JOIN | TAB_EMPTY)) - continue; + if (opt & (TAB_JOIN | TAB_EMPTY)) + continue; - text.string = t->cc[c + r * t->cf]; - text.justification = OUTP_LEFT; - text.font = options_to_font (opt); - text.h = text.v = INT_MAX; + text.string = t->cc[col + row * t->cf]; + text.justification = OUTP_LEFT; + text.font = options_to_font (opt); + text.h = text.v = INT_MAX; - d->class->text_metrics (d, &text, &w, NULL); - if (w > width) - width = w; - } - } + r->driver->class->text_metrics (r->driver, &text, &w, NULL); + if (w > width) + width = w; + } if (width == 0) { /* FIXME: This is an ugly kluge to compensate for the fact that we don't let joined cells contribute to column widths. */ - width = d->prop_em_width * 8; + width = r->driver->prop_em_width * 8; } - { - const int clamp = d->width - t->wrv[0] - t->wrv[t->nc]; - - if (width > clamp) - width = clamp; - } - - return width; + max_width = r->driver->width - r->wrv[0] - r->wrv[tab_nc (t)]; + return MIN (width, max_width); } /* Returns the natural height of row R in table T for driver D, that is, the minimum height necessary to display the information in the cell at the widths set for each column. */ int -tab_natural_height (struct tab_table *t, struct outp_driver *d, int r) +tab_natural_height (const struct tab_rendering *r, int row) { - int height; + const struct tab_table *t = r->table; + int height, col; - assert (t != NULL && r >= 0 && r < t->nr); + assert (row >= 0 && row < tab_nr (t)); - { - int c; - - for (height = d->font_height, c = 0; c < t->nc; c++) - { - struct outp_text text; - unsigned char opt = t->ct[c + r * t->cf]; - int h; - - if (opt & (TAB_JOIN | TAB_EMPTY)) - continue; - - text.string = t->cc[c + r * t->cf]; - text.justification = OUTP_LEFT; - text.font = options_to_font (opt); - text.h = t->w[c]; - text.v = INT_MAX; - d->class->text_metrics (d, &text, NULL, &h); - - if (h > height) - height = h; - } - } + height = r->driver->font_height; + for (col = 0; col < tab_nc (t); col++) + { + struct outp_text text; + unsigned char opt = t->ct[col + row * t->cf]; + int h; + + if (opt & (TAB_JOIN | TAB_EMPTY)) + continue; + + text.string = t->cc[col + row * t->cf]; + text.justification = OUTP_LEFT; + text.font = options_to_font (opt); + text.h = r->w[col]; + text.v = INT_MAX; + r->driver->class->text_metrics (r->driver, &text, NULL, &h); + + if (h > height) + height = h; + } return height; } @@ -486,18 +497,16 @@ tab_natural_height (struct tab_table *t, struct outp_driver *d, int r) /* Callback function to set all columns and rows to their natural dimensions. Not really meant to be called directly. */ void -tab_natural_dimensions (struct tab_table *t, struct outp_driver *d, - void *aux UNUSED) +tab_natural_dimensions (struct tab_rendering *r, void *aux UNUSED) { + const struct tab_table *t = r->table; int i; - assert (t != NULL); - - for (i = 0; i < t->nc; i++) - t->w[i] = tab_natural_width (t, d, i); + for (i = 0; i < tab_nc (t); i++) + r->w[i] = tab_natural_width (r, i); - for (i = 0; i < t->nr; i++) - t->h[i] = tab_natural_height (t, d, i); + for (i = 0; i < tab_nr (t); i++) + r->h[i] = tab_natural_height (r, i); } @@ -515,14 +524,14 @@ tab_value (struct tab_table *table, int c, int r, unsigned char opt, assert (table != NULL && v != NULL && f != NULL); #if DEBUGGING if (c + table->col_ofs < 0 || r + table->row_ofs < 0 - || c + table->col_ofs >= table->nc - || r + table->row_ofs >= table->nr) + || c + table->col_ofs >= tab_nc (table) + || r + table->row_ofs >= tab_nr (table)) { printf ("tab_value(): bad cell (%d+%d=%d,%d+%d=%d) in table size " "(%d,%d)\n", c, table->col_ofs, c + table->col_ofs, r, table->row_ofs, r + table->row_ofs, - table->nc, table->nr); + tab_nc (table), tab_nr (table)); return; } #endif @@ -547,22 +556,22 @@ tab_fixed (struct tab_table *table, int c, int r, unsigned char opt, assert (table != NULL && w <= 40); assert (c >= 0); - assert (c < table->nc); + assert (c < tab_nc (table)); assert (r >= 0); - assert (r < table->nr); + assert (r < tab_nr (table)); f = fmt_for_output (FMT_F, w, d); #if DEBUGGING if (c + table->col_ofs < 0 || r + table->row_ofs < 0 - || c + table->col_ofs >= table->nc - || r + table->row_ofs >= table->nr) + || c + table->col_ofs >= tab_nc (table) + || r + table->row_ofs >= tab_nr (table)) { printf ("tab_fixed(): bad cell (%d+%d=%d,%d+%d=%d) in table size " "(%d,%d)\n", c, table->col_ofs, c + table->col_ofs, r, table->row_ofs, r + table->row_ofs, - table->nc, table->nr); + tab_nc (table), tab_nr (table)); return; } #endif @@ -593,9 +602,9 @@ tab_double (struct tab_table *table, int c, int r, unsigned char opt, assert (table != NULL); assert (c >= 0); - assert (c < table->nc); + assert (c < tab_nc (table)); assert (r >= 0); - assert (r < table->nr); + assert (r < tab_nr (table)); if ( fmt == NULL) fmt = settings_get_format (); @@ -604,14 +613,14 @@ tab_double (struct tab_table *table, int c, int r, unsigned char opt, #if DEBUGGING if (c + table->col_ofs < 0 || r + table->row_ofs < 0 - || c + table->col_ofs >= table->nc - || r + table->row_ofs >= table->nr) + || c + table->col_ofs >= tab_nc (table) + || r + table->row_ofs >= tab_nr (table)) { printf ("tab_double(): bad cell (%d+%d=%d,%d+%d=%d) in table size " "(%d,%d)\n", c, table->col_ofs, c + table->col_ofs, r, table->row_ofs, r + table->row_ofs, - table->nc, table->nr); + tab_nc (table), tab_nr (table)); return; } #endif @@ -629,21 +638,21 @@ tab_double (struct tab_table *table, int c, int r, unsigned char opt, static void do_tab_text (struct tab_table *table, int c, int r, unsigned opt, char *text) { - assert (c >= 0); - assert (r >= 0); - assert (c < table->nc); - assert (r < table->nr); + assert (c >= 0 ); + assert (r >= 0 ); + assert (c < tab_nc (table)); + assert (r < tab_nr (table)); #if DEBUGGING if (c + table->col_ofs < 0 || r + table->row_ofs < 0 - || c + table->col_ofs >= table->nc - || r + table->row_ofs >= table->nr) + || c + table->col_ofs >= tab_nc (table) + || r + table->row_ofs >= tab_nr (table)) { printf ("tab_text(): bad cell (%d+%d=%d,%d+%d=%d) in table size " "(%d,%d)\n", c, table->col_ofs, c + table->col_ofs, r, table->row_ofs, r + table->row_ofs, - table->nc, table->nr); + tab_nc (table), tab_nr (table)); return; } #endif @@ -685,14 +694,14 @@ do_tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, assert (y1 + table->row_ofs >= 0); assert (y2 >= y1); assert (x2 >= x1); - assert (y2 + table->row_ofs < table->nr); - assert (x2 + table->col_ofs < table->nc); + assert (y2 + table->row_ofs < tab_nr (table)); + assert (x2 + table->col_ofs < tab_nc (table)); #if DEBUGGING - if (x1 + table->col_ofs < 0 || x1 + table->col_ofs >= table->nc - || y1 + table->row_ofs < 0 || y1 + table->row_ofs >= table->nr - || x2 < x1 || x2 + table->col_ofs >= table->nc - || y2 < y2 || y2 + table->row_ofs >= table->nr) + if (x1 + table->col_ofs < 0 || x1 + table->col_ofs >= tab_nc (table) + || y1 + table->row_ofs < 0 || y1 + table->row_ofs >= tab_nr (table) + || x2 < x1 || x2 + table->col_ofs >= tab_nc (table) + || y2 < y2 || y2 + table->row_ofs >= tab_nr (table)) { printf ("tab_joint_text(): bad cell " "(%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n", @@ -700,7 +709,7 @@ do_tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, y1, table->row_ofs, y1 + table->row_ofs, x2, table->col_ofs, x2 + table->col_ofs, y2, table->row_ofs, y2 + table->row_ofs, - table->nc, table->nr); + tab_nc (table), tab_nr (table)); return; } #endif @@ -708,7 +717,6 @@ do_tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2, tab_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2); j = pool_alloc (table->container, sizeof *j); - j->hit = 0; j->x1 = x1 + table->col_ofs; j->y1 = y1 + table->row_ofs; j->x2 = ++x2 + table->col_ofs; @@ -764,50 +772,25 @@ tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2, int y2, pool_vasprintf (table->container, format, args)); va_end (args); } - -/* Sets cell (C,R) in TABLE, with options OPT, to contents STRING. */ -void -tab_raw (struct tab_table *table, int c, int r, unsigned opt, - struct substring *string) -{ - assert (table != NULL && string != NULL); - -#if DEBUGGING - if (c + table->col_ofs < 0 || r + table->row_ofs < 0 - || c + table->col_ofs >= table->nc - || r + table->row_ofs >= table->nr) - { - printf ("tab_raw(): bad cell (%d+%d=%d,%d+%d=%d) in table size " - "(%d,%d)\n", - c, table->col_ofs, c + table->col_ofs, - r, table->row_ofs, r + table->row_ofs, - table->nc, table->nr); - return; - } -#endif - - table->cc[c + r * table->cf] = *string; - table->ct[c + r * table->cf] = opt; -} /* Miscellaneous. */ /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -nowrap_dim (struct tab_table *t, struct outp_driver *d, void *aux UNUSED) +nowrap_dim (struct tab_rendering *r, void *aux UNUSED) { - t->w[0] = tab_natural_width (t, d, 0); - t->h[0] = d->font_height; + r->w[0] = tab_natural_width (r, 0); + r->h[0] = r->driver->font_height; } /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -wrap_dim (struct tab_table *t, struct outp_driver *d, void *aux UNUSED) +wrap_dim (struct tab_rendering *r, void *aux UNUSED) { - t->w[0] = tab_natural_width (t, d, 0); - t->h[0] = tab_natural_height (t, d, 0); + r->w[0] = tab_natural_width (r, 0); + r->h[0] = tab_natural_height (r, 0); } static void @@ -815,7 +798,7 @@ do_tab_output_text (struct tab_table *t, int options, char *text) { do_tab_text (t, 0, 0, options, text); tab_flags (t, SOMF_NO_TITLE | SOMF_NO_SPACING); - tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim, NULL); + tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim, NULL, NULL); tab_submit (t); } @@ -825,7 +808,7 @@ do_tab_output_text (struct tab_table *t, int options, char *text) void tab_output_text (int options, const char *text) { - struct tab_table *table = tab_create (1, 1, 0); + struct tab_table *table = tab_create (1, 1); do_tab_output_text (table, options, pool_strdup (table->container, text)); } @@ -839,7 +822,7 @@ tab_output_text_format (int options, const char *format, ...) struct tab_table *table; va_list args; - table = tab_create (1, 1, 0); + table = tab_create (1, 1); va_start (args, format); do_tab_output_text (table, options, @@ -880,14 +863,14 @@ tab_offset (struct tab_table *t, int col, int row) assert (t != NULL); #if DEBUGGING - if (row < -1 || row > t->nr) + if (row < -1 || row > tab_nr (t)) { - printf ("tab_offset(): row=%d in %d-row table\n", row, t->nr); + printf ("tab_offset(): row=%d in %d-row table\n", row, tab_nr (t)); NOT_REACHED (); } - if (col < -1 || col > t->nc) + if (col < -1 || col > tab_nc (t)) { - printf ("tab_offset(): col=%d in %d-column table\n", col, t->nc); + printf ("tab_offset(): col=%d in %d-column table\n", col, tab_nc (t)); NOT_REACHED (); } #endif @@ -909,29 +892,46 @@ tab_next_row (struct tab_table *t) assert (t != NULL); t->cc += t->cf; t->ct += t->cf; - if (++t->row_ofs >= t->nr) - tab_realloc (t, -1, t->nr * 4 / 3); + if (++t->row_ofs >= tab_nr (t)) + tab_realloc (t, -1, tab_nr (t) * 4 / 3); } -static struct tab_table *t; -static struct outp_driver *d; -static int tab_hit; +/* Return the number of columns and rows in the table into N_COLUMNS + and N_ROWS, respectively. */ +static void +tabi_count (struct som_entity *t_, int *n_columns, int *n_rows) +{ + struct tab_table *t = t_->ext; + *n_columns = t->nc; + *n_rows = t->nr; +} -/* Set the current table to TABLE. */ +/* Return the column style for this table into STYLE. */ static void -tabi_table (struct som_entity *table) +tabi_columns (struct som_entity *t_, int *style) { - assert (table != NULL); - assert (table->type == SOM_TABLE); + struct tab_table *t = t_->ext; + *style = t->col_style; +} - t = table->ext; - tab_offset (t, 0, 0); +/* Return the number of header rows/columns on the left, right, top, + and bottom sides into HL, HR, HT, and HB, respectively. */ +static void +tabi_headers (struct som_entity *t_, int *hl, int *hr, int *ht, int *hb) +{ + struct tab_table *t = t_->ext; + *hl = t->l; + *hr = t->r; + *ht = t->t; + *hb = t->b; +} - assert (t->w == NULL && t->h == NULL); - t->w = pool_nalloc (t->container, t->nc, sizeof *t->w); - t->h = pool_nalloc (t->container, t->nr, sizeof *t->h); - t->hrh = pool_nmalloc (t->container, t->nr + 1, sizeof *t->hrh); - t->wrv = pool_nmalloc (t->container, t->nc + 1, sizeof *t->wrv); +/* Return flags set for the current table into FLAGS. */ +static void +tabi_flags (struct som_entity *t_, unsigned *flags) +{ + struct tab_table *t = t_->ext; + *flags = t->flags; } /* Returns the line style to use for spacing purposes for a rule @@ -953,153 +953,127 @@ rule_to_spacing_type (unsigned char type) } } -/* Set the current output device to DRIVER. */ -static void -tabi_driver (struct outp_driver *driver) +static void * +tabi_render_init (struct som_entity *t_, struct outp_driver *driver, + int hl, int hr, int ht, int hb) { - int c, r; + const struct tab_table *t = t_->ext; + struct tab_rendering *r; + int col, row; int i; - assert (driver != NULL); - d = driver; + tab_offset (t_->ext, 0, 0); + + r = xmalloc (sizeof *r); + r->table = t; + r->driver = driver; + r->w = xnmalloc (tab_nc (t), sizeof *r->w); + r->h = xnmalloc (tab_nr (t), sizeof *r->h); + r->hrh = xnmalloc (tab_nr (t) + 1, sizeof *r->hrh); + r->wrv = xnmalloc (tab_nc (t) + 1, sizeof *r->wrv); + r->l = hl; + r->r = hr; + r->t = ht; + r->b = hb; /* Figure out sizes of rules. */ - for (r = 0; r <= t->nr; r++) + for (row = 0; row <= tab_nr (t); row++) { int width = 0; - for (c = 0; c < t->nc; c++) + for (col = 0; col < tab_nc (t); col++) { - unsigned char rh = t->rh[c + r * t->cf]; + unsigned char rh = t->rh[col + row * t->cf]; int w = driver->horiz_line_width[rule_to_spacing_type (rh)]; if (w > width) width = w; } - t->hrh[r] = width; + r->hrh[row] = width; } - for (c = 0; c <= t->nc; c++) + for (col = 0; col <= tab_nc (t); col++) { int width = 0; - for (r = 0; r < t->nr; r++) + for (row = 0; row < tab_nr (t); row++) { - unsigned char *rv = &t->rv[c + r * (t->cf + 1)]; + unsigned char *rv = &t->rv[col + row * (t->cf + 1)]; int w; if (*rv == UCHAR_MAX) - *rv = c != 0 && c != t->nc ? TAL_GAP : TAL_0; + *rv = col != 0 && col != tab_nc (t) ? TAL_GAP : TAL_0; w = driver->vert_line_width[rule_to_spacing_type (*rv)]; if (w > width) width = w; } - t->wrv[c] = width; + r->wrv[col] = width; } -#if DEBUGGING - for (i = 0; i < t->nr; i++) - t->h[i] = -1; - for (i = 0; i < t->nc; i++) - t->w[i] = -1; -#endif - - assert (t->dim != NULL); - t->dim (t, d, t->dim_aux); + /* Determine row heights and columns widths. */ + for (i = 0; i < tab_nr (t); i++) + r->h[i] = -1; + for (i = 0; i < tab_nc (t); i++) + r->w[i] = -1; -#if DEBUGGING - { - int error = 0; - - for (i = 0; i < t->nr; i++) - { - if (t->h[i] == -1) - { - printf ("Table row %d height not initialized.\n", i); - error = 1; - } - assert (t->h[i] > 0); - } + t->dim (r, t->dim_aux); - for (i = 0; i < t->nc; i++) - { - if (t->w[i] == -1) - { - printf ("Table column %d width not initialized.\n", i); - error = 1; - } - assert (t->w[i] > 0); - } - } -#endif + for (i = 0; i < tab_nr (t); i++) + if (r->h[i] < 0) + error (0, 0, "height of table row %d is %d (not initialized?)", + i, r->h[i]); + for (i = 0; i < tab_nc (t); i++) + if (r->w[i] < 0) + error (0, 0, "width of table column %d is %d (not initialized?)", + i, r->w[i]); /* Add up header sizes. */ - for (i = 0, t->wl = t->wrv[0]; i < t->l; i++) - t->wl += t->w[i] + t->wrv[i + 1]; - for (i = 0, t->ht = t->hrh[0]; i < t->t; i++) - t->ht += t->h[i] + t->hrh[i + 1]; - for (i = t->nc - t->r, t->wr = t->wrv[i]; i < t->nc; i++) - t->wr += t->w[i] + t->wrv[i + 1]; - for (i = t->nr - t->b, t->hb = t->hrh[i]; i < t->nr; i++) - t->hb += t->h[i] + t->hrh[i + 1]; + for (i = 0, r->wl = r->wrv[0]; i < r->l; i++) + r->wl += r->w[i] + r->wrv[i + 1]; + for (i = 0, r->ht = r->hrh[0]; i < r->t; i++) + r->ht += r->h[i] + r->hrh[i + 1]; + for (i = tab_nc (t) - r->r, r->wr = r->wrv[i]; i < tab_nc (t); i++) + r->wr += r->w[i] + r->wrv[i + 1]; + for (i = tab_nr (t) - r->b, r->hb = r->hrh[i]; i < tab_nr (t); i++) + r->hb += r->h[i] + r->hrh[i + 1]; /* Title. */ if (!(t->flags & SOMF_NO_TITLE)) - t->ht += d->font_height; + r->ht += driver->font_height; + + return r; } -/* Return the number of columns and rows in the table into N_COLUMNS - and N_ROWS, respectively. */ static void -tabi_count (int *n_columns, int *n_rows) +tabi_render_free (void *r_) { - assert (n_columns != NULL && n_rows != NULL); - *n_columns = t->nc; - *n_rows = t->nr; -} + struct tab_rendering *r = r_; -static void tabi_cumulate (int cumtype, int start, int *end, int max, int *actual); + free (r->w); + free (r->h); + free (r->hrh); + free (r->wrv); + free (r); +} /* Return the horizontal and vertical size of the entire table, including headers, for the current output device, into HORIZ and VERT. */ static void -tabi_area (int *horiz, int *vert) +tabi_area (void *r_, int *horiz, int *vert) { - assert (horiz != NULL && vert != NULL); - - { - int w, c; - - for (c = t->l + 1, w = t->wl + t->wr + t->w[t->l]; - c < t->nc - t->r; c++) - w += t->w[c] + t->wrv[c]; - *horiz = w; - } - - { - int h, r; - for (r = t->t + 1, h = t->ht + t->hb + t->h[t->t]; - r < t->nr - t->b; r++) - h += t->h[r] + t->hrh[r]; - *vert = h; - } -} - -/* Return the column style for this table into STYLE. */ -static void -tabi_columns (int *style) -{ - assert (style != NULL); - *style = t->col_style; -} - -/* Return the number of header rows/columns on the left, right, top, - and bottom sides into HL, HR, HT, and HB, respectively. */ -static void -tabi_headers (int *hl, int *hr, int *ht, int *hb) -{ - assert (hl != NULL && hr != NULL && ht != NULL && hb != NULL); - *hl = t->l; - *hr = t->r; - *ht = t->t; - *hb = t->b; + struct tab_rendering *r = r_; + const struct tab_table *t = r->table; + int width, col; + int height, row; + + width = 0; + for (col = r->l + 1, width = r->wl + r->wr + r->w[tab_l (t)]; + col < tab_nc (t) - r->r; col++) + width += r->w[col] + r->wrv[col]; + *horiz = width; + + height = 0; + for (row = r->t + 1, height = r->ht + r->hb + r->h[tab_t (t)]; + row < tab_nr (t) - tab_b (t); row++) + height += r->h[row] + r->hrh[row]; + *vert = height; } /* Determines the number of rows or columns (including appropriate @@ -1110,32 +1084,35 @@ tabi_headers (int *hl, int *hr, int *ht, int *hb) space the selected rows/columns (including appropriate headers) filled. */ static void -tabi_cumulate (int cumtype, int start, int *end, int max, int *actual) +tabi_cumulate (void *r_, int cumtype, int start, int *end, + int max, int *actual) { - int n; - int *d; - int *r; + const struct tab_rendering *r = r_; + const struct tab_table *t = r->table; + int limit; + int *cells, *rules; int total; + int idx; assert (end != NULL && (cumtype == SOM_ROWS || cumtype == SOM_COLUMNS)); if (cumtype == SOM_ROWS) { - assert (start >= 0 && start < t->nr); - n = t->nr - t->b; - d = &t->h[start]; - r = &t->hrh[start + 1]; - total = t->ht + t->hb; + assert (start >= 0 && start < tab_nr (t)); + limit = tab_nr (t) - r->b; + cells = &r->h[start]; + rules = &r->hrh[start + 1]; + total = r->ht + r->hb; } else { - assert (start >= 0 && start < t->nc); - n = t->nc - t->r; - d = &t->w[start]; - r = &t->wrv[start + 1]; - total = t->wl + t->wr; + assert (start >= 0 && start < tab_nc (t)); + limit = tab_nc (t) - tab_r (t); + cells = &r->w[start]; + rules = &r->wrv[start + 1]; + total = r->wl + r->wr; } - total += *d++; + total += *cells++; if (total > max) { if (end) @@ -1145,180 +1122,139 @@ tabi_cumulate (int cumtype, int start, int *end, int max, int *actual) return; } - { - int x; - - for (x = start + 1; x < n; x++) - { - int amt = *d++ + *r++; - - total += amt; - if (total > max) - { - total -= amt; - break; - } - } - - if (end) - *end = x; - - if (actual) - *actual = total; - } -} - -/* Return flags set for the current table into FLAGS. */ -static void -tabi_flags (unsigned *flags) -{ - assert (flags != NULL); - *flags = t->flags; -} - -/* Returns true if the table will fit in the given page WIDTH, - false otherwise. */ -static bool -tabi_fits_width (int width) -{ - int i; - - for (i = t->l; i < t->nc - t->r; i++) - if (t->wl + t->wr + t->w[i] > width) - return false; - - return true; -} + for (idx = start + 1; idx < limit; idx++) + { + int amt = *cells++ + *rules++; -/* Returns true if the table will fit in the given page LENGTH, - false otherwise. */ -static bool -tabi_fits_length (int length) -{ - int i; + total += amt; + if (total > max) + { + total -= amt; + break; + } + } - for (i = t->t; i < t->nr - t->b; i++) - if (t->ht + t->hb + t->h[i] > length) - return false; + if (end) + *end = idx; - return true; -} - -/* Sets the number of header rows/columns on the left, right, top, - and bottom sides to HL, HR, HT, and HB, respectively. */ -static void -tabi_set_headers (int hl, int hr, int ht, int hb) -{ - t->l = hl; - t->r = hr; - t->t = ht; - t->b = hb; + if (actual) + *actual = total; } /* Render title for current table, with major index X and minor index Y. Y may be zero, or X and Y may be zero, but X should be nonzero if Y is nonzero. */ static void -tabi_title (int x, int y) +tabi_title (void *r_, int x, int y, int table_num, int subtable_num, + const char *command_name) { - char buf[1024]; - char *cp; + const struct tab_rendering *r = r_; + const struct tab_table *t = r->table; + struct outp_text text; + struct string title; if (t->flags & SOMF_NO_TITLE) return; - cp = spprintf (buf, "%d.%d", table_num, subtable_num); + ds_init_empty (&title); + ds_put_format (&title,"%d.%d", table_num, subtable_num); if (x && y) - cp = spprintf (cp, "(%d:%d)", x, y); + ds_put_format (&title, "(%d:%d)", x, y); else if (x) - cp = spprintf (cp, "(%d)", x); + ds_put_format (&title, "(%d)", x); if (command_name != NULL) - cp = spprintf (cp, " %s", command_name); - cp = stpcpy (cp, ". "); + ds_put_format (&title, " %s", command_name); + ds_put_cstr (&title, ". "); if (t->title != NULL) - { - size_t length = strlen (t->title); - memcpy (cp, t->title, length); - cp += length; - } - *cp = 0; - - { - struct outp_text text; - - text.font = OUTP_PROPORTIONAL; - text.justification = OUTP_LEFT; - text.string = ss_buffer (buf, cp - buf); - text.h = d->width; - text.v = d->font_height; - text.x = 0; - text.y = d->cp_y; - d->class->text_draw (d, &text); - } + ds_put_cstr (&title, t->title); + + text.font = OUTP_PROPORTIONAL; + text.justification = OUTP_LEFT; + text.string = ds_ss (&title); + text.h = r->driver->width; + text.v = r->driver->font_height; + text.x = 0; + text.y = r->driver->cp_y; + r->driver->class->text_draw (r->driver, &text); + + ds_destroy (&title); } -static int render_strip (int x, int y, int r, int c1, int c2, int r1, int r2); +static int render_strip (const struct tab_rendering *, + int x, int y, int r, int c1, int c2, int r1, int r2); -/* Renders columns C0...C1, plus headers, of rows R0...R1, - at the given vertical position Y. - C0 and C1 count vertical rules as columns, - but R0 and R1 do not count horizontal rules as rows. - Returns the vertical position after rendering. */ -static int -render_rows (int y, int c0, int c1, int r0, int r1) +static void +add_range (int ranges[][2], int *np, int start, int end) { - int r; - for (r = r0; r < r1; r++) + int n = *np; + if (n == 0 || start > ranges[n - 1][1]) { - int x = d->cp_x; - x = render_strip (x, y, r, 0, t->l * 2 + 1, r0, r1); - x = render_strip (x, y, r, c0 * 2 + 1, c1 * 2, r0, r1); - x = render_strip (x, y, r, (t->nc - t->r) * 2, t->nc * 2 + 1, r0, r1); - y += (r & 1) ? t->h[r / 2] : t->hrh[r / 2]; + ranges[n][0] = start; + ranges[n][1] = end; + ++*np; } - return y; + else + ranges[n - 1][1] = end; } /* Draws table region (C0,R0)-(C1,R1), plus headers, at the current position on the current output device. */ static void -tabi_render (int c0, int r0, int c1, int r1) +tabi_render (void *r_, int c0, int r0, int c1, int r1) { - int y; + const struct tab_rendering *r = r_; + const struct tab_table *t = r->table; + int rows[3][2], cols[3][2]; + int n_row_ranges, n_col_ranges; + int y, i; + + /* Rows to render, counting horizontal rules as rows. */ + n_row_ranges = 0; + add_range (rows, &n_row_ranges, 0, tab_t (t) * 2 + 1); + add_range (rows, &n_row_ranges, r0 * 2 + 1, r1 * 2); + add_range (rows, &n_row_ranges, (tab_nr (t) - tab_b (t)) * 2, + tab_nr (t) * 2 + 1); + + /* Columns to render, counting vertical rules as columns. */ + n_col_ranges = 0; + add_range (cols, &n_col_ranges, 0, r->l * 2 + 1); + add_range (cols, &n_col_ranges, c0 * 2 + 1, c1 * 2); + add_range (cols, &n_col_ranges, (tab_nc (t) - r->r) * 2, tab_nc (t) * 2 + 1); + + y = r->driver->cp_y; + if (!(t->flags & SOMF_NO_TITLE)) + y += r->driver->font_height; + for (i = 0; i < n_row_ranges; i++) + { + int row; - tab_hit++; + for (row = rows[i][0]; row < rows[i][1]; row++) + { + int x, j; - y = d->cp_y; - if (!(t->flags & SOMF_NO_TITLE)) - y += d->font_height; + x = r->driver->cp_x; + for (j = 0; j < n_col_ranges; j++) + x = render_strip (r, x, y, row, + cols[j][0], cols[j][1], + rows[i][0], rows[i][1]); - y = render_rows (y, c0, c1, 0, t->t * 2 + 1); - y = render_rows (y, c0, c1, r0 * 2 + 1, r1 * 2); - y = render_rows (y, c0, c1, (t->nr - t->b) * 2, t->nr * 2 + 1); + y += (row & 1) ? r->h[row / 2] : r->hrh[row / 2]; + } + } } const struct som_table_class tab_table_class = { - tabi_table, - tabi_driver, - tabi_count, - tabi_area, - NULL, - NULL, tabi_columns, - NULL, tabi_headers, - NULL, - tabi_cumulate, tabi_flags, - tabi_fits_width, - tabi_fits_length, - NULL, - NULL, - tabi_set_headers, + tabi_render_init, + tabi_render_free, + tabi_area, + tabi_cumulate, tabi_title, tabi_render, }; @@ -1360,56 +1296,63 @@ rule_to_draw_type (unsigned char type) /* Returns the horizontal rule at the given column and row. */ static int -get_hrule (int c, int r) +get_hrule (const struct tab_table *t, int col, int row) { - return t->rh[c + r * t->cf]; + return t->rh[col + row * t->cf]; } /* Returns the vertical rule at the given column and row. */ static int -get_vrule (int c, int r) +get_vrule (const struct tab_table *t, int col, int row) { - return t->rv[c + r * (t->cf + 1)]; + return t->rv[col + row * (t->cf + 1)]; } /* Renders the horizontal rule at the given column and row at (X,Y) on the page. */ static void -render_horz_rule (int x, int y, int c, int r) +render_horz_rule (const struct tab_rendering *r, + int x, int y, int col, int row) { - enum outp_line_style style = rule_to_draw_type (get_hrule (c, r)); + enum outp_line_style style; + style = rule_to_draw_type (get_hrule (r->table, col, row)); if (style != OUTP_L_NONE) - d->class->line (d, x, y, x + t->w[c], y + t->hrh[r], - OUTP_L_NONE, style, OUTP_L_NONE, style); + r->driver->class->line (r->driver, x, y, x + r->w[col], y + r->hrh[row], + OUTP_L_NONE, style, OUTP_L_NONE, style); } /* Renders the vertical rule at the given column and row at (X,Y) on the page. */ static void -render_vert_rule (int x, int y, int c, int r) +render_vert_rule (const struct tab_rendering *r, + int x, int y, int col, int row) { - enum outp_line_style style = rule_to_draw_type (get_vrule (c, r)); + enum outp_line_style style; + style = rule_to_draw_type (get_vrule (r->table, col, row)); if (style != OUTP_L_NONE) - d->class->line (d, x, y, x + t->wrv[c], y + t->h[r], - style, OUTP_L_NONE, style, OUTP_L_NONE); + r->driver->class->line (r->driver, x, y, x + r->wrv[col], y + r->h[row], + style, OUTP_L_NONE, style, OUTP_L_NONE); } /* Renders the rule intersection at the given column and row at (X,Y) on the page. */ static void -render_rule_intersection (int x, int y, int c, int r) +render_rule_intersection (const struct tab_rendering *r, + int x, int y, int col, int row) { + const struct tab_table *t = r->table; + /* Bounds of intersection. */ int x0 = x; int y0 = y; - int x1 = x + t->wrv[c]; - int y1 = y + t->hrh[r]; + int x1 = x + r->wrv[col]; + int y1 = y + r->hrh[row]; /* Lines on each side of intersection. */ - int top = r > 0 ? get_vrule (c, r - 1) : TAL_0; - int left = c > 0 ? get_hrule (c - 1, r) : TAL_0; - int bottom = r < t->nr ? get_vrule (c, r) : TAL_0; - int right = c < t->nc ? get_hrule (c, r) : TAL_0; + int top = row > 0 ? get_vrule (t, col, row - 1) : TAL_0; + int left = col > 0 ? get_hrule (t, col - 1, row) : TAL_0; + int bottom = row < tab_nr (t) ? get_vrule (t, col, row) : TAL_0; + int right = col < tab_nc (t) ? get_hrule (t, col, row) : TAL_0; /* Output style for each line. */ enum outp_line_style o_top = rule_to_draw_type (top); @@ -1419,36 +1362,37 @@ render_rule_intersection (int x, int y, int c, int r) if (o_top != OUTP_L_NONE || o_left != OUTP_L_NONE || o_bottom != OUTP_L_NONE || o_right != OUTP_L_NONE) - d->class->line (d, x0, y0, x1, y1, o_top, o_left, o_bottom, o_right); + r->driver->class->line (r->driver, x0, y0, x1, y1, + o_top, o_left, o_bottom, o_right); } /* Returns the width of columns C1...C2 exclusive, including interior but not exterior rules. */ static int -strip_width (int c1, int c2) +strip_width (const struct tab_rendering *r, int c1, int c2) { int width = 0; int c; for (c = c1; c < c2; c++) - width += t->w[c] + t->wrv[c + 1]; + width += r->w[c] + r->wrv[c + 1]; if (c1 < c2) - width -= t->wrv[c2]; + width -= r->wrv[c2]; return width; } /* Returns the height of rows R1...R2 exclusive, including interior but not exterior rules. */ static int -strip_height (int r1, int r2) +strip_height (const struct tab_rendering *r, int r1, int r2) { int height = 0; - int r; + int row; - for (r = r1; r < r2; r++) - height += t->h[r] + t->hrh[r + 1]; + for (row = r1; row < r2; row++) + height += r->h[row] + r->hrh[row + 1]; if (r1 < r2) - height -= t->hrh[r2]; + height -= r->hrh[r2]; return height; } @@ -1456,9 +1400,11 @@ strip_height (int r1, int r2) page. Also renders joined cells that extend as far to the right as C1 and as far down as R1. */ static void -render_cell (int x, int y, int c, int r, int c1, int r1) +render_cell (const struct tab_rendering *r, + int x, int y, int col, int row, int c1, int r1) { - const int index = c + (r * t->cf); + const struct tab_table *t = r->table; + const int index = col + (row * t->cf); unsigned char type = t->ct[index]; struct substring *content = &t->cc[index]; @@ -1470,11 +1416,11 @@ render_cell (int x, int y, int c, int r, int c1, int r1) text.font = options_to_font (type); text.justification = translate_justification (type); text.string = *content; - text.h = t->w[c]; - text.v = t->h[r]; + text.h = r->w[col]; + text.v = r->h[row]; text.x = x; text.y = y; - d->class->text_draw (d, &text); + r->driver->class->text_draw (r->driver, &text); } } else @@ -1482,63 +1428,50 @@ render_cell (int x, int y, int c, int r, int c1, int r1) struct tab_joined_cell *j = (struct tab_joined_cell *) ss_data (*content); - if (j->hit != tab_hit) + if (j->x1 == col && j->y1 == row) { - j->hit = tab_hit; - - if (j->x1 == c && j->y1 == r) - { - struct outp_text text; - text.font = options_to_font (type); - text.justification = translate_justification (type); - text.string = j->contents; - text.x = x; - text.y = y; - text.h = strip_width (j->x1, MIN (j->x2, c1)); - text.v = strip_height (j->y1, MIN (j->y2, r1)); - d->class->text_draw (d, &text); - } + struct outp_text text; + text.font = options_to_font (type); + text.justification = translate_justification (type); + text.string = j->contents; + text.x = x; + text.y = y; + text.h = strip_width (r, j->x1, MIN (j->x2, c1)); + text.v = strip_height (r, j->y1, MIN (j->y2, r1)); + r->driver->class->text_draw (r->driver, &text); } } } /* Render contiguous strip consisting of columns C0...C1, exclusive, - on row R, at (X,Y). Returns X position after rendering. + on row ROW, at (X,Y). Returns X position after rendering. Also renders joined cells that extend beyond that strip, cropping them to lie within rendering region (C0,R0)-(C1,R1). C0 and C1 count vertical rules as columns. - R counts horizontal rules as rows, but R0 and R1 do not. */ + ROW counts horizontal rules as rows, but R0 and R1 do not. */ static int -render_strip (int x, int y, int r, int c0, int c1, int r0 UNUSED, int r1) +render_strip (const struct tab_rendering *r, + int x, int y, int row, int c0, int c1, int r0 UNUSED, int r1) { - int c; + int col; - for (c = c0; c < c1; c++) - if (c & 1) + for (col = c0; col < c1; col++) + if (col & 1) { - if (r & 1) - render_cell (x, y, c / 2, r / 2, c1 / 2, r1); + if (row & 1) + render_cell (r, x, y, col / 2, row / 2, c1 / 2, r1); else - render_horz_rule (x, y, c / 2, r / 2); - x += t->w[c / 2]; + render_horz_rule (r, x, y, col / 2, row / 2); + x += r->w[col / 2]; } else { - if (r & 1) - render_vert_rule (x, y, c / 2, r / 2); + if (row & 1) + render_vert_rule (r, x, y, col / 2, row / 2); else - render_rule_intersection (x, y, c / 2, r / 2); - x += t->wrv[c / 2]; + render_rule_intersection (r, x, y, col / 2, row / 2); + x += r->wrv[col / 2]; } return x; } - -/* Sets COMMAND_NAME as the name of the current command, - for embedding in output. */ -void -tab_set_command_name (const char *command_name_) -{ - free (command_name); - command_name = command_name_ ? xstrdup (command_name_) : NULL; -} diff --git a/src/output/table.h b/src/output/table.h index 1748c24c..f4fbc786 100644 --- a/src/output/table.h +++ b/src/output/table.h @@ -61,23 +61,24 @@ struct tab_joined_cell { int x1, y1; int x2, y2; - int hit; struct substring contents; }; struct outp_driver; struct tab_table; -typedef void tab_dim_func (struct tab_table *, struct outp_driver *, - void *aux); +struct tab_rendering; + +typedef void tab_dim_func (struct tab_rendering *, void *aux); +typedef void tab_dim_free_func (void *aux); /* A table. */ struct tab_table { struct pool *container; + int ref_cnt; /* Reference count. */ /* Contents. */ int col_style; /* Columns: One of TAB_COL_*. */ - int col_group; /* Number of rows per column group. */ char *title; /* Table title. */ unsigned flags; /* SOMF_*. */ int nc, nr; /* Number of columns, rows. */ @@ -87,45 +88,51 @@ struct tab_table unsigned char *ct; /* Cell types; unsigned char[nr][nc]. */ unsigned char *rh; /* Horiz rules; unsigned char[nr+1][nc]. */ unsigned char *rv; /* Vert rules; unsigned char[nr][nc+1]. */ + + /* Calculating row and column dimensions. */ tab_dim_func *dim; /* Calculates cell widths and heights. */ + tab_dim_free_func *dim_free; /* Frees space allocated for dim function. */ void *dim_aux; /* Auxiliary data for dim function. */ - /* Calculated during output. */ - int *w; /* Column widths; [nc]. */ - int *h; /* Row heights; [nr]. */ - int *hrh; /* Heights of horizontal rules; [nr+1]. */ - int *wrv; /* Widths of vertical rules; [nc+1]. */ - int wl, wr, ht, hb; /* Width/height of header rows/columns. */ - /* Editing info. */ int col_ofs, row_ofs; /* X and Y offsets. */ }; -/* Number of rows in TABLE. */ -#define tab_nr(TABLE) ((TABLE)->nr) - -/* Number of columns in TABLE. */ -#define tab_nc(TABLE) ((TABLE)->nc) +/* Number of rows or columns in TABLE. */ +static inline int tab_nr (const struct tab_table *table) { return table->nr; } +static inline int tab_nc (const struct tab_table *table) { return table->nc; } -/* Number of left header columns in TABLE. */ -#define tab_l(TABLE) ((TABLE)->l) +/* Number of left/right/top/bottom header columns/rows in TABLE. */ +static inline int tab_l (const struct tab_table *table) { return table->l; } +static inline int tab_r (const struct tab_table *table) { return table->r; } +static inline int tab_t (const struct tab_table *table) { return table->t; } +static inline int tab_b (const struct tab_table *table) { return table->b; } -/* Number of right header columns in TABLE. */ -#define tab_r(TABLE) ((TABLE)->r) +struct tab_rendering + { + const struct tab_table *table; + struct outp_driver *driver; -/* Number of top header rows in TABLE. */ -#define tab_t(TABLE) ((TABLE)->t) + int *w; /* Column widths; [nc]. */ + int *h; /* Row heights; [nr]. */ + int *hrh; /* Heights of horizontal rules; [nr+1]. */ + int *wrv; /* Widths of vertical rules; [nc+1]. */ -/* Number of bottom header rows in TABLE. */ -#define tab_b(TABLE) ((TABLE)->b) + /* These fields would be redundant with those in struct tab_table, except + that a table will be rendered with fewer header rows or columns than + requested when we are pressed for space. */ + int l, r, t, b; /* Number of header rows/columns. */ + int wl, wr, ht, hb; /* Width/height of header rows/columns. */ + }; /* Tables. */ -struct tab_table *tab_create (int nc, int nr, int reallocable); +struct tab_table *tab_create (int nc, int nr); void tab_destroy (struct tab_table *); +void tab_ref (struct tab_table *); void tab_resize (struct tab_table *, int nc, int nr); void tab_realloc (struct tab_table *, int nc, int nr); void tab_headers (struct tab_table *, int l, int r, int t, int b); -void tab_columns (struct tab_table *, int style, int group); +void tab_columns (struct tab_table *, int style); void tab_title (struct tab_table *, const char *, ...) PRINTF_FORMAT (2, 3); void tab_flags (struct tab_table *, unsigned); @@ -133,9 +140,10 @@ void tab_submit (struct tab_table *); /* Dimensioning. */ tab_dim_func tab_natural_dimensions; -int tab_natural_width (struct tab_table *t, struct outp_driver *d, int c); -int tab_natural_height (struct tab_table *t, struct outp_driver *d, int r); -void tab_dim (struct tab_table *, tab_dim_func *, void *aux); +int tab_natural_width (const struct tab_rendering *, int c); +int tab_natural_height (const struct tab_rendering *, int r); +void tab_dim (struct tab_table *, + tab_dim_func *, tab_dim_free_func *, void *aux); /* Rules. */ void tab_hline (struct tab_table *, int style, int x1, int x2, int y); @@ -176,11 +184,6 @@ void tab_joint_text_format (struct tab_table *, int x1, int y1, int x2, int y2, unsigned opt, const char *, ...) PRINTF_FORMAT (7, 8); -/* Cell low-level access. */ -#define tab_alloc(TABLE, AMT) pool_alloc ((TABLE)->container, (AMT)) -void tab_raw (struct tab_table *, int c, int r, unsigned opt, - struct substring *); - /* Editing. */ void tab_offset (struct tab_table *, int col, int row); void tab_next_row (struct tab_table *); @@ -194,8 +197,5 @@ void tab_output_text (int options, const char *string); void tab_output_text_format (int options, const char *, ...) PRINTF_FORMAT (2, 3); -/* Embedding the command name in the output. */ -void tab_set_command_name (const char *); - #endif /* tab_h */ diff --git a/src/ui/automake.mk b/src/ui/automake.mk index c21b681d..743d0b6d 100644 --- a/src/ui/automake.mk +++ b/src/ui/automake.mk @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in -*- makefile -*- include $(top_srcdir)/src/ui/terminal/automake.mk -if WITHGUI +if HAVE_GUI include $(top_srcdir)/src/ui/gui/automake.mk endif diff --git a/src/ui/gui/automake.mk b/src/ui/gui/automake.mk index b7d60a78..3fbf4652 100644 --- a/src/ui/gui/automake.mk +++ b/src/ui/gui/automake.mk @@ -26,6 +26,7 @@ src_ui_gui_psppire_LDADD = \ src/libpspp.la \ src/libpspp-core.la \ $(GTK_LIBS) \ + $(CAIRO_LIBS) \ $(LIBINTL) src_ui_gui_psppiredir = $(pkgdatadir) diff --git a/src/ui/gui/executor.c b/src/ui/gui/executor.c index 9336f7ce..aa2fae51 100644 --- a/src/ui/gui/executor.c +++ b/src/ui/gui/executor.c @@ -104,7 +104,5 @@ execute_syntax (struct getl_interface *sss) som_flush (); - psppire_output_window_reload (); - return retval; } diff --git a/src/ui/gui/find-dialog.c b/src/ui/gui/find-dialog.c index 40e91bc0..2319fb9f 100644 --- a/src/ui/gui/find-dialog.c +++ b/src/ui/gui/find-dialog.c @@ -34,6 +34,7 @@ which match particular strings */ #include #include #include +#include #include #include @@ -566,7 +567,8 @@ regexp_label_compare (const struct comparator *cmptr, static void regexp_destroy (struct comparator *cmptr) { - struct regexp_comparator *rec = (struct regexp_comparator *) cmptr; + struct regexp_comparator *rec + = UP_CAST (cmptr, struct regexp_comparator, parent); regfree (&rec->re); } @@ -574,7 +576,8 @@ regexp_destroy (struct comparator *cmptr) static void cmptr_value_destroy (struct comparator *cmptr) { - struct value_comparator *vc = (struct value_comparator *) cmptr; + struct value_comparator *vc + = UP_CAST (cmptr, struct value_comparator, parent); value_destroy (&vc->pattern, var_get_width (cmptr->var)); } @@ -583,7 +586,7 @@ static struct comparator * value_comparator_create (const struct variable *var, const PsppireDict *dict, const char *target) { struct value_comparator *vc = xzalloc (sizeof (*vc)); - struct comparator *cmptr = (struct comparator *) vc; + struct comparator *cmptr = &vc->parent; cmptr->flags = 0; cmptr->var = var; @@ -602,7 +605,7 @@ string_comparator_create (const struct variable *var, const PsppireDict *dict, enum string_cmp_flags flags) { struct string_comparator *ssc = xzalloc (sizeof (*ssc)); - struct comparator *cmptr = (struct comparator *) ssc; + struct comparator *cmptr = &ssc->parent; cmptr->flags = flags; cmptr->var = var; @@ -625,7 +628,7 @@ regexp_comparator_create (const struct variable *var, const PsppireDict *dict, c { int code; struct regexp_comparator *rec = xzalloc (sizeof (*rec)); - struct comparator *cmptr = (struct comparator *) rec; + struct comparator *cmptr = &rec->parent; cmptr->flags = flags; cmptr->var = var; diff --git a/src/ui/gui/output-viewer.glade b/src/ui/gui/output-viewer.glade index 0b709ee4..50d92d46 100644 --- a/src/ui/gui/output-viewer.glade +++ b/src/ui/gui/output-viewer.glade @@ -1,7 +1,7 @@ - - - + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 600 @@ -16,7 +16,6 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK _File @@ -27,18 +26,18 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-save True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-save True True + gtk-save-as True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-save-as True True @@ -49,7 +48,6 @@ - False False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK _Edit @@ -60,9 +58,9 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-copy True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-copy True True @@ -121,23 +119,52 @@ False + 0 - + True True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC + 112 + True - + + True + True + automatic + automatic + + + True + True + False + + + + + False + True + + + + True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - 5 + automatic + automatic + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + True + True + diff --git a/src/ui/gui/psppire-output-window.c b/src/ui/gui/psppire-output-window.c index b0eff950..35216d4e 100644 --- a/src/ui/gui/psppire-output-window.c +++ b/src/ui/gui/psppire-output-window.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008 Free Software Foundation + Copyright (C) 2008, 2009 Free Software Foundation This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,6 +21,10 @@ #include "helper.h" #include +#include +#include +#include +#include #include #include "about.h" @@ -38,7 +42,12 @@ #define _(msgid) gettext (msgid) #define N_(msgid) msgid - +enum + { + COL_TITLE, /* Table title. */ + COL_Y, /* Y position of top of title. */ + N_COLS + }; static void psppire_output_window_base_finalize (PsppireOutputWindowClass *, gpointer); static void psppire_output_window_base_init (PsppireOutputWindowClass *class); @@ -106,13 +115,152 @@ psppire_output_window_base_finalize (PsppireOutputWindowClass *class, gpointer class_data) { } - - +/* Output driver class. */ static PsppireOutputWindow *the_output_viewer = NULL; +static gboolean +expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data) +{ + struct som_entity *entity = g_object_get_data (G_OBJECT (widget), "entity"); + GdkWindow *window = widget->window; + cairo_t *cairo = gdk_cairo_create (GDK_DRAWABLE (window)); + struct outp_driver *driver = xr_create_driver (cairo); /* XXX can fail */ + struct tab_table *t = entity->ext; + void *rendering; + + rendering = entity->class->render_init (entity, driver, tab_l (t), + tab_r (t), tab_t (t), tab_b (t)); + + entity->class->title (rendering, 0, 0, + entity->table_num, entity->subtable_num, + entity->command_name); + entity->class->render (rendering, tab_l (t), tab_t (t), + tab_nc (t) - tab_r (t), + tab_nr (t) - tab_b (t)); + + entity->class->render_free (rendering); + driver->class->close_driver (driver); + outp_free_driver (driver); + return TRUE; +} +static void +psppire_output_submit (struct outp_driver *this, struct som_entity *entity) +{ + if (the_output_viewer == NULL) + { + the_output_viewer = PSPPIRE_OUTPUT_WINDOW (psppire_output_window_new ()); + gtk_widget_show_all (GTK_WIDGET (the_output_viewer)); + } + + if (entity->type == SOM_TABLE) + { + GdkWindow *window = GTK_WIDGET (the_output_viewer)->window; + cairo_t *cairo = gdk_cairo_create (GDK_DRAWABLE (window)); + struct outp_driver *driver = xr_create_driver (cairo); /* XXX can fail */ + struct tab_table *t = entity->ext; + GtkTreeStore *store; + GtkTreeIter item; + GtkTreePath *path; + GtkWidget *drawing_area; + void *rendering; + struct string title; + int tw, th; + + tab_ref (t); + rendering = entity->class->render_init (entity, driver, tab_l (t), + tab_r (t), tab_t (t), tab_b (t)); + entity->class->area (rendering, &tw, &th); + + drawing_area = gtk_drawing_area_new (); + gtk_widget_modify_bg (GTK_WIDGET (drawing_area), GTK_STATE_NORMAL, + >k_widget_get_style (drawing_area)->base[GTK_STATE_NORMAL]); + g_object_set_data (G_OBJECT (drawing_area), + "entity", som_entity_clone (entity)); + gtk_widget_set_size_request (drawing_area, tw / 1024, th / 1024); + gtk_layout_put (the_output_viewer->output, drawing_area, + 0, the_output_viewer->y); + gtk_widget_show (drawing_area); + g_signal_connect (G_OBJECT (drawing_area), "expose_event", + G_CALLBACK (expose_event_callback), NULL); + + entity->class->render_free (rendering); + driver->class->close_driver (driver); + outp_free_driver (driver); + + store = GTK_TREE_STORE (gtk_tree_view_get_model ( + the_output_viewer->overview)); + + ds_init_empty (&title); + if (entity->table_num != the_output_viewer->last_table_num) + { + gtk_tree_store_append (store, &item, NULL); + + ds_put_format (&title, "%d %s", + entity->table_num, entity->command_name); + gtk_tree_store_set (store, &item, + COL_TITLE, ds_cstr (&title), + COL_Y, the_output_viewer->y, + -1); + + /* XXX shouldn't save a GtkTreeIter */ + the_output_viewer->last_table_num = entity->table_num; + the_output_viewer->last_top_level = item; + } + + gtk_tree_store_append (store, &item, + &the_output_viewer->last_top_level); + ds_clear (&title); + ds_put_format (&title, "%d.%d %s", + entity->table_num, entity->subtable_num, + t->title ? t->title : entity->command_name); + gtk_tree_store_set (store, &item, + COL_TITLE, ds_cstr (&title), + COL_Y, the_output_viewer->y, + -1); + ds_destroy (&title); + + path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), + &the_output_viewer->last_top_level); + gtk_tree_view_expand_row (the_output_viewer->overview, path, TRUE); + gtk_tree_path_free (path); + + if (tw / 1024 > the_output_viewer->max_width) + the_output_viewer->max_width = tw / 1024; + the_output_viewer->y += th / 1024; + + gtk_layout_set_size (the_output_viewer->output, + the_output_viewer->max_width, the_output_viewer->y); + } + + gtk_window_set_urgency_hint (GTK_WINDOW (the_output_viewer), TRUE); +} + +static struct outp_class psppire_output_class = + { + "PSPPIRE", /* name */ + true, /* special */ + NULL, /* open_driver */ + NULL, /* close_driver */ + NULL, /* open_page */ + NULL, /* close_page */ + NULL, /* flush */ + NULL, /* output_chart */ + psppire_output_submit, /* submit */ + NULL, /* line */ + NULL, /* text_metrics */ + NULL, /* text_draw */ + }; + +void +psppire_output_window_setup (void) +{ + outp_register_driver (outp_allocate_driver (&psppire_output_class, + "PSPPIRE", 0)); +} + int viewer_length = 16; int viewer_width = 59; @@ -127,8 +275,6 @@ on_delete (GtkWidget *w, GdkEvent *event, gpointer user_data) the_output_viewer = NULL; - unlink (output_file_name()); - return FALSE; } @@ -139,99 +285,78 @@ cancel_urgency (GtkWindow *window, gpointer data) { gtk_window_set_urgency_hint (window, FALSE); } -/* Sets width and length according to the new size - of the output window */ + static void -on_textview_resize (GtkWidget *widget, - GtkAllocation *allocation, - gpointer user_data) +on_row_activate (GtkTreeView *overview, + GtkTreePath *path, + GtkTreeViewColumn *column, + PsppireOutputWindow *window) { - PangoContext * context ; - PangoLayout *layout ; - PangoRectangle logical; - GtkStyle *style; - gint right_margin, left_margin; - GtkTextView *text_view = GTK_TEXT_VIEW (widget); - - context = gtk_widget_create_pango_context (widget); - layout = pango_layout_new (context); - - style = gtk_widget_get_style (widget); - - pango_layout_set_font_description (layout, style->font_desc); - - /* Find the width of one character. We can use any character, because - the textview has a monospaced font */ - pango_layout_set_text (layout, "M", 1); - - pango_layout_get_extents (layout, NULL, &logical); - - left_margin = gtk_text_view_get_left_margin (text_view); - right_margin = gtk_text_view_get_right_margin (text_view); - - viewer_length = allocation->height / PANGO_PIXELS (logical.height); - viewer_width = (allocation->width - right_margin - left_margin) - / PANGO_PIXELS (logical.width); - - g_object_unref (G_OBJECT (layout)); - g_object_unref (G_OBJECT (context)); + GtkTreeModel *model; + GtkTreeIter iter; + GtkAdjustment *vadj; + GValue value = {0}; + double y, min, max; + + model = gtk_tree_view_get_model (overview); + if (!gtk_tree_model_get_iter (model, &iter, path)) + return; + + gtk_tree_model_get_value (model, &iter, COL_Y, &value); + y = g_value_get_long (&value); + g_value_unset (&value); + + vadj = gtk_layout_get_vadjustment (window->output); + min = vadj->lower; + max = vadj->upper - vadj->page_size; + if (y < min) + y = min; + else if (y > max) + y = max; + gtk_adjustment_set_value (vadj, y); } - static void psppire_output_window_init (PsppireOutputWindow *window) { - GtkBuilder *xml = builder_new ("output-viewer.ui"); - - GtkWidget *box = gtk_vbox_new (FALSE, 0); - - GtkWidget *sw = get_widget_assert (xml, "scrolledwindow1"); - - GtkWidget *menubar = get_widget_assert (xml, "menubar1"); - - window->textview = get_widget_assert (xml, "output-viewer-textview"); - + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkBuilder *xml; - gtk_container_add (GTK_CONTAINER (window), box); + xml = builder_new ("output-viewer.ui"); + gtk_widget_reparent (get_widget_assert (xml, "vbox1"), GTK_WIDGET (window)); - g_object_ref (menubar); - gtk_widget_unparent (menubar); + window->output = GTK_LAYOUT (get_widget_assert (xml, "output")); + window->y = 0; - g_object_ref (sw); - gtk_widget_unparent (sw); + window->overview = GTK_TREE_VIEW (get_widget_assert (xml, "overview")); + gtk_tree_view_set_model (window->overview, + GTK_TREE_MODEL (gtk_tree_store_new ( + N_COLS, + G_TYPE_STRING, /* COL_TITLE */ + G_TYPE_LONG))); /* COL_Y */ + window->last_table_num = -1; + column = gtk_tree_view_column_new (); + gtk_tree_view_append_column (GTK_TREE_VIEW (window->overview), column); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, renderer, TRUE); + gtk_tree_view_column_add_attribute (column, renderer, "text", COL_TITLE); - gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (box), sw, TRUE, TRUE, 0); + g_signal_connect (GTK_TREE_VIEW (window->overview), + "row-activated", G_CALLBACK (on_row_activate), window); - - gtk_widget_show_all (box); + gtk_widget_modify_bg (GTK_WIDGET (window->output), GTK_STATE_NORMAL, + >k_widget_get_style (GTK_WIDGET (window->output))->base[GTK_STATE_NORMAL]); connect_help (xml); - window->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->textview)); - g_signal_connect (window, "focus-in-event", G_CALLBACK (cancel_urgency), NULL); - { - /* Output uses ascii characters for tabular material. - So we need a monospaced font otherwise it'll look silly */ - PangoFontDescription *font_desc = - pango_font_description_from_string ("monospace"); - - gtk_widget_modify_font (window->textview, font_desc); - pango_font_description_free (font_desc); - } - - g_signal_connect (window->textview, "size-allocate", - G_CALLBACK (on_textview_resize), NULL); - - window->fp = NULL; - g_signal_connect (get_action_assert (xml,"help_about"), "activate", G_CALLBACK (about_new), @@ -269,108 +394,3 @@ psppire_output_window_new (void) "description", _("Output Viewer"), NULL)); } - -static void reload_viewer (PsppireOutputWindow *ow); - -void -psppire_output_window_reload (void) -{ - struct stat buf; - - /* If there is no output, then don't do anything */ - if (0 != stat (output_file_name(), &buf)) - return ; - - if ( NULL == the_output_viewer ) - { - the_output_viewer = PSPPIRE_OUTPUT_WINDOW (psppire_output_window_new ()); - gtk_widget_show (GTK_WIDGET (the_output_viewer)); - } - - reload_viewer (the_output_viewer); - -} - - -static void -reload_viewer (PsppireOutputWindow *ow) -{ - GtkTextIter end_iter; - GtkTextMark *mark ; - - char *line = NULL; - - gboolean chars_inserted = FALSE; - - gtk_text_buffer_get_end_iter (ow->buffer, &end_iter); - - line = xrealloc (line, sizeof (char) * (viewer_width + 1)); - - mark = gtk_text_buffer_create_mark (ow->buffer, NULL, &end_iter, TRUE); - -#ifdef __CYGWIN__ - /* - Apparently Windoze is not capabale of writing to a file whilst - another (or the same) process is reading from it. Therefore, we - must close the file after reading it, and clear the entire buffer - before writing to it. - This will be slower for large buffers, but should work - (in so far as anything ever works on windows). - */ - { - GtkTextIter start_iter; - FILE *fp = fopen (output_file_name(), "r"); - if ( !fp) - { - g_critical ("Cannot open %s\n", output_file_name()); - return; - } - - /* Delete all the entire buffer */ - gtk_text_buffer_get_start_iter (ow->buffer, &start_iter); - gtk_text_buffer_delete (ow->buffer, &start_iter, &end_iter); - - - gtk_text_buffer_get_start_iter (ow->buffer, &start_iter); - /* Read in the next lot of text */ - while (fgets (line, viewer_width + 1, fp) != NULL) - { - chars_inserted = TRUE; - gtk_text_buffer_insert (ow->buffer, &start_iter, line, -1); - } - - fclose (fp); - } -#else - { - if ( ow->fp == NULL) - { - ow->fp = fopen (output_file_name(), "r"); - if ( ow->fp == NULL) - { - g_critical ("Cannot open %s\n", output_file_name()); - return; - } - } - - /* Read in the next lot of text */ - while (fgets (line, viewer_width + 1, ow->fp) != NULL) - { - chars_inserted = TRUE; - gtk_text_buffer_insert (ow->buffer, &end_iter, line, -1); - } - } -#endif - - /* Scroll to where the start of this lot of text begins */ - gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (ow->textview), - mark, - 0.1, TRUE, 0.0, 0.0); - - - if ( chars_inserted ) - gtk_window_set_urgency_hint ( GTK_WINDOW (ow), TRUE); -} - - - diff --git a/src/ui/gui/psppire-output-window.h b/src/ui/gui/psppire-output-window.h index d11eca61..606a9504 100644 --- a/src/ui/gui/psppire-output-window.h +++ b/src/ui/gui/psppire-output-window.h @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008 Free Software Foundation + Copyright (C) 2008, 2009 Free Software Foundation This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,10 +31,6 @@ extern int viewer_length; extern int viewer_width ; -#define OUTPUT_FILE_NAME "psppire.txt" - - - G_BEGIN_DECLS #define PSPPIRE_OUTPUT_WINDOW_TYPE (psppire_output_window_get_type ()) @@ -56,9 +52,13 @@ struct _PsppireOutputWindow PsppireWindow parent; /* */ - GtkTextBuffer *buffer; /* The buffer which contains the text */ - GtkWidget *textview ; - FILE *fp; /* The file it's viewing */ + GtkLayout *output; + int max_width; + int y; + + GtkTreeView *overview; + int last_table_num; + GtkTreeIter last_top_level; }; struct _PsppireOutputWindowClass @@ -70,9 +70,7 @@ struct _PsppireOutputWindowClass GType psppire_output_window_get_type (void); GtkWidget* psppire_output_window_new (void); - -void psppire_output_window_reload (void); - +void psppire_output_window_setup (void); G_END_DECLS diff --git a/src/ui/gui/psppire.c b/src/ui/gui/psppire.c index 84918513..3f6d49a6 100644 --- a/src/ui/gui/psppire.c +++ b/src/ui/gui/psppire.c @@ -123,25 +123,7 @@ initialize (struct command_line_processor *clp, int argc, char **argv) create_icon_factory (); - { - const char *filename = output_file_name (); - - struct string config_string; - - ds_init_empty (&config_string); - - ds_put_format (&config_string, - "gui:ascii:screen:squeeze=on headers=off top-margin=0 " - "bottom-margin=0 paginate=off length=auto width=auto " - "emphasis=none " - "output-file=\"%s\" append=yes", filename); - - outp_configure_driver_line (ds_ss (&config_string)); - - unlink (filename); - - ds_destroy (&config_string); - } + psppire_output_window_setup (); journal_enable (); textdomain (PACKAGE); @@ -345,16 +327,3 @@ parse_non_options (int key, char *arg, struct argp_state *state) const struct argp non_option_argp = {NULL, parse_non_options, 0, 0, 0, 0, 0}; - - -const char * -output_file_name (void) -{ - const char *dir = default_output_path (); - static char *filename = NULL; - - if ( NULL == filename ) - filename = xasprintf ("%s%s", dir, OUTPUT_FILE_NAME); - - return filename; -} diff --git a/src/ui/gui/syntax-editor-source.c b/src/ui/gui/syntax-editor-source.c index 21437051..6ec866c9 100644 --- a/src/ui/gui/syntax-editor-source.c +++ b/src/ui/gui/syntax-editor-source.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2006 Free Software Foundation + Copyright (C) 2006, 2009 Free Software Foundation This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -72,7 +73,8 @@ read_line_from_buffer (struct getl_interface *i, gchar *text; GtkTextIter next_line; - struct syntax_editor_source *ses = (struct syntax_editor_source *) i; + struct syntax_editor_source *ses + = UP_CAST (i, struct syntax_editor_source, parent); if ( gtk_text_iter_compare (&ses->i, &ses->end) >= 0) return false; @@ -124,5 +126,5 @@ create_syntax_editor_source (GtkTextBuffer *buffer, ses->parent.location = location; - return (struct getl_interface *) ses; + return &ses->parent; } diff --git a/src/ui/gui/val-labs-dialog.c b/src/ui/gui/val-labs-dialog.c index 14eacabf..5f43ff49 100644 --- a/src/ui/gui/val-labs-dialog.c +++ b/src/ui/gui/val-labs-dialog.c @@ -324,7 +324,7 @@ on_remove (GtkWidget *w, gpointer data) struct val_labs_dialog *dialog = data; union value value; - const struct val_lab *vl; + struct val_lab *vl; get_selected_tuple (dialog, &value, NULL); vl = val_labs_lookup (dialog->labs, &value); diff --git a/src/ui/terminal/automake.mk b/src/ui/terminal/automake.mk index 9cde11c9..81b896dc 100644 --- a/src/ui/terminal/automake.mk +++ b/src/ui/terminal/automake.mk @@ -25,6 +25,7 @@ src_ui_terminal_pspp_LDADD = \ src/ui/libuicommon.la \ src/libpspp.la \ src/libpspp-core.la \ + $(CAIRO_LIBS) \ $(NCURSES_LIBS) \ $(LIBICONV) \ $(LIBINTL) $(LIBREADLINE) diff --git a/src/ui/terminal/read-line.c b/src/ui/terminal/read-line.c index 7b23f38d..f85e4e76 100644 --- a/src/ui/terminal/read-line.c +++ b/src/ui/terminal/read-line.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -107,8 +108,7 @@ static bool read_interactive (struct getl_interface *s, struct string *line) { - struct readln_source *is = - (struct readln_source *) s ; + struct readln_source *is = UP_CAST (s, struct readln_source, parent); return is->interactive_func (line, prompt_get_style ()); } @@ -215,7 +215,7 @@ create_readln_source (void) rlns->parent.read = read_interactive; rlns->parent.close = readln_close; - return (struct getl_interface *) rlns; + return &rlns->parent; } diff --git a/tests/automake.mk b/tests/automake.mk index 8a974a32..76ee1f23 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -194,6 +194,8 @@ nodist_TESTS = \ tests/libpspp/range-set-test \ tests/libpspp/sparse-array-test \ tests/libpspp/str-test \ + tests/libpspp/string-map-test \ + tests/libpspp/string-set-test \ tests/libpspp/tower-test TESTS = $(dist_TESTS) $(nodist_TESTS) @@ -288,6 +290,23 @@ tests_libpspp_str_test_SOURCES = \ tests/libpspp/str-test.c tests_libpspp_str_test_LDADD = src/libpspp/libpspp.la gl/libgl.la $(LIBINTL) +tests_libpspp_string_map_test_SOURCES = \ + src/libpspp/hash-functions.c \ + src/libpspp/hmap.c \ + src/libpspp/string-map.c \ + src/libpspp/string-set.c \ + tests/libpspp/string-map-test.c +tests_libpspp_string_map_test_LDADD = gl/libgl.la $(LIBINTL) +tests_libpspp_string_map_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10 + +tests_libpspp_string_set_test_SOURCES = \ + src/libpspp/hash-functions.c \ + src/libpspp/hmap.c \ + src/libpspp/string-set.c \ + tests/libpspp/string-set-test.c +tests_libpspp_string_set_test_LDADD = gl/libgl.la $(LIBINTL) +tests_libpspp_string_set_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10 + tests_libpspp_tower_test_SOURCES = \ src/libpspp/abt.c \ src/libpspp/abt.h \ diff --git a/tests/libpspp/hmap-test.c b/tests/libpspp/hmap-test.c index 4ca7f92f..64511b7b 100644 --- a/tests/libpspp/hmap-test.c +++ b/tests/libpspp/hmap-test.c @@ -342,6 +342,7 @@ check_hmap (struct hmap *hmap, const int data[], size_t cnt, size_t i, j; int *order; + check (hmap_is_empty (hmap) == (cnt == 0)); check (hmap_count (hmap) == cnt); check (cnt <= hmap_capacity (hmap)); @@ -378,7 +379,6 @@ check_hmap (struct hmap *hmap, const int data[], size_t cnt, for (p = hmap_first (hmap), i = 0; i < cnt; p = hmap_next (hmap, p), i++) { struct element *e = hmap_node_to_element (p); - size_t j; check (hmap_node_hash (&e->node) == hash (e->data)); for (j = 0; j < left; j++) diff --git a/tests/libpspp/hmapx-test.c b/tests/libpspp/hmapx-test.c index fc08ca61..5ad5d572 100644 --- a/tests/libpspp/hmapx-test.c +++ b/tests/libpspp/hmapx-test.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -262,6 +262,7 @@ check_hmapx (struct hmapx *hmapx, const int data[], size_t cnt, size_t i, j; int *order; + check (hmapx_is_empty (hmapx) == (cnt == 0)); check (hmapx_count (hmapx) == cnt); check (cnt <= hmapx_capacity (hmapx)); diff --git a/tests/libpspp/range-set-test.c b/tests/libpspp/range-set-test.c index e8cbffa5..8d6e6831 100644 --- a/tests/libpspp/range-set-test.c +++ b/tests/libpspp/range-set-test.c @@ -212,7 +212,7 @@ check_pattern (const struct range_set *rs, unsigned int pattern) caching. */ for (start = 0; start <= 32; start++) { - struct range_set *nonconst_rs = (struct range_set *) rs; + struct range_set *nonconst_rs = CONST_CAST (struct range_set *, rs); nonconst_rs->cache_end = 0; s1 = range_set_scan (rs, start); s2 = next_1bit (pattern, start); diff --git a/tests/libpspp/string-map-test.c b/tests/libpspp/string-map-test.c new file mode 100644 index 00000000..e3f3b796 --- /dev/null +++ b/tests/libpspp/string-map-test.c @@ -0,0 +1,906 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* This is a test program for the string_map_* routines defined in + string-map.c. This test program aims to be as comprehensive as possible. + "gcov -a -b" should report almost complete coverage of lines, blocks and + branches in string-map.c, except that one branch caused by hash collision is + not exercised because our hash function has so few collisions. "valgrind + --leak-check=yes --show-reachable=yes" should give a clean report. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Currently running test. */ +static const char *test_name; + +/* Exit with a failure code. + (Place a breakpoint on this function while debugging.) */ +static void +check_die (void) +{ + exit (EXIT_FAILURE); +} + +/* If OK is not true, prints a message about failure on the + current source file and the given LINE and terminates. */ +static void +check_func (bool ok, int line) +{ + if (!ok) + { + printf ("Check failed in %s test at %s, line %d\n", + test_name, __FILE__, line); + check_die (); + } +} + +/* Verifies that EXPR evaluates to true. + If not, prints a message citing the calling line number and + terminates. */ +#define check(EXPR) check_func ((EXPR), __LINE__) + +/* Prints a message about memory exhaustion and exits with a + failure code. */ +static void +xalloc_die (void) +{ + printf ("virtual memory exhausted\n"); + exit (EXIT_FAILURE); +} + +static void *xmalloc (size_t n) MALLOC_LIKE; +static void *xnmalloc (size_t n, size_t m) MALLOC_LIKE; +static void *xmemdup (const void *p, size_t n) MALLOC_LIKE; + +/* Allocates and returns N bytes of memory. */ +static void * +xmalloc (size_t n) +{ + if (n != 0) + { + void *p = malloc (n); + if (p == NULL) + xalloc_die (); + + return p; + } + else + return NULL; +} + +static void * +xmemdup (const void *p, size_t n) +{ + void *q = xmalloc (n); + memcpy (q, p, n); + return q; +} + +/* Clone STRING. */ +static char * +xstrdup (const char *string) +{ + return xmemdup (string, strlen (string) + 1); +} + +/* Allocates and returns N * M bytes of memory. */ +static void * +xnmalloc (size_t n, size_t m) +{ + if ((size_t) -1 / m <= n) + xalloc_die (); + return xmalloc (n * m); +} + +/* Support routines. */ + +enum { + IDX_BITS = 10, + MAX_IDX = 1 << IDX_BITS, + KEY_MASK = (MAX_IDX - 1), + KEY_SHIFT = 0, + VALUE_MASK = (MAX_IDX - 1) << IDX_BITS, + VALUE_SHIFT = IDX_BITS +}; + +static char *string_table[MAX_IDX]; + +static const char * +get_string (int idx) +{ + char **s; + + assert (idx >= 0 && idx < MAX_IDX); + s = &string_table[idx]; + if (*s == NULL) + { + *s = xmalloc (16); + sprintf (*s, "%d", idx); + } + return *s; +} + +static void +free_strings (void) +{ + int i; + + for (i = 0; i < MAX_IDX; i++) + free (string_table[i]); +} + +static const char * +make_key (int value) +{ + return get_string ((value & KEY_MASK) >> KEY_SHIFT); +} + +static const char * +make_value (int value) +{ + return get_string ((value & VALUE_MASK) >> VALUE_SHIFT); +} + +static int +random_value (unsigned int seed, int basis) +{ + return hash_int (seed, basis) & VALUE_MASK; +} + +/* Swaps *A and *B. */ +static void +swap (int *a, int *b) +{ + int t = *a; + *a = *b; + *b = t; +} + +/* Reverses the order of the CNT integers starting at VALUES. */ +static void +reverse (int *values, size_t cnt) +{ + size_t i = 0; + size_t j = cnt; + + while (j > i) + swap (&values[i++], &values[--j]); +} + +/* Arranges the CNT elements in VALUES into the lexicographically next greater + permutation. Returns true if successful. If VALUES is already the + lexicographically greatest permutation of its elements (i.e. ordered from + greatest to smallest), arranges them into the lexicographically least + permutation (i.e. ordered from smallest to largest) and returns false. + + Comparisons among elements of VALUES consider only the bits in KEY_MASK. */ +static bool +next_permutation (int *values, size_t cnt) +{ + if (cnt > 0) + { + size_t i = cnt - 1; + while (i != 0) + { + i--; + if ((values[i] & KEY_MASK) < (values[i + 1] & KEY_MASK)) + { + size_t j; + for (j = cnt - 1; + (values[i] & KEY_MASK) >= (values[j] & KEY_MASK); + j--) + continue; + swap (values + i, values + j); + reverse (values + (i + 1), cnt - (i + 1)); + return true; + } + } + + reverse (values, cnt); + } + + return false; +} + +/* Returns N!. */ +static unsigned int +factorial (unsigned int n) +{ + unsigned int value = 1; + while (n > 1) + value *= n--; + return value; +} + +/* Randomly shuffles the CNT elements in ARRAY, each of which is + SIZE bytes in size. */ +static void +random_shuffle (void *array_, size_t cnt, size_t size) +{ + char *array = array_; + char *tmp = xmalloc (size); + size_t i; + + for (i = 0; i < cnt; i++) + { + size_t j = rand () % (cnt - i) + i; + if (i != j) + { + memcpy (tmp, array + j * size, size); + memcpy (array + j * size, array + i * size, size); + memcpy (array + i * size, tmp, size); + } + } + + free (tmp); +} + +/* Checks that MAP contains the CNT strings in DATA, that its structure is + correct, and that certain operations on MAP produce the expected results. */ +static void +check_string_map (struct string_map *map, const int data[], size_t cnt) +{ + size_t i; + + check (string_map_is_empty (map) == (cnt == 0)); + check (string_map_count (map) == cnt); + + for (i = 0; i < cnt; i++) + { + struct string_map_node *node; + const char *key = make_key (data[i]); + const char *value = make_value (data[i]); + const char *found_value; + + check (string_map_contains (map, key)); + + node = string_map_find_node (map, key); + check (node != NULL); + check (!strcmp (key, string_map_node_get_key (node))); + check (!strcmp (value, string_map_node_get_value (node))); + + check (node == string_map_insert (map, key, "abc")); + check (!strcmp (value, string_map_node_get_value (node))); + + check (node == string_map_insert_nocopy (map, xstrdup (key), + xstrdup ("def"))); + check (!strcmp (value, string_map_node_get_value (node))); + + found_value = string_map_find (map, key); + check (found_value != NULL); + check (!strcmp (found_value, value)); + } + + check (!string_map_contains (map, "xxx")); + check (string_map_find (map, "z") == NULL); + check (string_map_find_node (map, "") == NULL); + check (!string_map_delete (map, "xyz")); + + if (cnt == 0) + check (string_map_first (map) == NULL); + else + { + const struct string_map_node *node; + int *data_copy; + int left; + + data_copy = xmemdup (data, cnt * sizeof *data); + left = cnt; + for (node = string_map_first (map), i = 0; i < cnt; + node = string_map_next (map, node), i++) + { + const char *key = string_map_node_get_key (node); + const char *value = string_map_node_get_value (node); + size_t j; + + for (j = 0; j < left; j++) + if (!strcmp (key, make_key (data_copy[j])) + || !strcmp (value, make_value (data_copy[j]))) + { + data_copy[j] = data_copy[--left]; + goto next; + } + check_die (); + + next: ; + } + check (node == NULL); + free (data_copy); + } +} + +/* Inserts the CNT strings from 0 to CNT - 1 (inclusive) into a map in the + order specified by INSERTIONS, then deletes them in the order specified by + DELETIONS, checking the map's contents for correctness after each + operation. */ +static void +test_insert_delete (const int insertions[], + const int deletions[], + size_t cnt) +{ + struct string_map map; + size_t i; + + string_map_init (&map); + check_string_map (&map, NULL, 0); + for (i = 0; i < cnt; i++) + { + check (string_map_insert (&map, make_key (insertions[i]), + make_value (insertions[i]))); + check_string_map (&map, insertions, i + 1); + } + for (i = 0; i < cnt; i++) + { + check (string_map_delete (&map, make_key (deletions[i]))); + check_string_map (&map, deletions + i + 1, cnt - i - 1); + } + string_map_destroy (&map); +} + +/* Inserts strings into a map in each possible order, then removes them in each + possible order, up to a specified maximum size. */ +static void +test_insert_any_remove_any (void) +{ + const int basis = 0; + const int max_elems = 5; + int cnt; + + for (cnt = 0; cnt <= max_elems; cnt++) + { + int *insertions, *deletions; + unsigned int ins_perm_cnt; + int i; + + insertions = xnmalloc (cnt, sizeof *insertions); + deletions = xnmalloc (cnt, sizeof *deletions); + for (i = 0; i < cnt; i++) + insertions[i] = i | random_value (i, basis); + + for (ins_perm_cnt = 0; + ins_perm_cnt == 0 || next_permutation (insertions, cnt); + ins_perm_cnt++) + { + unsigned int del_perm_cnt; + int i; + + for (i = 0; i < cnt; i++) + deletions[i] = i | random_value (i, basis); + + for (del_perm_cnt = 0; + del_perm_cnt == 0 || next_permutation (deletions, cnt); + del_perm_cnt++) + test_insert_delete (insertions, deletions, cnt); + + check (del_perm_cnt == factorial (cnt)); + } + check (ins_perm_cnt == factorial (cnt)); + + free (insertions); + free (deletions); + } +} + +/* Inserts strings into a map in each possible order, then removes them in the + same order, up to a specified maximum size. */ +static void +test_insert_any_remove_same (void) +{ + const int max_elems = 7; + int cnt; + + for (cnt = 0; cnt <= max_elems; cnt++) + { + int *values; + unsigned int permutation_cnt; + int i; + + values = xnmalloc (cnt, sizeof *values); + for (i = 0; i < cnt; i++) + values[i] = i | random_value (i, 1); + + for (permutation_cnt = 0; + permutation_cnt == 0 || next_permutation (values, cnt); + permutation_cnt++) + test_insert_delete (values, values, cnt); + check (permutation_cnt == factorial (cnt)); + + free (values); + } +} + +/* Inserts strings into a map in each possible order, then + removes them in reverse order, up to a specified maximum + size. */ +static void +test_insert_any_remove_reverse (void) +{ + const int max_elems = 7; + int cnt; + + for (cnt = 0; cnt <= max_elems; cnt++) + { + int *insertions, *deletions; + unsigned int permutation_cnt; + int i; + + insertions = xnmalloc (cnt, sizeof *insertions); + deletions = xnmalloc (cnt, sizeof *deletions); + for (i = 0; i < cnt; i++) + insertions[i] = i | random_value (i, 2); + + for (permutation_cnt = 0; + permutation_cnt == 0 || next_permutation (insertions, cnt); + permutation_cnt++) + { + memcpy (deletions, insertions, sizeof *insertions * cnt); + reverse (deletions, cnt); + + test_insert_delete (insertions, deletions, cnt); + } + check (permutation_cnt == factorial (cnt)); + + free (insertions); + free (deletions); + } +} + +/* Inserts and removes strings in a map, in random order. */ +static void +test_random_sequence (void) +{ + const int basis = 3; + const int max_elems = 64; + const int max_trials = 8; + int cnt; + + for (cnt = 0; cnt <= max_elems; cnt += 2) + { + int *insertions, *deletions; + int trial; + int i; + + insertions = xnmalloc (cnt, sizeof *insertions); + deletions = xnmalloc (cnt, sizeof *deletions); + for (i = 0; i < cnt; i++) + insertions[i] = i | random_value (i, basis); + for (i = 0; i < cnt; i++) + deletions[i] = i | random_value (i, basis); + + for (trial = 0; trial < max_trials; trial++) + { + random_shuffle (insertions, cnt, sizeof *insertions); + random_shuffle (deletions, cnt, sizeof *deletions); + + test_insert_delete (insertions, deletions, cnt); + } + + free (insertions); + free (deletions); + } +} + +/* Inserts strings into a map in ascending order, then delete in ascending + order. */ +static void +test_insert_ordered (void) +{ + const int max_elems = 64; + int *values; + struct string_map map; + int i; + + string_map_init (&map); + values = xnmalloc (max_elems, sizeof *values); + for (i = 0; i < max_elems; i++) + { + values[i] = i | random_value (i, 4); + string_map_insert_nocopy (&map, xstrdup (make_key (values[i])), + xstrdup (make_value (values[i]))); + check_string_map (&map, values, i + 1); + } + for (i = 0; i < max_elems; i++) + { + string_map_delete (&map, make_key (i)); + check_string_map (&map, values + i + 1, max_elems - i - 1); + } + string_map_destroy (&map); + free (values); +} + +/* Inserts and replaces strings in a map, in random order. */ +static void +test_replace (void) +{ + const int basis = 15; + enum { MAX_ELEMS = 16 }; + const int max_trials = 8; + int cnt; + + for (cnt = 0; cnt <= MAX_ELEMS; cnt++) + { + int insertions[MAX_ELEMS]; + int trial; + int i; + + for (i = 0; i < cnt; i++) + insertions[i] = (i / 2) | random_value (i, basis); + + for (trial = 0; trial < max_trials; trial++) + { + struct string_map map; + int data[MAX_ELEMS]; + int n_data; + + /* Insert with replacement in random order. */ + n_data = 0; + string_map_init (&map); + random_shuffle (insertions, cnt, sizeof *insertions); + for (i = 0; i < cnt; i++) + { + const char *key = make_key (insertions[i]); + const char *value = make_value (insertions[i]); + int j; + + for (j = 0; j < n_data; j++) + if ((data[j] & KEY_MASK) == (insertions[i] & KEY_MASK)) + { + data[j] = insertions[i]; + goto found; + } + data[n_data++] = insertions[i]; + found: + + if (i % 2) + string_map_replace (&map, key, value); + else + string_map_replace_nocopy (&map, + xstrdup (key), xstrdup (value)); + check_string_map (&map, data, n_data); + } + + /* Delete in original order. */ + for (i = 0; i < cnt; i++) + { + const char *expected_value; + char *value; + int j; + + expected_value = NULL; + for (j = 0; j < n_data; j++) + if ((data[j] & KEY_MASK) == (insertions[i] & KEY_MASK)) + { + expected_value = make_value (data[j]); + data[j] = data[--n_data]; + break; + } + + value = string_map_find_and_delete (&map, + make_key (insertions[i])); + check ((value != NULL) == (expected_value != NULL)); + check (value == NULL || !strcmp (value, expected_value)); + free (value); + } + assert (string_map_is_empty (&map)); + + string_map_destroy (&map); + } + } +} + +static void +make_patterned_map (struct string_map *map, unsigned int pattern, int basis, + int insertions[], int *np) +{ + int n; + int i; + + string_map_init (map); + + n = 0; + for (i = 0; pattern != 0; i++) + if (pattern & (1u << i)) + { + pattern &= pattern - 1; + insertions[n] = i | random_value (i, basis); + check (string_map_insert (map, make_key (insertions[n]), + make_value (insertions[n]))); + n++; + } + check_string_map (map, insertions, n); + + *np = n; +} + +static void +for_each_map (void (*cb)(struct string_map *, int data[], int n), + int basis) +{ + enum { MAX_ELEMS = 5 }; + unsigned int pattern; + + for (pattern = 0; pattern < (1u << MAX_ELEMS); pattern++) + { + int data[MAX_ELEMS]; + struct string_map map; + int n; + + make_patterned_map (&map, pattern, basis, data, &n); + (*cb) (&map, data, n); + string_map_destroy (&map); + } +} + +static void +for_each_pair_of_maps ( + void (*cb)(struct string_map *a, int a_data[], int n_a, + struct string_map *b, int b_data[], int n_b), + int a_basis, int b_basis) +{ + enum { MAX_ELEMS = 5 }; + unsigned int a_pattern, b_pattern; + + for (a_pattern = 0; a_pattern < (1u << MAX_ELEMS); a_pattern++) + for (b_pattern = 0; b_pattern < (1u << MAX_ELEMS); b_pattern++) + { + int a_data[MAX_ELEMS], b_data[MAX_ELEMS]; + struct string_map a_map, b_map; + int n_a, n_b; + + make_patterned_map (&a_map, a_pattern, a_basis, a_data, &n_a); + make_patterned_map (&b_map, b_pattern, b_basis, b_data, &n_b); + (*cb) (&a_map, a_data, n_a, &b_map, b_data, n_b); + string_map_destroy (&a_map); + string_map_destroy (&b_map); + } +} + +static void +clear_cb (struct string_map *map, int data[] UNUSED, int n UNUSED) +{ + string_map_clear (map); + check_string_map (map, NULL, 0); +} + +static void +test_clear (void) +{ + for_each_map (clear_cb, 5); +} + +static void +clone_cb (struct string_map *map, int data[], int n) +{ + struct string_map clone; + + string_map_clone (&clone, map); + check_string_map (&clone, data, n); + string_map_destroy (&clone); +} + +static void +test_clone (void) +{ + for_each_map (clone_cb, 6); +} + +static void +node_swap_value_cb (struct string_map *map, int data[], int n) +{ + int i; + + for (i = 0; i < n; i++) + { + const char *value = make_value (data[i]); + struct string_map_node *node; + char *old_value; + + node = string_map_find_node (map, make_key (data[i])); + check (node != NULL); + check (!strcmp (string_map_node_get_value (node), value)); + data[i] = (data[i] & KEY_MASK) | random_value (i, 15); + old_value = string_map_node_swap_value (node, make_value (data[i])); + check (old_value != NULL); + check (!strcmp (value, old_value)); + free (old_value); + } +} + +static void +test_node_swap_value (void) +{ + for_each_map (node_swap_value_cb, 14); +} + +static void +swap_cb (struct string_map *a, int a_data[], int n_a, + struct string_map *b, int b_data[], int n_b) +{ + string_map_swap (a, b); + check_string_map (a, b_data, n_b); + check_string_map (b, a_data, n_a); +} + +static void +test_swap (void) +{ + for_each_pair_of_maps (swap_cb, 7, 8); +} + +static void +insert_map_cb (struct string_map *a, int a_data[], int n_a, + struct string_map *b, int b_data[], int n_b) +{ + int i, j; + + string_map_insert_map (a, b); + + for (i = 0; i < n_b; i++) + { + for (j = 0; j < n_a; j++) + if ((b_data[i] & KEY_MASK) == (a_data[j] & KEY_MASK)) + goto found; + a_data[n_a++] = b_data[i]; + found:; + } + check_string_map (a, a_data, n_a); + check_string_map (b, b_data, n_b); +} + +static void +test_insert_map (void) +{ + for_each_pair_of_maps (insert_map_cb, 91, 10); +} + +static void +replace_map_cb (struct string_map *a, int a_data[], int n_a, + struct string_map *b, int b_data[], int n_b) +{ + int i, j; + + string_map_replace_map (a, b); + + for (i = 0; i < n_b; i++) + { + for (j = 0; j < n_a; j++) + if ((b_data[i] & KEY_MASK) == (a_data[j] & KEY_MASK)) + { + a_data[j] = (a_data[j] & KEY_MASK) | (b_data[i] & VALUE_MASK); + goto found; + } + a_data[n_a++] = b_data[i]; + found:; + } + check_string_map (a, a_data, n_a); + check_string_map (b, b_data, n_b); +} + +static void +test_replace_map (void) +{ + for_each_pair_of_maps (replace_map_cb, 11, 12); +} + +static void +check_set (struct string_set *set, const int *data, int n_data, + int mask, int shift) +{ + int *unique; + int n_unique; + int i; + + n_unique = 0; + unique = xmalloc (n_data * sizeof *unique); + for (i = 0; i < n_data; i++) + { + int idx = (data[i] & mask) >> shift; + int j; + + for (j = 0; j < n_unique; j++) + if (unique[j] == idx) + goto found; + unique[n_unique++] = idx; + found:; + } + + check (string_set_count (set) == n_unique); + for (i = 0; i < n_unique; i++) + check (string_set_contains (set, get_string (unique[i]))); + string_set_destroy (set); + free (unique); +} + +static void +get_keys_and_values_cb (struct string_map *map, int data[], int n) +{ + struct string_set keys, values; + + string_set_init (&keys); + string_set_init (&values); + string_map_get_keys (map, &keys); + string_map_get_values (map, &values); + check_set (&keys, data, n, KEY_MASK, KEY_SHIFT); + check_set (&values, data, n, VALUE_MASK, VALUE_SHIFT); +} + +static void +test_get_keys_and_values (void) +{ + for_each_map (get_keys_and_values_cb, 13); +} + +static void +test_destroy_null (void) +{ + string_map_destroy (NULL); +} + +/* Main program. */ + +/* Runs TEST_FUNCTION and prints a message about NAME. */ +static void +run_test (void (*test_function) (void), const char *name) +{ + test_name = name; + putchar ('.'); + fflush (stdout); + test_function (); +} + +int +main (void) +{ + run_test (test_insert_any_remove_any, "insert any order, delete any order"); + run_test (test_insert_any_remove_same, + "insert any order, delete same order"); + run_test (test_insert_any_remove_reverse, + "insert any order, delete reverse order"); + run_test (test_random_sequence, "insert and delete in random sequence"); + run_test (test_replace, "insert and replace in random sequence"); + run_test (test_insert_ordered, "insert in ascending order"); + run_test (test_clear, "clear"); + run_test (test_clone, "clone"); + run_test (test_swap, "swap"); + run_test (test_node_swap_value, "node_swap_value"); + run_test (test_insert_map, "insert_map"); + run_test (test_replace_map, "replace_map"); + run_test (test_get_keys_and_values, "get keys and values"); + run_test (test_destroy_null, "destroying null table"); + + putchar ('\n'); + + free_strings (); + + return 0; +} diff --git a/tests/libpspp/string-set-test.c b/tests/libpspp/string-set-test.c new file mode 100644 index 00000000..6aafef44 --- /dev/null +++ b/tests/libpspp/string-set-test.c @@ -0,0 +1,681 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* This is a test program for the string_set_* routines defined in + string-set.c. This test program aims to be as comprehensive as possible. + "gcov -a -b" should report almost complete coverage of lines, blocks and + branches in string-set.c, except that one branch caused by hash collision is + not exercised because our hash function has so few collisions. "valgrind + --leak-check=yes --show-reachable=yes" should give a clean report. */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Currently running test. */ +static const char *test_name; + +/* Exit with a failure code. + (Place a breakpoint on this function while debugging.) */ +static void +check_die (void) +{ + exit (EXIT_FAILURE); +} + +/* If OK is not true, prints a message about failure on the + current source file and the given LINE and terminates. */ +static void +check_func (bool ok, int line) +{ + if (!ok) + { + printf ("Check failed in %s test at %s, line %d\n", + test_name, __FILE__, line); + check_die (); + } +} + +/* Verifies that EXPR evaluates to true. + If not, prints a message citing the calling line number and + terminates. */ +#define check(EXPR) check_func ((EXPR), __LINE__) + +/* Prints a message about memory exhaustion and exits with a + failure code. */ +static void +xalloc_die (void) +{ + printf ("virtual memory exhausted\n"); + exit (EXIT_FAILURE); +} + +static void *xmalloc (size_t n) MALLOC_LIKE; +static void *xnmalloc (size_t n, size_t m) MALLOC_LIKE; +static void *xmemdup (const void *p, size_t n) MALLOC_LIKE; + +/* Allocates and returns N bytes of memory. */ +static void * +xmalloc (size_t n) +{ + if (n != 0) + { + void *p = malloc (n); + if (p == NULL) + xalloc_die (); + + return p; + } + else + return NULL; +} + +static void * +xmemdup (const void *p, size_t n) +{ + void *q = xmalloc (n); + memcpy (q, p, n); + return q; +} + +/* Clone STRING. */ +static char * +xstrdup (const char *string) +{ + return xmemdup (string, strlen (string) + 1); +} + +/* Allocates and returns N * M bytes of memory. */ +static void * +xnmalloc (size_t n, size_t m) +{ + if ((size_t) -1 / m <= n) + xalloc_die (); + return xmalloc (n * m); +} + +/* Support routines. */ + +enum { MAX_VALUE = 1024 }; + +static char *string_table[MAX_VALUE]; + +static const char * +make_string (int value) +{ + char **s; + + assert (value >= 0 && value < MAX_VALUE); + s = &string_table[value]; + if (*s == NULL) + { + *s = xmalloc (16); + sprintf (*s, "%d", value); + } + return *s; +} + +static void +free_strings (void) +{ + int i; + + for (i = 0; i < MAX_VALUE; i++) + free (string_table[i]); +} + +/* Swaps *A and *B. */ +static void +swap (int *a, int *b) +{ + int t = *a; + *a = *b; + *b = t; +} + +/* Reverses the order of the CNT integers starting at VALUES. */ +static void +reverse (int *values, size_t cnt) +{ + size_t i = 0; + size_t j = cnt; + + while (j > i) + swap (&values[i++], &values[--j]); +} + +/* Arranges the CNT elements in VALUES into the lexicographically + next greater permutation. Returns true if successful. + If VALUES is already the lexicographically greatest + permutation of its elements (i.e. ordered from greatest to + smallest), arranges them into the lexicographically least + permutation (i.e. ordered from smallest to largest) and + returns false. */ +static bool +next_permutation (int *values, size_t cnt) +{ + if (cnt > 0) + { + size_t i = cnt - 1; + while (i != 0) + { + i--; + if (values[i] < values[i + 1]) + { + size_t j; + for (j = cnt - 1; values[i] >= values[j]; j--) + continue; + swap (values + i, values + j); + reverse (values + (i + 1), cnt - (i + 1)); + return true; + } + } + + reverse (values, cnt); + } + + return false; +} + +/* Returns N!. */ +static unsigned int +factorial (unsigned int n) +{ + unsigned int value = 1; + while (n > 1) + value *= n--; + return value; +} + +/* Randomly shuffles the CNT elements in ARRAY, each of which is + SIZE bytes in size. */ +static void +random_shuffle (void *array_, size_t cnt, size_t size) +{ + char *array = array_; + char *tmp = xmalloc (size); + size_t i; + + for (i = 0; i < cnt; i++) + { + size_t j = rand () % (cnt - i) + i; + if (i != j) + { + memcpy (tmp, array + j * size, size); + memcpy (array + j * size, array + i * size, size); + memcpy (array + i * size, tmp, size); + } + } + + free (tmp); +} + +/* Checks that SET contains the CNT strings in DATA, that its structure is + correct, and that certain operations on SET produce the expected results. */ +static void +check_string_set (struct string_set *set, const int data[], size_t cnt) +{ + size_t i; + + check (string_set_is_empty (set) == (cnt == 0)); + check (string_set_count (set) == cnt); + + for (i = 0; i < cnt; i++) + { + struct string_set_node *node; + const char *s = make_string (data[i]); + + check (string_set_contains (set, s)); + check (!string_set_insert (set, s)); + check (!string_set_insert_nocopy (set, xstrdup (s))); + + node = string_set_find_node (set, s); + check (node != NULL); + check (!strcmp (s, string_set_node_get_string (node))); + } + + check (!string_set_contains (set, "xxx")); + check (string_set_find_node (set, "") == NULL); + + if (cnt == 0) + check (string_set_first (set) == NULL); + else + { + const struct string_set_node *node; + int *data_copy; + int left; + + data_copy = xmemdup (data, cnt * sizeof *data); + left = cnt; + for (node = string_set_first (set), i = 0; i < cnt; + node = string_set_next (set, node), i++) + { + const char *s = string_set_node_get_string (node); + size_t j; + + for (j = 0; j < left; j++) + if (!strcmp (s, make_string (data_copy[j]))) + { + data_copy[j] = data_copy[--left]; + goto next; + } + check_die (); + + next: ; + } + check (node == NULL); + free (data_copy); + } +} + +/* Inserts the CNT strings from 0 to CNT - 1 (inclusive) into a set in the + order specified by INSERTIONS, then deletes them in the order specified by + DELETIONS, checking the set's contents for correctness after each + operation. */ +static void +test_insert_delete (const int insertions[], + const int deletions[], + size_t cnt) +{ + struct string_set set; + size_t i; + + string_set_init (&set); + check_string_set (&set, NULL, 0); + for (i = 0; i < cnt; i++) + { + check (string_set_insert (&set, make_string (insertions[i]))); + check_string_set (&set, insertions, i + 1); + } + for (i = 0; i < cnt; i++) + { + check (string_set_delete (&set, make_string (deletions[i]))); + check_string_set (&set, deletions + i + 1, cnt - i - 1); + } + string_set_destroy (&set); +} + +/* Inserts strings into a set in each possible order, then removes them in each + possible order, up to a specified maximum size. */ +static void +test_insert_any_remove_any (void) +{ + const int max_elems = 5; + int cnt; + + for (cnt = 0; cnt <= max_elems; cnt++) + { + int *insertions, *deletions; + unsigned int ins_perm_cnt; + int i; + + insertions = xnmalloc (cnt, sizeof *insertions); + deletions = xnmalloc (cnt, sizeof *deletions); + for (i = 0; i < cnt; i++) + insertions[i] = i; + + for (ins_perm_cnt = 0; + ins_perm_cnt == 0 || next_permutation (insertions, cnt); + ins_perm_cnt++) + { + unsigned int del_perm_cnt; + int i; + + for (i = 0; i < cnt; i++) + deletions[i] = i; + + for (del_perm_cnt = 0; + del_perm_cnt == 0 || next_permutation (deletions, cnt); + del_perm_cnt++) + test_insert_delete (insertions, deletions, cnt); + + check (del_perm_cnt == factorial (cnt)); + } + check (ins_perm_cnt == factorial (cnt)); + + free (insertions); + free (deletions); + } +} + +/* Inserts strings into a set in each possible order, then removes them in the + same order, up to a specified maximum size. */ +static void +test_insert_any_remove_same (void) +{ + const int max_elems = 7; + int cnt; + + for (cnt = 0; cnt <= max_elems; cnt++) + { + int *values; + unsigned int permutation_cnt; + int i; + + values = xnmalloc (cnt, sizeof *values); + for (i = 0; i < cnt; i++) + values[i] = i; + + for (permutation_cnt = 0; + permutation_cnt == 0 || next_permutation (values, cnt); + permutation_cnt++) + test_insert_delete (values, values, cnt); + check (permutation_cnt == factorial (cnt)); + + free (values); + } +} + +/* Inserts strings into a set in each possible order, then + removes them in reverse order, up to a specified maximum + size. */ +static void +test_insert_any_remove_reverse (void) +{ + const int max_elems = 7; + int cnt; + + for (cnt = 0; cnt <= max_elems; cnt++) + { + int *insertions, *deletions; + unsigned int permutation_cnt; + int i; + + insertions = xnmalloc (cnt, sizeof *insertions); + deletions = xnmalloc (cnt, sizeof *deletions); + for (i = 0; i < cnt; i++) + insertions[i] = i; + + for (permutation_cnt = 0; + permutation_cnt == 0 || next_permutation (insertions, cnt); + permutation_cnt++) + { + memcpy (deletions, insertions, sizeof *insertions * cnt); + reverse (deletions, cnt); + + test_insert_delete (insertions, deletions, cnt); + } + check (permutation_cnt == factorial (cnt)); + + free (insertions); + free (deletions); + } +} + +/* Inserts and removes strings in a set, in random order. */ +static void +test_random_sequence (void) +{ + const int max_elems = 64; + const int max_trials = 8; + int cnt; + + for (cnt = 0; cnt <= max_elems; cnt += 2) + { + int *insertions, *deletions; + int trial; + int i; + + insertions = xnmalloc (cnt, sizeof *insertions); + deletions = xnmalloc (cnt, sizeof *deletions); + for (i = 0; i < cnt; i++) + insertions[i] = i; + for (i = 0; i < cnt; i++) + deletions[i] = i; + + for (trial = 0; trial < max_trials; trial++) + { + random_shuffle (insertions, cnt, sizeof *insertions); + random_shuffle (deletions, cnt, sizeof *deletions); + + test_insert_delete (insertions, deletions, cnt); + } + + free (insertions); + free (deletions); + } +} + +/* Inserts strings into a set in ascending order, then delete in ascending + order. */ +static void +test_insert_ordered (void) +{ + const int max_elems = 64; + int *values; + struct string_set set; + int i; + + string_set_init (&set); + values = xnmalloc (max_elems, sizeof *values); + for (i = 0; i < max_elems; i++) + { + values[i] = i; + string_set_insert_nocopy (&set, xstrdup (make_string (i))); + check_string_set (&set, values, i + 1); + } + for (i = 0; i < max_elems; i++) + { + string_set_delete (&set, make_string (i)); + check_string_set (&set, values + i + 1, max_elems - i - 1); + } + string_set_destroy (&set); + free (values); +} + +static void +test_boolean_ops (void (*function)(struct string_set *a, struct string_set *b, + unsigned int *a_pat, unsigned int *b_pat)) +{ + enum { MAX_STRINGS = 7 }; + unsigned int a_pat, b_pat; + + for (a_pat = 0; a_pat < (1u << MAX_STRINGS); a_pat++) + for (b_pat = 0; b_pat < (1u << MAX_STRINGS); b_pat++) + { + unsigned int new_a_pat = a_pat; + unsigned int new_b_pat = b_pat; + struct string_set a, b; + int a_strings[MAX_STRINGS], b_strings[MAX_STRINGS]; + size_t i, n_a, n_b; + + string_set_init (&a); + string_set_init (&b); + for (i = 0; i < MAX_STRINGS; i++) + { + if (a_pat & (1u << i)) + string_set_insert (&a, make_string (i)); + if (b_pat & (1u << i)) + string_set_insert (&b, make_string (i)); + } + + function (&a, &b, &new_a_pat, &new_b_pat); + + n_a = n_b = 0; + for (i = 0; i < MAX_STRINGS; i++) + { + if (new_a_pat & (1u << i)) + a_strings[n_a++] = i; + if (new_b_pat & (1u << i)) + b_strings[n_b++] = i; + } + check_string_set (&a, a_strings, n_a); + check_string_set (&b, b_strings, n_b); + string_set_destroy (&a); + string_set_destroy (&b); + } +} + +static void +union_cb (struct string_set *a, struct string_set *b, + unsigned int *a_pat, unsigned int *b_pat) +{ + string_set_union (a, b); + *a_pat |= *b_pat; +} + +static void +test_union (void) +{ + test_boolean_ops (union_cb); +} + +static void +union_and_intersection_cb (struct string_set *a, struct string_set *b, + unsigned int *a_pat, unsigned int *b_pat) +{ + unsigned int orig_a_pat = *a_pat; + unsigned int orig_b_pat = *b_pat; + + string_set_union_and_intersection (a, b); + *a_pat = orig_a_pat | orig_b_pat; + *b_pat = orig_a_pat & orig_b_pat; +} + +static void +test_union_and_intersection (void) +{ + test_boolean_ops (union_and_intersection_cb); +} + +static void +intersect_cb (struct string_set *a, struct string_set *b, + unsigned int *a_pat, unsigned int *b_pat) +{ + string_set_intersect (a, b); + *a_pat &= *b_pat; +} + +static void +test_intersect (void) +{ + test_boolean_ops (intersect_cb); +} + +static void +subtract_cb (struct string_set *a, struct string_set *b, + unsigned int *a_pat, unsigned int *b_pat) +{ + string_set_subtract (a, b); + *a_pat &= ~*b_pat; +} + +static void +test_subtract (void) +{ + test_boolean_ops (subtract_cb); +} + +static void +swap_cb (struct string_set *a, struct string_set *b, + unsigned int *a_pat, unsigned int *b_pat) +{ + unsigned int tmp; + string_set_swap (a, b); + tmp = *a_pat; + *a_pat = *b_pat; + *b_pat = tmp; +} + +static void +test_swap (void) +{ + test_boolean_ops (swap_cb); +} + +static void +clear_cb (struct string_set *a, struct string_set *b UNUSED, + unsigned int *a_pat, unsigned int *b_pat UNUSED) +{ + string_set_clear (a); + *a_pat = 0; +} + +static void +test_clear (void) +{ + test_boolean_ops (clear_cb); +} + +static void +clone_cb (struct string_set *a, struct string_set *b, + unsigned int *a_pat, unsigned int *b_pat) +{ + string_set_destroy (a); + string_set_clone (a, b); + *a_pat = *b_pat; +} + +static void +test_clone (void) +{ + test_boolean_ops (clone_cb); +} + +static void +test_destroy_null (void) +{ + string_set_destroy (NULL); +} + +/* Main program. */ + +/* Runs TEST_FUNCTION and prints a message about NAME. */ +static void +run_test (void (*test_function) (void), const char *name) +{ + test_name = name; + putchar ('.'); + fflush (stdout); + test_function (); +} + +int +main (void) +{ + run_test (test_insert_any_remove_any, "insert any order, delete any order"); + run_test (test_insert_any_remove_same, + "insert any order, delete same order"); + run_test (test_insert_any_remove_reverse, + "insert any order, delete reverse order"); + run_test (test_random_sequence, "insert and delete in random sequence"); + run_test (test_insert_ordered, "insert in ascending order"); + run_test (test_union, "union"); + run_test (test_union_and_intersection, "union and intersection"); + run_test (test_intersect, "intersect"); + run_test (test_subtract, "subtract"); + run_test (test_swap, "swap"); + run_test (test_clear, "clear"); + run_test (test_clone, "clone"); + run_test (test_destroy_null, "destroying null table"); + + putchar ('\n'); + + free_strings (); + + return 0; +}