From 7fc95240daaa1c2d6e4ff61a559a4feedef4fcbd Mon Sep 17 00:00:00 2001 From: Victor Wagner Date: Tue, 31 Dec 2002 19:38:08 +0000 Subject: [PATCH] First checked in version --- Makefile | 27 + TODO | 71 + colors/150color.clr | 152 ++ colors/50grays.clr | 52 + colors/aspect.clr | 181 ++ colors/aspect8.clr | 256 ++ colors/bw100.clr | 256 ++ colors/bw17.clr | 17 + colors/bw256.clr | 257 ++ colors/bw256inv.clr | 256 ++ colors/bw5.clr | 5 + colors/bw64.clr | 64 + colors/default.clr | 256 ++ colors/digdoq.clr | 256 ++ colors/drgbw.clr | 256 ++ colors/drgclr.clr | 256 ++ colors/ega.clr | 17 + colors/fort.clr | 12 + colors/lesson.clr | 17 + colors/luse.clr | 11 + colors/names.clr | 25 + colors/pal100.clr | 256 ++ colors/pal24.clr | 26 + colors/pal255.clr | 256 ++ colors/rainbow.clr | 257 ++ colors/random.clr | 256 ++ dll/Makefile | 47 + dll/fgis.h | 122 + dll/fgisCount.c | 34 + dll/fgisEppCalc.c | 161 ++ dll/fgisEppDraw.c | 364 +++ dll/fgisEppEdit.c | 186 ++ dll/fgisEppEdit.h | 26 + dll/fgisInit.c | 126 + dll/fgisInt.h | 72 + dll/fgisMisc.c | 133 + dll/fgisPalette.c | 272 ++ dll/fgisPatterns.c | 402 +++ dll/fgisPlanchet.c | 255 ++ dll/fgisProjection.c | 25 + dll/fgisRaster.c | 998 +++++++ dll/fgisVector.c | 12 + dll/patterns.n | 13 + doc/.log | 40 + doc/3rd.attempt | 282 ++ doc/concepts.html | 360 +++ doc/doc.formats | 37 + doc/epu_doc.tex | 181 ++ doc/layers.doc | 91 + doc/levels.eps | 147 + doc/levels.fig | 56 + doc/levels.gif | Bin 0 -> 2540 bytes doc/levels.pbm | 3300 +++++++++++++++++++++++ doc/levels.xbm | 1209 +++++++++ doc/lib_doc.tex | 1196 +++++++++ doc/lib_doc.toc | 33 + doc/object_concept | 218 ++ doc/region.concept | 31 + doc/visualisagion.concept | 18 + epu/Makefile | 42 + epu/bil2epp | Bin 0 -> 60478 bytes epu/bil2epp.c | 137 + epu/border.c | 526 ++++ epu/centers.c | 78 + epu/clip.c | 154 ++ epu/cluster | Bin 0 -> 85838 bytes epu/cluster.c | 841 ++++++ epu/dgt2gen | Bin 0 -> 74260 bytes epu/dgt2gen.c | 128 + epu/eheader.c | 564 ++++ epu/extents.c | 187 ++ epu/fill.c | 157 ++ epu/intable | Bin 0 -> 66559 bytes epu/intable.c | 252 ++ epu/mosaic.c | 125 + epu/neighbours.c | 147 + epu/outtab.c | 180 ++ epu/outtable.c | 386 +++ epu/outtable.h | 56 + epu/outtable_func.c | 467 ++++ epu/points.tab | 262 ++ epu/project | Bin 0 -> 237951 bytes epu/project.c | 373 +++ epu/reclass1.c | 93 + epu/tag2epp.c | 32 + epu/window.c | 85 + fgis.rc | 30 + include/Makefile | 14 + include/clr.h | 6 + include/defpal.h | 256 ++ include/dgt.h | 164 ++ include/epp.h | 148 ++ include/epp_err.h | 26 + include/eppl.h | 74 + include/eppl_ut.h | 19 + include/getopt.h | 132 + include/reclass.h | 30 + include/regex.h | 490 ++++ lib/Makefile | 64 + lib/TODO.lib | 16 + lib/byteorder.c | 18 + lib/clr.c | 52 + lib/dgt_dist.c | 21 + lib/dgt_input.c | 112 + lib/dgt_iter.c | 27 + lib/dgt_output.c | 211 ++ lib/epp_cache.c | 66 + lib/epp_input.c | 274 ++ lib/epp_iter.c | 64 + lib/epp_loaded.c | 327 +++ lib/epp_output.c | 525 ++++ lib/epp_private.h | 20 + lib/file_utils.c | 86 + lib/gnu_lib/getopt.c | 757 ++++++ lib/gnu_lib/getopt.h | 132 + lib/gnu_lib/getopt1.c | 187 ++ lib/gnu_lib/regex.c | 5171 ++++++++++++++++++++++++++++++++++++ lib/gnu_lib/regex.h | 490 ++++ lib/lookup.c | 30 + lib/overlay.c | 53 + lib/reclass.tab.c | 967 +++++++ lib/reclass.y | 131 + lib/test/Makefile | 26 + lib/test/recltest.c | 17 + lib/test/test8.epp | Bin 0 -> 640 bytes lib/test/test_epplib.c | 286 ++ lib/test/testdata.dat | 57 + maketar | 16 + man/border.1 | 60 + man/clip.1 | 43 + man/cluster.1 | 71 + man/eheader.1 | 209 ++ man/extents.1 | 71 + man/fgisRasterColorImage.n | 94 + man/legend.n | 85 + man/mosaic.1 | 62 + man/neighbours.1 | 43 + man/outtable.1 | 153 ++ man/palette.n | 67 + man/planchet.n | 535 ++++ man/projection.n | 85 + man/raster.n | 326 +++ man/reclass.1 | 92 + man/window.1 | 47 + pkgIndex.tcl | 1 + symbols/alpha10.sym | 148 ++ symbols/alpha6.sym | 81 + symbols/digit25.sym | 405 +++ symbols/digit6.sym | 22 + symbols/fort10.sym | 12 + symbols/gray5.sym | 27 + symbols/luse6.sym | 18 + symbols/misc14.sym | 47 + symbols/misc16.sym | 236 ++ symbols/misc25.sym | 661 +++++ symbols/misc3.sym | 27 + symbols/misc8.sym | 44 + symbols/tone10a.sym | 145 + symbols/tone10b.sym | 19 + symbols/tone10c.sym | 14 + symbols/tone10d.sym | 48 + symbols/tone5.sym | 98 + symbols/tone6a.sym | 227 ++ symbols/tone6b.sym | 70 + tcl/admin.layer | 96 + tcl/balloonhelp.tcl | 225 ++ tcl/calculator.tcl | 523 ++++ tcl/combobox.tcl | 353 +++ tcl/console.tcl | 2237 ++++++++++++++++ tcl/draw.tcl | 14 + tcl/getopt.tcl | 206 ++ tcl/help.tcl | 405 +++ tcl/hierarchy.tcl | 1253 +++++++++ tcl/html_library.tcl | 1417 ++++++++++ tcl/hypermap | 136 + tcl/layer.tcl | 567 ++++ tcl/legend.tcl | 136 + tcl/lesras.lay | 30 + tcl/mapview | 35 + tcl/objects.tcl | 87 + tcl/planchet.tcl | 1011 +++++++ tcl/progressbar.tcl | 619 +++++ tcl/tabnotebook.tcl | 555 ++++ tcl/tclIndex | 79 + tcl/toolbar.tcl | 145 + tcl/ventry.tcl | 241 ++ tcl/viewer.tcl | 200 ++ tcl/widget.tcl | 812 ++++++ testdata/admin.epp | Bin 0 -> 45568 bytes testdata/admin.lay | 96 + testdata/admin.leg | 87 + testdata/admin_html.leg | 86 + testdata/html/1.html | 10 + testdata/html/10.html | 10 + testdata/html/11.html | 10 + testdata/html/12.html | 10 + testdata/html/13.html | 10 + testdata/html/14.html | 10 + testdata/html/15.html | 10 + testdata/html/16.html | 10 + testdata/html/17.html | 10 + testdata/html/18.html | 10 + testdata/html/19.html | 10 + testdata/html/2.html | 10 + testdata/html/20.html | 10 + testdata/html/21.html | 10 + testdata/html/22.html | 10 + testdata/html/23.html | 10 + testdata/html/24.html | 10 + testdata/html/25.html | 10 + testdata/html/26.html | 10 + testdata/html/27.html | 10 + testdata/html/28.html | 10 + testdata/html/29.html | 10 + testdata/html/3.html | 10 + testdata/html/30.html | 10 + testdata/html/31.html | 10 + testdata/html/32.html | 10 + testdata/html/33.html | 10 + testdata/html/34.html | 10 + testdata/html/35.html | 10 + testdata/html/36.html | 10 + testdata/html/37.html | 10 + testdata/html/38.html | 10 + testdata/html/39.html | 10 + testdata/html/4.html | 10 + testdata/html/40.html | 10 + testdata/html/41.html | 10 + testdata/html/42.html | 10 + testdata/html/43.html | 10 + testdata/html/44.html | 10 + testdata/html/45.html | 10 + testdata/html/46.html | 10 + testdata/html/47.html | 10 + testdata/html/48.html | 10 + testdata/html/49.html | 10 + testdata/html/5.html | 10 + testdata/html/50.html | 10 + testdata/html/51.html | 10 + testdata/html/52.html | 10 + testdata/html/53.html | 10 + testdata/html/54.html | 10 + testdata/html/55.html | 10 + testdata/html/56.html | 10 + testdata/html/57.html | 10 + testdata/html/58.html | 10 + testdata/html/59.html | 10 + testdata/html/6.html | 10 + testdata/html/60.html | 10 + testdata/html/61.html | 10 + testdata/html/62.html | 10 + testdata/html/63.html | 10 + testdata/html/64.html | 10 + testdata/html/65.html | 10 + testdata/html/66.html | 10 + testdata/html/67.html | 10 + testdata/html/68.html | 10 + testdata/html/69.html | 10 + testdata/html/7.html | 10 + testdata/html/70.html | 10 + testdata/html/71.html | 10 + testdata/html/72.html | 10 + testdata/html/73.html | 10 + testdata/html/74.html | 10 + testdata/html/75.html | 10 + testdata/html/76.html | 10 + testdata/html/77.html | 10 + testdata/html/78.html | 10 + testdata/html/79.html | 10 + testdata/html/8.html | 10 + testdata/html/80.html | 15 + testdata/html/81.html | 10 + testdata/html/82.html | 10 + testdata/html/83.html | 10 + testdata/html/84.html | 10 + testdata/html/85.html | 10 + testdata/html/86.html | 10 + testdata/html/9.html | 10 + testdata/lesras.epp | Bin 0 -> 84096 bytes testdata/lesras.lay | 30 + testdata/lesras.leg | 22 + testdata/mkhtml.tcl | 24 + testdata/pgrm.epp | Bin 0 -> 75008 bytes testdata/poger.epp | Bin 0 -> 60160 bytes testdata/soil_mo.clr | 37 + testdata/soil_mo.epp | Bin 0 -> 67968 bytes testdata/soil_mo.leg | 34 + testdata/test.prj | 5 + 288 files changed, 48123 insertions(+) create mode 100644 Makefile create mode 100644 TODO create mode 100644 colors/150color.clr create mode 100644 colors/50grays.clr create mode 100644 colors/aspect.clr create mode 100644 colors/aspect8.clr create mode 100644 colors/bw100.clr create mode 100644 colors/bw17.clr create mode 100644 colors/bw256.clr create mode 100644 colors/bw256inv.clr create mode 100644 colors/bw5.clr create mode 100644 colors/bw64.clr create mode 100644 colors/default.clr create mode 100644 colors/digdoq.clr create mode 100644 colors/drgbw.clr create mode 100644 colors/drgclr.clr create mode 100644 colors/ega.clr create mode 100644 colors/fort.clr create mode 100644 colors/lesson.clr create mode 100644 colors/luse.clr create mode 100644 colors/names.clr create mode 100644 colors/pal100.clr create mode 100644 colors/pal24.clr create mode 100644 colors/pal255.clr create mode 100644 colors/rainbow.clr create mode 100644 colors/random.clr create mode 100644 dll/Makefile create mode 100644 dll/fgis.h create mode 100644 dll/fgisCount.c create mode 100644 dll/fgisEppCalc.c create mode 100644 dll/fgisEppDraw.c create mode 100644 dll/fgisEppEdit.c create mode 100644 dll/fgisEppEdit.h create mode 100644 dll/fgisInit.c create mode 100644 dll/fgisInt.h create mode 100644 dll/fgisMisc.c create mode 100644 dll/fgisPalette.c create mode 100644 dll/fgisPatterns.c create mode 100644 dll/fgisPlanchet.c create mode 100644 dll/fgisProjection.c create mode 100644 dll/fgisRaster.c create mode 100644 dll/fgisVector.c create mode 100644 dll/patterns.n create mode 100644 doc/.log create mode 100644 doc/3rd.attempt create mode 100644 doc/concepts.html create mode 100644 doc/doc.formats create mode 100644 doc/epu_doc.tex create mode 100644 doc/layers.doc create mode 100644 doc/levels.eps create mode 100644 doc/levels.fig create mode 100644 doc/levels.gif create mode 100644 doc/levels.pbm create mode 100644 doc/levels.xbm create mode 100644 doc/lib_doc.tex create mode 100644 doc/lib_doc.toc create mode 100644 doc/object_concept create mode 100644 doc/region.concept create mode 100644 doc/visualisagion.concept create mode 100644 epu/Makefile create mode 100755 epu/bil2epp create mode 100644 epu/bil2epp.c create mode 100644 epu/border.c create mode 100644 epu/centers.c create mode 100644 epu/clip.c create mode 100755 epu/cluster create mode 100644 epu/cluster.c create mode 100755 epu/dgt2gen create mode 100644 epu/dgt2gen.c create mode 100644 epu/eheader.c create mode 100644 epu/extents.c create mode 100644 epu/fill.c create mode 100755 epu/intable create mode 100644 epu/intable.c create mode 100644 epu/mosaic.c create mode 100644 epu/neighbours.c create mode 100644 epu/outtab.c create mode 100644 epu/outtable.c create mode 100644 epu/outtable.h create mode 100644 epu/outtable_func.c create mode 100644 epu/points.tab create mode 100755 epu/project create mode 100644 epu/project.c create mode 100644 epu/reclass1.c create mode 100644 epu/tag2epp.c create mode 100644 epu/window.c create mode 100644 fgis.rc create mode 100644 include/Makefile create mode 100644 include/clr.h create mode 100644 include/defpal.h create mode 100644 include/dgt.h create mode 100644 include/epp.h create mode 100644 include/epp_err.h create mode 100644 include/eppl.h create mode 100644 include/eppl_ut.h create mode 100644 include/getopt.h create mode 100644 include/reclass.h create mode 100644 include/regex.h create mode 100644 lib/Makefile create mode 100644 lib/TODO.lib create mode 100644 lib/byteorder.c create mode 100644 lib/clr.c create mode 100644 lib/dgt_dist.c create mode 100644 lib/dgt_input.c create mode 100644 lib/dgt_iter.c create mode 100644 lib/dgt_output.c create mode 100644 lib/epp_cache.c create mode 100644 lib/epp_input.c create mode 100644 lib/epp_iter.c create mode 100644 lib/epp_loaded.c create mode 100644 lib/epp_output.c create mode 100644 lib/epp_private.h create mode 100644 lib/file_utils.c create mode 100644 lib/gnu_lib/getopt.c create mode 100644 lib/gnu_lib/getopt.h create mode 100644 lib/gnu_lib/getopt1.c create mode 100644 lib/gnu_lib/regex.c create mode 100644 lib/gnu_lib/regex.h create mode 100644 lib/lookup.c create mode 100644 lib/overlay.c create mode 100644 lib/reclass.tab.c create mode 100644 lib/reclass.y create mode 100644 lib/test/Makefile create mode 100644 lib/test/recltest.c create mode 100644 lib/test/test8.epp create mode 100644 lib/test/test_epplib.c create mode 100644 lib/test/testdata.dat create mode 100755 maketar create mode 100644 man/border.1 create mode 100644 man/clip.1 create mode 100644 man/cluster.1 create mode 100644 man/eheader.1 create mode 100644 man/extents.1 create mode 100644 man/fgisRasterColorImage.n create mode 100644 man/legend.n create mode 100644 man/mosaic.1 create mode 100644 man/neighbours.1 create mode 100644 man/outtable.1 create mode 100644 man/palette.n create mode 100644 man/planchet.n create mode 100644 man/projection.n create mode 100644 man/raster.n create mode 100644 man/reclass.1 create mode 100644 man/window.1 create mode 100644 pkgIndex.tcl create mode 100644 symbols/alpha10.sym create mode 100644 symbols/alpha6.sym create mode 100644 symbols/digit25.sym create mode 100644 symbols/digit6.sym create mode 100644 symbols/fort10.sym create mode 100644 symbols/gray5.sym create mode 100644 symbols/luse6.sym create mode 100644 symbols/misc14.sym create mode 100644 symbols/misc16.sym create mode 100644 symbols/misc25.sym create mode 100644 symbols/misc3.sym create mode 100644 symbols/misc8.sym create mode 100644 symbols/tone10a.sym create mode 100644 symbols/tone10b.sym create mode 100644 symbols/tone10c.sym create mode 100644 symbols/tone10d.sym create mode 100644 symbols/tone5.sym create mode 100644 symbols/tone6a.sym create mode 100644 symbols/tone6b.sym create mode 100644 tcl/admin.layer create mode 100644 tcl/balloonhelp.tcl create mode 100644 tcl/calculator.tcl create mode 100644 tcl/combobox.tcl create mode 100644 tcl/console.tcl create mode 100644 tcl/draw.tcl create mode 100644 tcl/getopt.tcl create mode 100644 tcl/help.tcl create mode 100644 tcl/hierarchy.tcl create mode 100644 tcl/html_library.tcl create mode 100755 tcl/hypermap create mode 100644 tcl/layer.tcl create mode 100644 tcl/legend.tcl create mode 100644 tcl/lesras.lay create mode 100755 tcl/mapview create mode 100644 tcl/objects.tcl create mode 100644 tcl/planchet.tcl create mode 100644 tcl/progressbar.tcl create mode 100644 tcl/tabnotebook.tcl create mode 100644 tcl/tclIndex create mode 100644 tcl/toolbar.tcl create mode 100644 tcl/ventry.tcl create mode 100644 tcl/viewer.tcl create mode 100644 tcl/widget.tcl create mode 100644 testdata/admin.epp create mode 100644 testdata/admin.lay create mode 100644 testdata/admin.leg create mode 100644 testdata/admin_html.leg create mode 100644 testdata/html/1.html create mode 100644 testdata/html/10.html create mode 100644 testdata/html/11.html create mode 100644 testdata/html/12.html create mode 100644 testdata/html/13.html create mode 100644 testdata/html/14.html create mode 100644 testdata/html/15.html create mode 100644 testdata/html/16.html create mode 100644 testdata/html/17.html create mode 100644 testdata/html/18.html create mode 100644 testdata/html/19.html create mode 100644 testdata/html/2.html create mode 100644 testdata/html/20.html create mode 100644 testdata/html/21.html create mode 100644 testdata/html/22.html create mode 100644 testdata/html/23.html create mode 100644 testdata/html/24.html create mode 100644 testdata/html/25.html create mode 100644 testdata/html/26.html create mode 100644 testdata/html/27.html create mode 100644 testdata/html/28.html create mode 100644 testdata/html/29.html create mode 100644 testdata/html/3.html create mode 100644 testdata/html/30.html create mode 100644 testdata/html/31.html create mode 100644 testdata/html/32.html create mode 100644 testdata/html/33.html create mode 100644 testdata/html/34.html create mode 100644 testdata/html/35.html create mode 100644 testdata/html/36.html create mode 100644 testdata/html/37.html create mode 100644 testdata/html/38.html create mode 100644 testdata/html/39.html create mode 100644 testdata/html/4.html create mode 100644 testdata/html/40.html create mode 100644 testdata/html/41.html create mode 100644 testdata/html/42.html create mode 100644 testdata/html/43.html create mode 100644 testdata/html/44.html create mode 100644 testdata/html/45.html create mode 100644 testdata/html/46.html create mode 100644 testdata/html/47.html create mode 100644 testdata/html/48.html create mode 100644 testdata/html/49.html create mode 100644 testdata/html/5.html create mode 100644 testdata/html/50.html create mode 100644 testdata/html/51.html create mode 100644 testdata/html/52.html create mode 100644 testdata/html/53.html create mode 100644 testdata/html/54.html create mode 100644 testdata/html/55.html create mode 100644 testdata/html/56.html create mode 100644 testdata/html/57.html create mode 100644 testdata/html/58.html create mode 100644 testdata/html/59.html create mode 100644 testdata/html/6.html create mode 100644 testdata/html/60.html create mode 100644 testdata/html/61.html create mode 100644 testdata/html/62.html create mode 100644 testdata/html/63.html create mode 100644 testdata/html/64.html create mode 100644 testdata/html/65.html create mode 100644 testdata/html/66.html create mode 100644 testdata/html/67.html create mode 100644 testdata/html/68.html create mode 100644 testdata/html/69.html create mode 100644 testdata/html/7.html create mode 100644 testdata/html/70.html create mode 100644 testdata/html/71.html create mode 100644 testdata/html/72.html create mode 100644 testdata/html/73.html create mode 100644 testdata/html/74.html create mode 100644 testdata/html/75.html create mode 100644 testdata/html/76.html create mode 100644 testdata/html/77.html create mode 100644 testdata/html/78.html create mode 100644 testdata/html/79.html create mode 100644 testdata/html/8.html create mode 100644 testdata/html/80.html create mode 100644 testdata/html/81.html create mode 100644 testdata/html/82.html create mode 100644 testdata/html/83.html create mode 100644 testdata/html/84.html create mode 100644 testdata/html/85.html create mode 100644 testdata/html/86.html create mode 100644 testdata/html/9.html create mode 100755 testdata/lesras.epp create mode 100644 testdata/lesras.lay create mode 100644 testdata/lesras.leg create mode 100644 testdata/mkhtml.tcl create mode 100755 testdata/pgrm.epp create mode 100755 testdata/poger.epp create mode 100644 testdata/soil_mo.clr create mode 100644 testdata/soil_mo.epp create mode 100644 testdata/soil_mo.leg create mode 100644 testdata/test.prj diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..99bf0da --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ + +all: fgis.so epu doc + +fgis.so: dll/fgis.so + cp dll/fgis.so . + +dll/fgis.so: lib/libepp.a proj/libproj.a dll/*.c + cd dll; make fgis.so + +lib/libepp.a: + cd lib; make + +proj/libproj.a: + cd proj; make + +epu: lib/libepp.a epu/*.[chy] + cd epu; make all +clean: + for i in dll epu doc proj lib ; do make clean; done + +doc: + cd doc; make + +tar: + ./maketar + + diff --git a/TODO b/TODO new file mode 100644 index 0000000..a43c4e8 --- /dev/null +++ b/TODO @@ -0,0 +1,71 @@ +Near future + +Fgis tcl extension: + +1. Compile tcl extension for NT/Win 95 + +2. Finish pattern handling + +3. Write drawing of patterned raster + +4. Write projection object + +5. Finish editing primitives + +6. Separate tk-dependent part from non-GUI part of C code. + +7. Develop initialization code for Win32 + +Tcl scripts + +1. Invent interface to call EPU from within TCL + +2. Complete chart (choropleth) type of layer + +3. Write tag (point) type of layer + +4. Invent standartized interface to SQL databases (Postgres, Oracle, + ODBC for start) + +5. Write ``object'' layer - collection of arbitrary Tk canvas items, + which are treated as layer and can be saved and loaded + +EPU + +1. Debug outtable + +2. Write projection conversion tool + +3. Write evaluate + +4. Do something with border and debug rasterize + +5. Write ppmtoepp and epptoppm converters + +6. Design and write RADIUS + +7. Design and write INTERPOLATE + +Distribution: + +1. Write top-level Makefile + +2. Provide example dataset + +3. Write installation program for Win32 binary distr. + +Documentation + +1. Fill holes in docs for already written commands + +2. Document layered structure of fGIS + +3. Translte epp_lib docs to English + +4. Complete (and translate to english) EPU manual + +IDEAS TO CONSIDER + +fGIS user environment should be able to store layers in RCS + +Invent and document vector format diff --git a/colors/150color.clr b/colors/150color.clr new file mode 100644 index 0000000..4bef0c9 --- /dev/null +++ b/colors/150color.clr @@ -0,0 +1,152 @@ + 0 0 0 0 BLACK + 1 462 729 196 + 2 533 847 219 + 3 603 913 298 + 4 678 964 388 + 5 498 1000 749 LT. GREEN + 6 196 729 462 + 7 219 847 533 + 8 298 913 603 + 9 388 964 678 + 10 498 1000 749 + 11 0 729 0 + 12 0 796 0 + 13 0 862 0 + 14 0 929 0 + 15 0 1000 0 GREEN + 16 792 792 129 + 17 898 898 168 + 18 941 941 266 + 19 976 976 376 + 20 1000 1000 500 YELLOW + 21 1000 444 0 ORANGE + 22 1000 634 0 + 23 1000 730 0 + 24 1000 825 0 + 25 1000 904 0 + 26 729 462 196 + 27 847 533 219 + 28 913 603 298 + 29 964 678 388 + 30 1000 749 498 + 31 792 129 129 + 32 898 168 168 + 33 941 266 266 + 34 976 376 376 + 35 1000 498 498 + 36 729 0 0 + 37 796 0 0 DK. RED + 38 862 0 0 + 39 929 0 0 + 40 1000 0 0 RED + 41 650 215 215 DK. BROWN + 42 756 270 270 + 43 796 388 388 BROWN + 44 835 505 505 + 45 874 623 623 LT. BROWN + 46 650 215 650 + 47 756 270 756 + 48 796 388 796 + 49 835 505 835 + 50 874 623 874 + 51 0 729 729 DK. CYAN + 52 0 796 796 + 53 0 862 862 + 54 0 929 929 + 55 0 1000 1000 CYAN + 56 129 792 792 + 57 168 898 898 + 58 266 941 941 + 59 376 976 976 + 60 498 1000 1000 LT. CYAN + 61 215 650 650 + 62 270 756 756 + 63 388 796 796 + 64 505 835 835 + 65 623 874 874 + 66 0 0 929 DK. BLUE + 67 0 0 1000 BLUE + 68 298 576 996 + 69 196 678 996 + 70 98 819 996 LT. BLUE + 71 196 462 729 + 72 219 533 847 + 73 298 603 913 + 74 388 678 964 + 75 498 749 1000 + 76 462 196 729 DK. PURPLE + 77 533 219 847 + 78 603 298 913 PURPLE + 79 678 388 964 + 80 749 498 1000 LT. PURPLE + 81 729 0 729 DK. MAGENTA + 82 796 0 796 + 83 862 0 862 + 84 929 0 929 + 85 1000 0 1000 MAGENTA + 86 792 129 792 + 87 898 168 898 + 88 941 266 941 + 89 976 376 976 + 90 1000 498 1000 LT. MAGENTA + 91 1000 0 1000 + 92 240 1000 1000 + 93 500 1000 1000 + 94 750 1000 1000 + 95 750 750 1000 + 96 1000 500 1000 + 97 1000 750 1000 + 98 1000 1000 750 LT. YELLOW + 99 1000 1000 0 BT. YELLOW +100 1000 793 587 +101 750 1000 750 +102 500 1000 500 +103 627 313 0 +104 730 63 63 +105 627 313 0 +106 1000 650 650 +107 888 523 587 +108 825 571 269 +109 904 0 476 +110 1000 857 888 +111 0 0 0 BLACK +112 492 492 492 DK. GRAY +113 501 501 501 +114 507 507 507 +115 523 523 523 +116 539 539 539 +117 555 555 555 +118 555 555 555 +119 571 571 571 +120 587 587 587 +121 492 492 492 +122 603 603 603 +123 619 619 619 MD. GRAY +124 634 634 634 +125 666 666 666 +126 682 682 682 +127 698 698 698 +128 714 714 714 +129 730 730 730 +130 746 746 746 +131 746 746 746 +132 873 873 873 +133 761 761 761 +134 777 777 777 +135 793 793 793 +136 809 809 809 +137 825 825 825 +138 841 841 841 +139 857 857 857 +140 873 873 873 LT. GRAY +141 873 873 873 +142 886 886 886 +143 888 888 888 +144 904 904 904 +145 920 920 920 +146 936 936 936 +147 952 952 952 +148 952 952 952 +149 968 968 968 +150 1000 1000 1000 WHITE +255 1000 1000 1000 WHITE diff --git a/colors/50grays.clr b/colors/50grays.clr new file mode 100644 index 0000000..7624013 --- /dev/null +++ b/colors/50grays.clr @@ -0,0 +1,52 @@ +0 0 0 0 BLACK +1 0 0 0 BLACK +2 3 3 3 +3 31 31 31 +4 156 156 156 +5 478 478 478 +6 482 482 482 +7 494 494 494 +8 509 509 509 +9 525 525 525 +10 533 533 533 +11 541 541 541 +12 545 545 545 +13 576 576 576 +14 592 592 592 +15 603 603 603 +16 507 507 507 +17 611 611 611 +18 623 623 623 +19 635 635 635 +20 666 666 666 +21 670 670 670 +22 674 674 674 +23 682 682 682 +24 701 701 701 +25 713 713 713 +26 733 733 733 +27 737 737 737 +28 741 741 741 +29 756 756 756 +30 772 772 772 +31 788 788 788 +32 800 800 800 +33 803 803 803 +34 807 807 807 +35 835 835 835 +36 850 850 850 +37 866 866 866 +38 870 870 870 +39 874 874 874 +40 886 886 886 +41 894 894 894 +42 909 909 909 +43 929 929 929 +44 933 933 933 +45 937 937 937 +46 964 964 964 +47 968 968 968 +48 980 980 980 +49 984 984 984 +50 1000 1000 1000 +255 1000 1000 1000 diff --git a/colors/aspect.clr b/colors/aspect.clr new file mode 100644 index 0000000..9d8e885 --- /dev/null +++ b/colors/aspect.clr @@ -0,0 +1,181 @@ + 0 726 726 726 + 1 0 407 298 + 2 0 423 290 + 3 0 439 282 + 4 0 454 274 + 5 0 470 266 + 6 0 486 258 + 7 0 501 250 + 8 11 509 243 + 9 23 517 235 + 10 35 525 227 + 11 47 533 219 + 12 58 541 211 + 13 70 549 203 + 14 82 556 196 + 15 98 564 188 + 16 109 572 180 + 17 121 580 172 + 18 133 588 164 + 19 145 596 156 + 20 156 603 149 + 21 168 611 141 + 22 180 619 133 + 23 196 627 125 + 24 207 635 117 + 25 219 643 109 + 26 231 650 101 + 27 243 658 94 + 28 254 666 86 + 29 266 674 78 + 30 278 682 70 + 31 294 690 62 + 32 305 698 54 + 33 317 705 47 + 34 329 713 39 + 35 341 721 31 + 36 352 729 23 + 37 364 737 15 + 38 376 745 7 + 39 392 752 0 + 40 407 756 0 + 41 427 764 0 + 42 447 772 0 + 43 466 780 0 + 44 486 788 0 + 45 505 796 0 + 46 521 803 0 + 47 541 811 0 + 48 560 819 0 + 49 580 827 0 + 50 600 835 0 + 51 619 843 0 + 52 635 850 0 + 53 654 858 0 + 54 674 866 0 + 55 694 874 0 + 56 713 882 0 + 57 733 890 0 + 58 752 898 0 + 59 768 905 0 + 60 788 913 0 + 61 807 921 0 + 62 827 929 0 + 63 847 937 0 + 64 866 945 0 + 65 882 952 0 + 66 901 960 0 + 67 921 968 0 + 68 941 976 0 + 69 960 984 0 + 70 980 992 0 + 71 1000 1000 0 + 72 1000 980 0 + 73 1000 960 0 + 74 1000 941 0 + 75 1000 921 0 + 76 1000 901 0 + 77 1000 882 0 + 78 1000 866 0 + 79 1000 847 0 + 80 1000 827 0 + 81 1000 807 0 + 82 1000 788 0 + 83 1000 768 0 + 84 1000 752 0 + 85 1000 733 0 + 86 1000 713 0 + 87 1000 694 0 + 88 1000 674 0 + 89 1000 654 0 + 90 1000 635 0 + 91 1000 619 0 + 92 1000 600 0 + 93 1000 580 0 + 94 1000 560 0 + 95 1000 541 0 + 96 1000 521 0 + 97 1000 505 0 + 98 1000 486 0 + 99 1000 466 0 +100 1000 447 0 +101 1000 427 0 +102 1000 407 0 +103 1000 392 0 +104 1000 376 11 +105 1000 364 23 +106 1000 352 35 +107 1000 341 47 +108 1000 329 58 +109 1000 317 70 +110 1000 305 82 +111 1000 294 98 +112 1000 278 109 +113 1000 266 121 +114 1000 254 133 +115 1000 243 145 +116 1000 231 156 +117 1000 219 168 +118 1000 207 180 +119 1000 196 196 +120 1000 180 207 +121 1000 168 219 +122 1000 156 231 +123 1000 145 243 +124 1000 133 254 +125 1000 121 266 +126 1000 109 278 +127 1000 98 294 +128 1000 82 305 +129 1000 70 317 +130 1000 58 329 +131 1000 47 341 +132 1000 35 352 +133 1000 23 364 +134 1000 11 376 +135 1000 0 392 +136 988 0 400 +137 980 0 411 +138 968 0 419 +139 960 0 431 +140 952 0 439 +141 941 0 450 +142 933 0 458 +143 925 0 470 +144 913 0 478 +145 905 0 490 +146 898 0 498 +147 886 0 509 +148 878 0 517 +149 870 0 529 +150 858 0 537 +151 850 0 549 +152 682 0 674 +153 674 0 662 +154 662 0 647 +155 650 0 631 +156 643 0 619 +157 631 0 603 +158 623 0 592 +159 611 0 576 +160 600 0 560 +161 592 0 549 +162 580 0 533 +163 568 0 517 +164 560 0 505 +165 549 0 490 +166 541 0 478 +167 529 0 462 +168 549 0 447 +169 509 0 435 +170 498 0 419 +171 486 0 403 +172 478 0 392 +173 466 0 376 +174 458 0 364 +175 447 0 349 +176 435 0 333 +177 427 0 321 +178 415 0 305 +179 403 0 290 +180 396 0 278 \ No newline at end of file diff --git a/colors/aspect8.clr b/colors/aspect8.clr new file mode 100644 index 0000000..7eb7675 --- /dev/null +++ b/colors/aspect8.clr @@ -0,0 +1,256 @@ + 0 726 726 726 + 1 0 0 444 + 2 0 158 365 + 3 0 317 285 + 4 380 730 0 + 5 1000 825 0 + 6 1000 539 0 + 7 1000 285 15 + 8 1000 111 206 + 9 1000 1000 1000 + 10 1000 1000 1000 + 11 1000 1000 1000 + 12 1000 1000 1000 + 13 1000 1000 1000 + 14 1000 1000 1000 + 15 1000 1000 1000 + 16 0 0 0 + 17 0 0 0 + 18 0 0 0 + 19 0 0 0 + 20 0 0 0 + 21 0 0 0 + 22 0 0 0 + 23 0 0 0 + 24 0 0 0 + 25 0 0 0 + 26 0 0 0 + 27 0 0 0 + 28 0 0 0 + 29 0 0 0 + 30 0 0 0 + 31 0 0 0 + 32 0 0 0 + 33 0 0 0 + 34 0 0 0 + 35 0 0 0 + 36 0 0 0 + 37 0 0 0 + 38 0 0 0 + 39 0 0 0 + 40 0 0 0 + 41 0 0 0 + 42 0 0 0 + 43 0 0 0 + 44 0 0 0 + 45 0 0 0 + 46 0 0 0 + 47 0 0 0 + 48 0 0 0 + 49 0 0 0 + 50 0 0 0 + 51 0 0 0 + 52 0 0 0 + 53 0 0 0 + 54 0 0 0 + 55 0 0 0 + 56 0 0 0 + 57 0 0 0 + 58 0 0 0 + 59 0 0 0 + 60 0 0 0 + 61 0 0 0 + 62 0 0 0 + 63 0 0 0 + 64 0 0 0 + 65 0 0 0 + 66 0 0 0 + 67 0 0 0 + 68 0 0 0 + 69 0 0 0 + 70 0 0 0 + 71 0 0 0 + 72 0 0 0 + 73 0 0 0 + 74 0 0 0 + 75 0 0 0 + 76 0 0 0 + 77 0 0 0 + 78 0 0 0 + 79 0 0 0 + 80 0 0 0 + 81 0 0 0 + 82 0 0 0 + 83 0 0 0 + 84 0 0 0 + 85 0 0 0 + 86 0 0 0 + 87 0 0 0 + 88 0 0 0 + 89 0 0 0 + 90 0 0 0 + 91 0 0 0 + 92 0 0 0 + 93 0 0 0 + 94 0 0 0 + 95 0 0 0 + 96 0 0 0 + 97 0 0 0 + 98 0 0 0 + 99 0 0 0 +100 0 0 0 +101 0 0 0 +102 0 0 0 +103 0 0 0 +104 0 0 0 +105 0 0 0 +106 0 0 0 +107 0 0 0 +108 0 0 0 +109 0 0 0 +110 0 0 0 +111 0 0 0 +112 0 0 0 +113 0 0 0 +114 0 0 0 +115 0 0 0 +116 0 0 0 +117 0 0 0 +118 0 0 0 +119 0 0 0 +120 0 0 0 +121 0 0 0 +122 0 0 0 +123 0 0 0 +124 0 0 0 +125 0 0 0 +126 0 0 0 +127 0 0 0 +128 0 0 0 +129 0 0 0 +130 0 0 0 +131 0 0 0 +132 0 0 0 +133 0 0 0 +134 0 0 0 +135 0 0 0 +136 0 0 0 +137 0 0 0 +138 0 0 0 +139 0 0 0 +140 0 0 0 +141 0 0 0 +142 0 0 0 +143 0 0 0 +144 0 0 0 +145 0 0 0 +146 0 0 0 +147 0 0 0 +148 0 0 0 +149 0 0 0 +150 0 0 0 +151 0 0 0 +152 0 0 0 +153 0 0 0 +154 0 0 0 +155 0 0 0 +156 0 0 0 +157 0 0 0 +158 0 0 0 +159 0 0 0 +160 0 0 0 +161 0 0 0 +162 0 0 0 +163 0 0 0 +164 0 0 0 +165 0 0 0 +166 0 0 0 +167 0 0 0 +168 0 0 0 +169 0 0 0 +170 0 0 0 +171 0 0 0 +172 0 0 0 +173 0 0 0 +174 0 0 0 +175 0 0 0 +176 0 0 0 +177 0 0 0 +178 0 0 0 +179 0 0 0 +180 0 0 0 +181 0 0 0 +182 0 0 0 +183 0 0 0 +184 0 0 0 +185 0 0 0 +186 0 0 0 +187 0 0 0 +188 0 0 0 +189 0 0 0 +190 0 0 0 +191 0 0 0 +192 0 0 0 +193 0 0 0 +194 0 0 0 +195 0 0 0 +196 0 0 0 +197 0 0 0 +198 0 0 0 +199 0 0 0 +200 0 0 0 +201 0 0 0 +202 0 0 0 +203 0 0 0 +204 0 0 0 +205 0 0 0 +206 0 0 0 +207 0 0 0 +208 0 0 0 +209 0 0 0 +210 0 0 0 +211 0 0 0 +212 0 0 0 +213 0 0 0 +214 0 0 0 +215 0 0 0 +216 0 0 0 +217 0 0 0 +218 0 0 0 +219 0 0 0 +220 0 0 0 +221 0 0 0 +222 0 0 0 +223 0 0 0 +224 0 0 0 +225 0 0 0 +226 0 0 0 +227 0 0 0 +228 0 0 0 +229 0 0 0 +230 0 0 0 +231 0 0 0 +232 0 0 0 +233 0 0 0 +234 0 0 0 +235 0 0 0 +236 0 0 0 +237 0 0 0 +238 0 0 0 +239 0 0 0 +240 0 0 0 +241 0 0 0 +242 0 0 0 +243 0 0 0 +244 0 0 0 +245 0 0 0 +246 0 0 0 +247 0 0 0 +248 0 0 0 +249 0 0 0 +250 0 0 0 +251 0 0 0 +252 0 0 0 +253 0 0 0 +254 0 0 0 +255 1000 1000 1000 diff --git a/colors/bw100.clr b/colors/bw100.clr new file mode 100644 index 0000000..bf5ffc9 --- /dev/null +++ b/colors/bw100.clr @@ -0,0 +1,256 @@ + 0 0 0 0 + 1 0 0 0 + 2 15 15 15 + 3 15 15 15 + 4 31 31 31 + 5 47 47 47 + 6 47 47 47 + 7 63 63 63 + 8 79 79 79 + 9 79 79 79 + 10 95 95 95 + 11 95 95 95 + 12 111 111 111 + 13 126 126 126 + 14 126 126 126 + 15 142 142 142 + 16 158 158 158 + 17 158 158 158 + 18 174 174 174 + 19 174 174 174 + 20 190 190 190 + 21 206 206 206 + 22 206 206 206 + 23 222 222 222 + 24 238 238 238 + 25 238 238 238 + 26 253 253 253 + 27 269 269 269 + 28 269 269 269 + 29 285 285 285 + 30 285 285 285 + 31 301 301 301 + 32 317 317 317 + 33 317 317 317 + 34 333 333 333 + 35 349 349 349 + 36 349 349 349 + 37 365 365 365 + 38 365 365 365 + 39 380 380 380 + 40 396 396 396 + 41 396 396 396 + 42 412 412 412 + 43 428 428 428 + 44 428 428 428 + 45 444 444 444 + 46 444 444 444 + 47 460 460 460 + 48 476 476 476 + 49 476 476 476 + 50 492 492 492 + 51 507 507 507 + 52 507 507 507 + 53 523 523 523 + 54 539 539 539 + 55 539 539 539 + 56 555 555 555 + 57 555 555 555 + 58 571 571 571 + 59 587 587 587 + 60 587 587 587 + 61 603 603 603 + 62 619 619 619 + 63 619 619 619 + 64 634 634 634 + 65 634 634 634 + 66 650 650 650 + 67 666 666 666 + 68 666 666 666 + 69 682 682 682 + 70 698 698 698 + 71 698 698 698 + 72 714 714 714 + 73 714 714 714 + 74 730 730 730 + 75 746 746 746 + 76 746 746 746 + 77 761 761 761 + 78 777 777 777 + 79 777 777 777 + 80 793 793 793 + 81 809 809 809 + 82 809 809 809 + 83 825 825 825 + 84 825 825 825 + 85 841 841 841 + 86 857 857 857 + 87 857 857 857 + 88 873 873 873 + 89 888 888 888 + 90 888 888 888 + 91 904 904 904 + 92 904 904 904 + 93 920 920 920 + 94 936 936 936 + 95 936 936 936 + 96 952 952 952 + 97 968 968 968 + 98 968 968 968 + 99 984 984 984 +100 1000 1000 1000 +101 0 0 0 +102 0 0 0 +103 0 0 0 +104 0 0 0 +105 0 0 0 +106 0 0 0 +107 0 0 0 +108 0 0 0 +109 0 0 0 +110 0 0 0 +111 0 0 0 +112 0 0 0 +113 0 0 0 +114 0 0 0 +115 0 0 0 +116 0 0 0 +117 0 0 0 +118 0 0 0 +119 0 0 0 +120 0 0 0 +121 0 0 0 +122 0 0 0 +123 0 0 0 +124 0 0 0 +125 0 0 0 +126 0 0 0 +127 0 0 0 +128 0 0 0 +129 0 0 0 +130 0 0 0 +131 0 0 0 +132 0 0 0 +133 0 0 0 +134 0 0 0 +135 0 0 0 +136 0 0 0 +137 0 0 0 +138 0 0 0 +139 0 0 0 +140 0 0 0 +141 0 0 0 +142 0 0 0 +143 0 0 0 +144 0 0 0 +145 0 0 0 +146 0 0 0 +147 0 0 0 +148 0 0 0 +149 0 0 0 +150 0 0 0 +151 0 0 0 +152 0 0 0 +153 0 0 0 +154 0 0 0 +155 0 0 0 +156 0 0 0 +157 0 0 0 +158 0 0 0 +159 0 0 0 +160 0 0 0 +161 0 0 0 +162 0 0 0 +163 0 0 0 +164 0 0 0 +165 0 0 0 +166 0 0 0 +167 0 0 0 +168 0 0 0 +169 0 0 0 +170 0 0 0 +171 0 0 0 +172 0 0 0 +173 0 0 0 +174 0 0 0 +175 0 0 0 +176 0 0 0 +177 0 0 0 +178 0 0 0 +179 0 0 0 +180 0 0 0 +181 0 0 0 +182 0 0 0 +183 0 0 0 +184 0 0 0 +185 0 0 0 +186 0 0 0 +187 0 0 0 +188 0 0 0 +189 0 0 0 +190 0 0 0 +191 0 0 0 +192 0 0 0 +193 0 0 0 +194 0 0 0 +195 0 0 0 +196 0 0 0 +197 0 0 0 +198 0 0 0 +199 0 0 0 +200 0 0 0 +201 0 0 0 +202 0 0 0 +203 0 0 0 +204 0 0 0 +205 0 0 0 +206 0 0 0 +207 0 0 0 +208 0 0 0 +209 0 0 0 +210 0 0 0 +211 0 0 0 +212 0 0 0 +213 0 0 0 +214 0 0 0 +215 0 0 0 +216 0 0 0 +217 0 0 0 +218 0 0 0 +219 0 0 0 +220 0 0 0 +221 0 0 0 +222 0 0 0 +223 0 0 0 +224 0 0 0 +225 0 0 0 +226 0 0 0 +227 0 0 0 +228 0 0 0 +229 0 0 0 +230 0 0 0 +231 0 0 0 +232 0 0 0 +233 0 0 0 +234 0 0 0 +235 0 0 0 +236 0 0 0 +237 0 0 0 +238 0 0 0 +239 0 0 0 +240 0 0 0 +241 0 0 0 +242 0 0 0 +243 0 0 0 +244 0 0 0 +245 0 0 0 +246 0 0 0 +247 0 0 0 +248 0 0 0 +249 0 0 0 +250 0 0 0 +251 0 0 0 +252 0 0 0 +253 0 0 0 +254 396 0 278 +255 1000 1000 1000 diff --git a/colors/bw17.clr b/colors/bw17.clr new file mode 100644 index 0000000..9241a46 --- /dev/null +++ b/colors/bw17.clr @@ -0,0 +1,17 @@ +0 0 0 0 +1 42 42 42 +2 86 86 86 +3 133 133 133 +4 180 180 180 +5 231 231 231 +6 282 282 282 +7 341 341 341 +8 400 400 400 +9 462 462 462 +10 529 529 529 +11 600 600 600 +12 670 670 670 +13 749 749 749 +14 831 831 831 +15 917 917 917 +16 998 998 998 \ No newline at end of file diff --git a/colors/bw256.clr b/colors/bw256.clr new file mode 100644 index 0000000..abd765d --- /dev/null +++ b/colors/bw256.clr @@ -0,0 +1,257 @@ + 0 0 0 0 + 1 3 3 3 + 2 7 7 7 + 3 11 11 11 + 4 15 15 15 + 5 19 19 19 + 6 23 23 23 + 7 27 27 27 + 8 31 31 31 + 9 35 35 35 + 10 39 39 39 + 11 43 43 43 + 12 47 47 47 + 13 50 50 50 + 14 54 54 54 + 15 58 58 58 + 16 62 62 62 + 17 66 66 66 + 18 70 70 70 + 19 74 74 74 + 20 78 78 78 + 21 82 82 82 + 22 86 86 86 + 23 90 90 90 + 24 94 94 94 + 25 98 98 98 + 26 101 101 101 + 27 105 105 105 + 28 109 109 109 + 29 113 113 113 + 30 117 117 117 + 31 121 121 121 + 32 125 125 125 + 33 129 129 129 + 34 133 133 133 + 35 137 137 137 + 36 141 141 141 + 37 145 145 145 + 38 149 149 149 + 39 152 152 152 + 40 156 156 156 + 41 160 160 160 + 42 164 164 164 + 43 168 168 168 + 44 172 172 172 + 45 176 176 176 + 46 180 180 180 + 47 184 184 184 + 48 188 188 188 + 49 192 192 192 + 50 196 196 196 + 51 200 200 200 + 52 203 203 203 + 53 207 207 207 + 54 211 211 211 + 55 215 215 215 + 56 219 219 219 + 57 223 223 223 + 58 227 227 227 + 59 231 231 231 + 60 235 235 235 + 61 239 239 239 + 62 243 243 243 + 63 247 247 247 + 64 250 250 250 + 65 254 254 254 + 66 258 258 258 + 67 262 262 262 + 68 266 266 266 + 69 270 270 270 + 70 274 274 274 + 71 278 278 278 + 72 282 282 282 + 73 286 286 286 + 74 290 290 290 + 75 294 294 294 + 76 298 298 298 + 77 301 301 301 + 78 305 305 305 + 79 309 309 309 + 80 313 313 313 + 81 317 317 317 + 82 321 321 321 + 83 325 325 325 + 84 329 329 329 + 85 333 333 333 + 86 337 337 337 + 87 341 341 341 + 88 345 345 345 + 89 349 349 349 + 90 352 352 352 + 91 356 356 356 + 92 360 360 360 + 93 364 364 364 + 94 368 368 368 + 95 372 372 372 + 96 376 376 376 + 97 380 380 380 + 98 384 384 384 + 99 388 388 388 +100 392 392 392 +101 396 396 396 +102 400 400 400 +103 403 403 403 +104 407 407 407 +105 411 411 411 +106 415 415 415 +107 419 419 419 +108 423 423 423 +109 427 427 427 +110 431 431 431 +111 435 435 435 +112 439 439 439 +113 443 443 443 +114 447 447 447 +115 450 450 450 +116 454 454 454 +117 458 458 458 +118 462 462 462 +119 466 466 466 +120 470 470 470 +121 474 474 474 +122 478 478 478 +123 482 482 482 +124 486 486 486 +125 490 490 490 +126 494 494 494 +127 498 498 498 +128 501 501 501 +129 505 505 505 +130 509 509 509 +131 513 513 513 +132 517 517 517 +133 521 521 521 +134 525 525 525 +135 529 529 529 +136 533 533 533 +137 537 537 537 +138 541 541 541 +139 545 545 545 +140 549 549 549 +141 552 552 552 +142 556 556 556 +143 560 560 560 +144 564 564 564 +145 568 568 568 +146 572 572 572 +147 576 576 576 +148 580 580 580 +149 584 584 584 +150 588 588 588 +151 592 592 592 +152 596 596 596 +153 600 600 600 +154 603 603 603 +155 607 607 607 +156 611 611 611 +157 615 615 615 +158 619 619 619 +159 623 623 623 +160 627 627 627 +161 631 631 631 +162 635 635 635 +163 639 639 639 +164 643 643 643 +165 647 647 647 +166 650 650 650 +167 654 654 654 +168 658 658 658 +169 662 662 662 +170 666 666 666 +171 670 670 670 +172 674 674 674 +173 678 678 678 +174 682 682 682 +175 686 686 686 +176 690 690 690 +177 694 694 694 +178 698 698 698 +179 701 701 701 +180 705 705 705 +181 709 709 709 +182 713 713 713 +183 717 717 717 +184 721 721 721 +185 725 725 725 +186 729 729 729 +187 733 733 733 +188 737 737 737 +189 741 741 741 +190 745 745 745 +191 749 749 749 +192 752 752 752 +193 756 756 756 +194 760 760 760 +195 764 764 764 +196 768 768 768 +197 772 772 772 +198 776 776 776 +199 780 780 780 +200 784 784 784 +201 788 788 788 +202 792 792 792 +203 796 796 796 +204 800 800 800 +205 803 803 803 +206 807 807 807 +207 811 811 811 +208 815 815 815 +209 819 819 819 +210 823 823 823 +211 827 827 827 +212 831 831 831 +213 835 835 835 +214 839 839 839 +215 843 843 843 +216 847 847 847 +217 850 850 850 +218 854 854 854 +219 858 858 858 +220 862 862 862 +221 866 866 866 +222 870 870 870 +223 874 874 874 +224 878 878 878 +225 882 882 882 +226 886 886 886 +227 890 890 890 +228 894 894 894 +229 898 898 898 +230 901 901 901 +231 905 905 905 +232 909 909 909 +233 913 913 913 +234 917 917 917 +235 921 921 921 +236 925 925 925 +237 929 929 929 +238 933 933 933 +239 937 937 937 +240 941 941 941 +241 945 945 945 +242 949 949 949 +243 952 952 952 +244 956 956 956 +245 960 960 960 +246 964 964 964 +247 968 968 968 +248 972 972 972 +249 976 976 976 +250 980 980 980 +251 984 984 984 +252 988 988 988 +253 992 992 992 +254 1000 1000 1000 +255 1000 1000 1000 + \ No newline at end of file diff --git a/colors/bw256inv.clr b/colors/bw256inv.clr new file mode 100644 index 0000000..020b754 --- /dev/null +++ b/colors/bw256inv.clr @@ -0,0 +1,256 @@ + 0 1000 1000 1000 + 1 997 997 997 + 2 993 993 993 + 3 989 989 989 + 4 985 985 985 + 5 981 981 981 + 6 977 977 977 + 7 974 974 974 + 8 970 970 970 + 9 966 966 966 + 10 962 962 962 + 11 958 958 958 + 12 954 954 954 + 13 950 950 950 + 14 946 946 946 + 15 942 942 942 + 16 938 938 938 + 17 934 934 934 + 18 930 930 930 + 19 926 926 926 + 20 923 923 923 + 21 919 919 919 + 22 915 915 915 + 23 911 911 911 + 24 907 907 907 + 25 903 903 903 + 26 899 899 899 + 27 895 895 895 + 28 891 891 891 + 29 887 887 887 + 30 883 883 883 + 31 879 879 879 + 32 876 876 876 + 33 872 872 872 + 34 868 868 868 + 35 864 864 864 + 36 860 860 860 + 37 856 856 856 + 38 852 852 852 + 39 848 848 848 + 40 844 844 844 + 41 840 840 840 + 42 836 836 836 + 43 832 832 832 + 44 828 828 828 + 45 825 825 825 + 46 821 821 821 + 47 817 817 817 + 48 813 813 813 + 49 809 809 809 + 50 805 805 805 + 51 801 801 801 + 52 797 797 797 + 53 793 793 793 + 54 789 789 789 + 55 785 785 785 + 56 781 781 781 + 57 777 777 777 + 58 774 774 774 + 59 770 770 770 + 60 766 766 766 + 61 762 762 762 + 62 758 758 758 + 63 754 754 754 + 64 750 750 750 + 65 746 746 746 + 66 742 742 742 + 67 738 738 738 + 68 734 734 734 + 69 730 730 730 + 70 726 726 726 + 71 723 723 723 + 72 719 719 719 + 73 715 715 715 + 74 711 711 711 + 75 707 707 707 + 76 703 703 703 + 77 699 699 699 + 78 695 695 695 + 79 691 691 691 + 80 687 687 687 + 81 683 683 683 + 82 679 679 679 + 83 676 676 676 + 84 672 672 672 + 85 668 668 668 + 86 664 664 664 + 87 660 660 660 + 88 656 656 656 + 89 652 652 652 + 90 648 648 648 + 91 644 644 644 + 92 640 640 640 + 93 636 636 636 + 94 632 632 632 + 95 628 628 628 + 96 625 625 625 + 97 621 621 621 + 98 617 617 617 + 99 613 613 613 +100 609 609 609 +101 605 605 605 +102 601 601 601 +103 597 597 597 +104 593 593 593 +105 589 589 589 +106 585 585 585 +107 581 581 581 +108 577 577 577 +109 574 574 574 +110 570 570 570 +111 566 566 566 +112 562 562 562 +113 558 558 558 +114 554 554 554 +115 550 550 550 +116 546 546 546 +117 542 542 542 +118 538 538 538 +119 534 534 534 +120 530 530 530 +121 526 526 526 +122 523 523 523 +123 519 519 519 +124 515 515 515 +125 511 511 511 +126 507 507 507 +127 503 503 503 +128 499 499 499 +129 495 495 495 +130 491 491 491 +131 487 487 487 +132 483 483 483 +133 479 479 479 +134 476 476 476 +135 472 472 472 +136 468 468 468 +137 464 464 464 +138 460 460 460 +139 456 456 456 +140 452 452 452 +141 448 448 448 +142 444 444 444 +143 440 440 440 +144 436 436 436 +145 432 432 432 +146 428 428 428 +147 425 425 425 +148 421 421 421 +149 417 417 417 +150 413 413 413 +151 409 409 409 +152 405 405 405 +153 401 401 401 +154 397 397 397 +155 393 393 393 +156 389 389 389 +157 385 385 385 +158 381 381 381 +159 377 377 377 +160 374 374 374 +161 370 370 370 +162 366 366 366 +163 362 362 362 +164 358 358 358 +165 354 354 354 +166 350 350 350 +167 346 346 346 +168 342 342 342 +169 338 338 338 +170 334 334 334 +171 330 330 330 +172 326 326 326 +173 323 323 323 +174 319 319 319 +175 315 315 315 +176 311 311 311 +177 307 307 307 +178 303 303 303 +179 299 299 299 +180 295 295 295 +181 291 291 291 +182 287 287 287 +183 283 283 283 +184 279 279 279 +185 276 276 276 +186 272 272 272 +187 268 268 268 +188 264 264 264 +189 260 260 260 +190 256 256 256 +191 252 252 252 +192 248 248 248 +193 244 244 244 +194 240 240 240 +195 236 236 236 +196 232 232 232 +197 228 228 228 +198 225 225 225 +199 221 221 221 +200 217 217 217 +201 213 213 213 +202 209 209 209 +203 205 205 205 +204 201 201 201 +205 197 197 197 +206 193 193 193 +207 189 189 189 +208 185 185 185 +209 181 181 181 +210 177 177 177 +211 174 174 174 +212 170 170 170 +213 166 166 166 +214 162 162 162 +215 158 158 158 +216 154 154 154 +217 150 150 150 +218 146 146 146 +219 142 142 142 +220 138 138 138 +221 134 134 134 +222 130 130 130 +223 126 126 126 +224 123 123 123 +225 119 119 119 +226 115 115 115 +227 111 111 111 +228 107 107 107 +229 103 103 103 +230 99 99 99 +231 95 95 95 +232 91 91 91 +233 87 87 87 +234 83 83 83 +235 79 79 79 +236 76 76 76 +237 72 72 72 +238 68 68 68 +239 64 64 64 +240 60 60 60 +241 56 56 56 +242 52 52 52 +243 48 48 48 +244 44 44 44 +245 40 40 40 +246 36 36 36 +247 32 32 32 +248 28 28 28 +249 25 25 25 +250 21 21 21 +251 17 17 17 +252 13 13 13 +253 9 9 9 +254 5 5 5 +255 0 0 0 diff --git a/colors/bw5.clr b/colors/bw5.clr new file mode 100644 index 0000000..7e88da4 --- /dev/null +++ b/colors/bw5.clr @@ -0,0 +1,5 @@ +0 0 0 0 +1 180 180 180 +2 400 400 400 +3 670 670 670 +4 1000 1000 1000 diff --git a/colors/bw64.clr b/colors/bw64.clr new file mode 100644 index 0000000..a45048a --- /dev/null +++ b/colors/bw64.clr @@ -0,0 +1,64 @@ + 0 0 0 0 + 1 15 15 15 + 2 31 31 31 + 3 47 47 47 + 4 62 62 62 + 5 78 78 78 + 6 94 94 94 + 7 109 109 109 + 8 125 125 125 + 9 141 141 141 +10 156 156 156 +11 172 172 172 +12 188 188 188 +13 203 203 203 +14 219 219 219 +15 235 235 235 +16 250 250 250 +17 266 266 266 +18 282 282 282 +19 298 298 298 +20 313 313 313 +21 329 329 329 +22 345 345 345 +23 360 360 360 +24 376 376 376 +25 392 392 392 +26 407 407 407 +27 423 423 423 +28 439 439 439 +29 454 454 454 +30 470 470 470 +31 486 486 486 +32 501 501 501 +33 517 517 517 +34 533 533 533 +35 549 549 549 +36 564 564 564 +37 580 580 580 +38 596 596 596 +39 611 611 611 +40 627 627 627 +41 643 643 643 +42 658 658 658 +43 674 674 674 +44 690 690 690 +45 705 705 705 +46 721 721 721 +47 737 737 737 +48 752 752 752 +49 768 768 768 +50 784 784 784 +51 800 800 800 +52 815 815 815 +53 831 831 831 +54 847 847 847 +55 862 862 862 +56 878 878 878 +57 894 894 894 +58 909 909 909 +59 925 925 925 +60 941 941 941 +61 956 956 956 +62 972 972 972 +63 1000 1000 1000 diff --git a/colors/default.clr b/colors/default.clr new file mode 100644 index 0000000..53ae720 --- /dev/null +++ b/colors/default.clr @@ -0,0 +1,256 @@ + 0 0 0 0 + 1 1000 0 0 + 2 0 1000 0 + 3 650 650 1000 + 4 1000 1000 0 + 5 1000 0 1000 + 6 0 1000 1000 + 7 650 650 650 + 8 1000 650 0 + 9 650 317 0 + 10 0 650 0 + 11 0 0 1000 + 12 650 650 0 + 13 650 0 650 + 14 0 650 650 + 15 857 857 857 + 16 587 587 587 + 17 0 380 380 + 18 0 539 539 + 19 0 682 682 + 20 0 841 841 + 21 0 1000 1000 + 22 95 809 984 + 23 190 666 984 + 24 285 571 984 + 25 380 507 984 + 26 492 492 1000 + 27 365 0 365 + 28 523 0 523 + 29 682 0 682 + 30 841 0 841 + 31 1000 0 1000 + 32 984 95 904 + 33 984 190 825 + 34 984 285 777 + 35 984 380 746 + 36 1000 492 746 + 37 0 0 190 + 38 0 0 380 + 39 0 0 587 + 40 0 0 793 + 41 0 0 1000 + 42 142 63 920 + 43 269 126 857 + 44 365 206 777 + 45 444 269 714 + 46 333 333 634 + 47 190 190 0 + 48 380 380 0 + 49 587 587 0 + 50 793 793 0 + 51 1000 1000 0 + 52 920 920 63 + 53 857 857 126 + 54 777 777 206 + 55 714 714 269 + 56 634 634 333 + 57 0 190 0 + 58 0 380 0 + 59 0 587 0 + 60 0 793 0 + 61 0 1000 0 + 62 63 904 63 + 63 142 825 142 + 64 238 746 238 + 65 301 666 301 + 66 396 587 396 + 67 190 0 0 + 68 380 0 0 + 69 587 0 0 + 70 793 0 0 + 71 1000 0 0 + 72 904 63 63 + 73 825 142 142 + 74 746 238 238 + 75 666 301 301 + 76 587 396 396 + 77 238 746 746 + 78 238 634 746 + 79 238 523 746 + 80 238 412 746 + 81 238 285 746 + 82 285 238 746 + 83 412 238 746 + 84 523 238 746 + 85 634 238 746 + 86 746 238 746 + 87 746 238 634 + 88 746 238 539 + 89 746 238 444 + 90 746 238 349 + 91 746 238 253 + 92 746 333 238 + 93 746 444 238 + 94 746 539 238 + 95 746 634 238 + 96 746 746 238 + 97 634 746 238 + 98 412 746 238 + 99 238 746 285 +100 238 746 507 +101 238 746 746 +102 380 158 0 +103 587 238 0 +104 793 317 0 +105 1000 412 0 +106 1000 523 190 +107 79 79 79 +108 190 190 190 +109 285 285 285 +110 396 396 396 +111 492 492 492 +112 587 587 587 +113 682 682 682 +114 777 777 777 +115 888 888 888 +116 984 984 984 +117 0 492 1000 +118 0 1000 1000 +119 746 492 0 +120 0 841 15 +121 650 0 650 +122 698 396 0 +123 841 587 285 +124 1000 650 650 +125 1000 793 587 +126 0 793 1000 +127 0 1000 793 +128 380 380 380 +129 1000 238 238 +130 1000 650 317 +131 317 317 1000 +132 0 317 1000 +133 1000 317 0 +134 746 238 0 +135 746 79 79 +136 0 0 0 +137 857 1000 857 +138 1000 1000 0 +139 1000 0 1000 +140 650 650 650 +141 1000 492 0 +142 1000 0 0 +143 492 1000 0 +144 0 492 0 +145 317 698 0 +146 0 0 1000 +147 0 492 1000 +148 0 1000 1000 +149 746 492 0 +150 0 841 0 +151 650 0 650 +152 698 396 0 +153 841 587 285 +154 1000 650 650 +155 1000 793 587 +156 0 793 1000 +157 0 1000 793 +158 380 380 380 +159 1000 238 238 +160 1000 650 317 +161 317 317 1000 +162 0 317 1000 +163 1000 317 0 +164 746 238 15 +165 746 79 79 +166 0 0 15 +167 857 920 1000 +168 1000 1000 0 +169 1000 0 1000 +170 650 650 650 +171 1000 492 0 +172 1000 0 0 +173 492 1000 0 +174 0 492 0 +175 317 698 0 +176 0 0 1000 +177 0 492 1000 +178 0 1000 1000 +179 746 492 0 +180 0 841 0 +181 650 0 650 +182 698 396 0 +183 841 587 285 +184 1000 650 650 +185 1000 793 587 +186 0 793 1000 +187 0 1000 793 +188 380 380 380 +189 1000 238 238 +190 1000 650 317 +191 317 317 1000 +192 0 317 1000 +193 1000 317 0 +194 746 238 15 +195 746 79 79 +196 0 0 0 +197 1000 857 857 +198 1000 1000 0 +199 1000 0 1000 +200 650 650 650 +201 1000 492 0 +202 1000 0 0 +203 492 1000 0 +204 0 492 0 +205 317 698 0 +206 0 0 1000 +207 0 492 1000 +208 0 1000 1000 +209 746 492 0 +210 0 841 15 +211 650 0 650 +212 698 396 0 +213 841 587 285 +214 1000 650 650 +215 1000 793 587 +216 0 793 1000 +217 0 1000 793 +218 380 380 380 +219 1000 238 238 +220 1000 650 317 +221 317 317 1000 +222 746 238 0 +223 746 79 79 +224 0 0 0 +225 1000 857 1000 +226 1000 1000 0 +227 1000 0 1000 +228 650 650 650 +229 1000 492 0 +230 1000 0 0 +231 492 1000 0 +232 0 492 0 +233 317 698 0 +234 0 0 1000 +235 0 492 1000 +236 0 1000 1000 +237 746 492 0 +238 0 841 0 +239 650 0 650 +240 698 396 0 +241 841 587 285 +242 1000 650 650 +243 1000 793 587 +244 0 793 1000 +245 0 1000 793 +246 380 380 380 +247 1000 238 238 +248 1000 650 317 +249 317 317 1000 +250 0 317 1000 +251 1000 317 0 +252 746 238 0 +253 746 79 79 +254 0 0 0 +255 1000 1000 1000 diff --git a/colors/digdoq.clr b/colors/digdoq.clr new file mode 100644 index 0000000..493d067 --- /dev/null +++ b/colors/digdoq.clr @@ -0,0 +1,256 @@ + 0 0 0 0 + 1 850 0 0 + 2 7 7 7 + 3 11 11 11 + 4 15 15 15 + 5 19 19 19 + 6 23 23 23 + 7 27 27 27 + 8 31 31 31 + 9 35 35 35 + 10 39 39 39 + 11 43 43 43 + 12 47 47 47 + 13 50 50 50 + 14 54 54 54 + 15 58 58 58 + 16 62 62 62 + 17 66 66 66 + 18 70 70 70 + 19 74 74 74 + 20 78 78 78 + 21 82 82 82 + 22 86 86 86 + 23 90 90 90 + 24 94 94 94 + 25 98 98 98 + 26 101 101 101 + 27 105 105 105 + 28 109 109 109 + 29 113 113 113 + 30 117 117 117 + 31 121 121 121 + 32 125 125 125 + 33 129 129 129 + 34 133 133 133 + 35 137 137 137 + 36 141 141 141 + 37 145 145 145 + 38 149 149 149 + 39 152 152 152 + 40 156 156 156 + 41 160 160 160 + 42 164 164 164 + 43 168 168 168 + 44 172 172 172 + 45 176 176 176 + 46 180 180 180 + 47 184 184 184 + 48 188 188 188 + 49 192 192 192 + 50 196 196 196 + 51 200 200 200 + 52 203 203 203 + 53 207 207 207 + 54 211 211 211 + 55 215 215 215 + 56 219 219 219 + 57 223 223 223 + 58 227 227 227 + 59 231 231 231 + 60 235 235 235 + 61 239 239 239 + 62 243 243 243 + 63 247 247 247 + 64 250 250 250 + 65 254 254 254 + 66 258 258 258 + 67 262 262 262 + 68 266 266 266 + 69 270 270 270 + 70 274 274 274 + 71 278 278 278 + 72 282 282 282 + 73 286 286 286 + 74 290 290 290 + 75 294 294 294 + 76 298 298 298 + 77 301 301 301 + 78 305 305 305 + 79 309 309 309 + 80 313 313 313 + 81 317 317 317 + 82 321 321 321 + 83 325 325 325 + 84 329 329 329 + 85 333 333 333 + 86 337 337 337 + 87 341 341 341 + 88 345 345 345 + 89 349 349 349 + 90 352 352 352 + 91 356 356 356 + 92 360 360 360 + 93 364 364 364 + 94 368 368 368 + 95 372 372 372 + 96 376 376 376 + 97 380 380 380 + 98 384 384 384 + 99 388 388 388 +100 392 392 392 +101 396 396 396 +102 400 400 400 +103 403 403 403 +104 407 407 407 +105 411 411 411 +106 415 415 415 +107 419 419 419 +108 423 423 423 +109 427 427 427 +110 431 431 431 +111 435 435 435 +112 439 439 439 +113 443 443 443 +114 447 447 447 +115 450 450 450 +116 454 454 454 +117 458 458 458 +118 462 462 462 +119 466 466 466 +120 470 470 470 +121 474 474 474 +122 478 478 478 +123 482 482 482 +124 486 486 486 +125 490 490 490 +126 494 494 494 +127 498 498 498 +128 501 501 501 +129 505 505 505 +130 509 509 509 +131 513 513 513 +132 517 517 517 +133 521 521 521 +134 525 525 525 +135 529 529 529 +136 533 533 533 +137 537 537 537 +138 541 541 541 +139 545 545 545 +140 549 549 549 +141 552 552 552 +142 556 556 556 +143 560 560 560 +144 564 564 564 +145 568 568 568 +146 572 572 572 +147 576 576 576 +148 580 580 580 +149 584 584 584 +150 588 588 588 +151 592 592 592 +152 596 596 596 +153 600 600 600 +154 603 603 603 +155 607 607 607 +156 611 611 611 +157 615 615 615 +158 619 619 619 +159 623 623 623 +160 627 627 627 +161 631 631 631 +162 635 635 635 +163 639 639 639 +164 643 643 643 +165 647 647 647 +166 650 650 650 +167 654 654 654 +168 658 658 658 +169 662 662 662 +170 666 666 666 +171 670 670 670 +172 674 674 674 +173 678 678 678 +174 682 682 682 +175 686 686 686 +176 690 690 690 +177 694 694 694 +178 698 698 698 +179 701 701 701 +180 705 705 705 +181 709 709 709 +182 713 713 713 +183 717 717 717 +184 721 721 721 +185 725 725 725 +186 729 729 729 +187 733 733 733 +188 737 737 737 +189 741 741 741 +190 745 745 745 +191 749 749 749 +192 752 752 752 +193 756 756 756 +194 760 760 760 +195 764 764 764 +196 768 768 768 +197 772 772 772 +198 776 776 776 +199 780 780 780 +200 784 784 784 +201 788 788 788 +202 792 792 792 +203 796 796 796 +204 800 800 800 +205 803 803 803 +206 807 807 807 +207 811 811 811 +208 815 815 815 +209 819 819 819 +210 823 823 823 +211 827 827 827 +212 831 831 831 +213 835 835 835 +214 839 839 839 +215 843 843 843 +216 847 847 847 +217 850 850 850 +218 854 854 854 +219 858 858 858 +220 862 862 862 +221 866 866 866 +222 870 870 870 +223 874 874 874 +224 878 878 878 +225 882 882 882 +226 886 886 886 +227 890 890 890 +228 894 894 894 +229 898 898 898 +230 901 901 901 +231 905 905 905 +232 909 909 909 +233 913 913 913 +234 917 917 917 +235 921 921 921 +236 925 925 925 +237 929 929 929 +238 933 933 933 +239 937 937 937 +240 941 941 941 +241 945 945 945 +242 949 949 949 +243 952 952 952 +244 956 956 956 +245 960 960 960 +246 964 964 964 +247 968 968 968 +248 972 972 972 +249 976 976 976 +250 980 980 980 +251 984 984 984 +252 988 988 988 +253 992 992 992 +254 1000 1000 1000 +255 1000 1000 1000 diff --git a/colors/drgbw.clr b/colors/drgbw.clr new file mode 100644 index 0000000..e87a574 --- /dev/null +++ b/colors/drgbw.clr @@ -0,0 +1,256 @@ + 0 0 0 0 + 1 1000 1000 1000 + 2 380 380 380 + 3 439 439 439 + 4 349 349 349 + 5 894 894 894 + 6 474 474 474 + 7 411 411 411 + 8 862 862 862 + 9 764 764 764 + 10 811 811 811 + 11 781 781 781 + 12 678 678 678 + 13 0 0 0 + 14 0 0 0 + 15 0 0 0 + 16 0 0 0 + 17 0 0 0 + 18 0 0 0 + 19 0 0 0 + 20 0 0 0 + 21 0 0 0 + 22 0 0 0 + 23 0 0 0 + 24 0 0 0 + 25 0 0 0 + 26 0 0 0 + 27 0 0 0 + 28 0 0 0 + 29 0 0 0 + 30 0 0 0 + 31 0 0 0 + 32 0 0 0 + 33 0 0 0 + 34 0 0 0 + 35 0 0 0 + 36 0 0 0 + 37 0 0 0 + 38 0 0 0 + 39 0 0 0 + 40 0 0 0 + 41 0 0 0 + 42 0 0 0 + 43 0 0 0 + 44 0 0 0 + 45 0 0 0 + 46 0 0 0 + 47 0 0 0 + 48 0 0 0 + 49 0 0 0 + 50 0 0 0 + 51 0 0 0 + 52 0 0 0 + 53 0 0 0 + 54 0 0 0 + 55 0 0 0 + 56 0 0 0 + 57 0 0 0 + 58 0 0 0 + 59 0 0 0 + 60 0 0 0 + 61 0 0 0 + 62 0 0 0 + 63 0 0 0 + 64 0 0 0 + 65 0 0 0 + 66 0 0 0 + 67 0 0 0 + 68 0 0 0 + 69 0 0 0 + 70 0 0 0 + 71 0 0 0 + 72 0 0 0 + 73 0 0 0 + 74 0 0 0 + 75 0 0 0 + 76 0 0 0 + 77 0 0 0 + 78 0 0 0 + 79 0 0 0 + 80 0 0 0 + 81 0 0 0 + 82 0 0 0 + 83 0 0 0 + 84 0 0 0 + 85 0 0 0 + 86 0 0 0 + 87 0 0 0 + 88 0 0 0 + 89 0 0 0 + 90 0 0 0 + 91 0 0 0 + 92 0 0 0 + 93 0 0 0 + 94 0 0 0 + 95 0 0 0 + 96 0 0 0 + 97 0 0 0 + 98 0 0 0 + 99 0 0 0 +100 0 0 0 +101 0 0 0 +102 0 0 0 +103 0 0 0 +104 0 0 0 +105 0 0 0 +106 0 0 0 +107 0 0 0 +108 0 0 0 +109 0 0 0 +110 0 0 0 +111 0 0 0 +112 0 0 0 +113 0 0 0 +114 0 0 0 +115 0 0 0 +116 0 0 0 +117 0 0 0 +118 0 0 0 +119 0 0 0 +120 0 0 0 +121 0 0 0 +122 0 0 0 +123 0 0 0 +124 0 0 0 +125 0 0 0 +126 0 0 0 +127 0 0 0 +128 0 0 0 +129 0 0 0 +130 0 0 0 +131 0 0 0 +132 0 0 0 +133 0 0 0 +134 0 0 0 +135 0 0 0 +136 0 0 0 +137 0 0 0 +138 0 0 0 +139 0 0 0 +140 0 0 0 +141 0 0 0 +142 0 0 0 +143 0 0 0 +144 0 0 0 +145 0 0 0 +146 0 0 0 +147 0 0 0 +148 0 0 0 +149 0 0 0 +150 0 0 0 +151 0 0 0 +152 0 0 0 +153 0 0 0 +154 0 0 0 +155 0 0 0 +156 0 0 0 +157 0 0 0 +158 0 0 0 +159 0 0 0 +160 0 0 0 +161 0 0 0 +162 0 0 0 +163 0 0 0 +164 0 0 0 +165 0 0 0 +166 0 0 0 +167 0 0 0 +168 0 0 0 +169 0 0 0 +170 0 0 0 +171 0 0 0 +172 0 0 0 +173 0 0 0 +174 0 0 0 +175 0 0 0 +176 0 0 0 +177 0 0 0 +178 0 0 0 +179 0 0 0 +180 0 0 0 +181 0 0 0 +182 0 0 0 +183 0 0 0 +184 0 0 0 +185 0 0 0 +186 0 0 0 +187 0 0 0 +188 0 0 0 +189 0 0 0 +190 0 0 0 +191 0 0 0 +192 0 0 0 +193 0 0 0 +194 0 0 0 +195 0 0 0 +196 0 0 0 +197 0 0 0 +198 0 0 0 +199 0 0 0 +200 0 0 0 +201 0 0 0 +202 0 0 0 +203 0 0 0 +204 0 0 0 +205 0 0 0 +206 0 0 0 +207 0 0 0 +208 0 0 0 +209 0 0 0 +210 0 0 0 +211 0 0 0 +212 0 0 0 +213 0 0 0 +214 0 0 0 +215 0 0 0 +216 0 0 0 +217 0 0 0 +218 0 0 0 +219 0 0 0 +220 0 0 0 +221 0 0 0 +222 0 0 0 +223 0 0 0 +224 0 0 0 +225 0 0 0 +226 0 0 0 +227 0 0 0 +228 0 0 0 +229 0 0 0 +230 0 0 0 +231 0 0 0 +232 0 0 0 +233 0 0 0 +234 0 0 0 +235 0 0 0 +236 0 0 0 +237 0 0 0 +238 0 0 0 +239 0 0 0 +240 0 0 0 +241 0 0 0 +242 0 0 0 +243 0 0 0 +244 0 0 0 +245 0 0 0 +246 0 0 0 +247 0 0 0 +248 0 0 0 +249 0 0 0 +250 0 0 0 +251 0 0 0 +252 0 0 0 +253 0 0 0 +254 0 0 0 +255 0 0 0 diff --git a/colors/drgclr.clr b/colors/drgclr.clr new file mode 100644 index 0000000..314a8f5 --- /dev/null +++ b/colors/drgclr.clr @@ -0,0 +1,256 @@ + 0 0 0 0 + 1 996 996 996 + 2 0 589 640 + 3 792 0 89 + 4 511 257 144 + 5 785 914 613 + 6 535 199 500 + 7 996 914 0 + 8 652 882 882 + 9 996 718 718 + 10 851 699 835 + 11 816 816 816 + 12 808 640 554 + 13 0 0 0 + 14 0 0 0 + 15 0 0 0 + 16 0 0 0 + 17 0 0 0 + 18 0 0 0 + 19 0 0 0 + 20 0 0 0 + 21 0 0 0 + 22 0 0 0 + 23 0 0 0 + 24 0 0 0 + 25 0 0 0 + 26 0 0 0 + 27 0 0 0 + 28 0 0 0 + 29 0 0 0 + 30 0 0 0 + 31 0 0 0 + 32 0 0 0 + 33 0 0 0 + 34 0 0 0 + 35 0 0 0 + 36 0 0 0 + 37 0 0 0 + 38 0 0 0 + 39 0 0 0 + 40 0 0 0 + 41 0 0 0 + 42 0 0 0 + 43 0 0 0 + 44 0 0 0 + 45 0 0 0 + 46 0 0 0 + 47 0 0 0 + 48 0 0 0 + 49 0 0 0 + 50 0 0 0 + 51 0 0 0 + 52 0 0 0 + 53 0 0 0 + 54 0 0 0 + 55 0 0 0 + 56 0 0 0 + 57 0 0 0 + 58 0 0 0 + 59 0 0 0 + 60 0 0 0 + 61 0 0 0 + 62 0 0 0 + 63 0 0 0 + 64 0 0 0 + 65 0 0 0 + 66 0 0 0 + 67 0 0 0 + 68 0 0 0 + 69 0 0 0 + 70 0 0 0 + 71 0 0 0 + 72 0 0 0 + 73 0 0 0 + 74 0 0 0 + 75 0 0 0 + 76 0 0 0 + 77 0 0 0 + 78 0 0 0 + 79 0 0 0 + 80 0 0 0 + 81 0 0 0 + 82 0 0 0 + 83 0 0 0 + 84 0 0 0 + 85 0 0 0 + 86 0 0 0 + 87 0 0 0 + 88 0 0 0 + 89 0 0 0 + 90 0 0 0 + 91 0 0 0 + 92 0 0 0 + 93 0 0 0 + 94 0 0 0 + 95 0 0 0 + 96 0 0 0 + 97 0 0 0 + 98 0 0 0 + 99 0 0 0 + 100 0 0 0 + 101 0 0 0 + 102 0 0 0 + 103 0 0 0 + 104 0 0 0 + 105 0 0 0 + 106 0 0 0 + 107 0 0 0 + 108 0 0 0 + 109 0 0 0 + 110 0 0 0 + 111 0 0 0 + 112 0 0 0 + 113 0 0 0 + 114 0 0 0 + 115 0 0 0 + 116 0 0 0 + 117 0 0 0 + 118 0 0 0 + 119 0 0 0 + 120 0 0 0 + 121 0 0 0 + 122 0 0 0 + 123 0 0 0 + 124 0 0 0 + 125 0 0 0 + 126 0 0 0 + 127 0 0 0 + 128 0 0 0 + 129 0 0 0 + 130 0 0 0 + 131 0 0 0 + 132 0 0 0 + 133 0 0 0 + 134 0 0 0 + 135 0 0 0 + 136 0 0 0 + 137 0 0 0 + 138 0 0 0 + 139 0 0 0 + 140 0 0 0 + 141 0 0 0 + 142 0 0 0 + 143 0 0 0 + 144 0 0 0 + 145 0 0 0 + 146 0 0 0 + 147 0 0 0 + 148 0 0 0 + 149 0 0 0 + 150 0 0 0 + 151 0 0 0 + 152 0 0 0 + 153 0 0 0 + 154 0 0 0 + 155 0 0 0 + 156 0 0 0 + 157 0 0 0 + 158 0 0 0 + 159 0 0 0 + 160 0 0 0 + 161 0 0 0 + 162 0 0 0 + 163 0 0 0 + 164 0 0 0 + 165 0 0 0 + 166 0 0 0 + 167 0 0 0 + 168 0 0 0 + 169 0 0 0 + 170 0 0 0 + 171 0 0 0 + 172 0 0 0 + 173 0 0 0 + 174 0 0 0 + 175 0 0 0 + 176 0 0 0 + 177 0 0 0 + 178 0 0 0 + 179 0 0 0 + 180 0 0 0 + 181 0 0 0 + 182 0 0 0 + 183 0 0 0 + 184 0 0 0 + 185 0 0 0 + 186 0 0 0 + 187 0 0 0 + 188 0 0 0 + 189 0 0 0 + 190 0 0 0 + 191 0 0 0 + 192 0 0 0 + 193 0 0 0 + 194 0 0 0 + 195 0 0 0 + 196 0 0 0 + 197 0 0 0 + 198 0 0 0 + 199 0 0 0 + 200 0 0 0 + 201 0 0 0 + 202 0 0 0 + 203 0 0 0 + 204 0 0 0 + 205 0 0 0 + 206 0 0 0 + 207 0 0 0 + 208 0 0 0 + 209 0 0 0 + 210 0 0 0 + 211 0 0 0 + 212 0 0 0 + 213 0 0 0 + 214 0 0 0 + 215 0 0 0 + 216 0 0 0 + 217 0 0 0 + 218 0 0 0 + 219 0 0 0 + 220 0 0 0 + 221 0 0 0 + 222 0 0 0 + 223 0 0 0 + 224 0 0 0 + 225 0 0 0 + 226 0 0 0 + 227 0 0 0 + 228 0 0 0 + 229 0 0 0 + 230 0 0 0 + 231 0 0 0 + 232 0 0 0 + 233 0 0 0 + 234 0 0 0 + 235 0 0 0 + 236 0 0 0 + 237 0 0 0 + 238 0 0 0 + 239 0 0 0 + 240 0 0 0 + 241 0 0 0 + 242 0 0 0 + 243 0 0 0 + 244 0 0 0 + 245 0 0 0 + 246 0 0 0 + 247 0 0 0 + 248 0 0 0 + 249 0 0 0 + 250 0 0 0 + 251 0 0 0 + 252 0 0 0 + 253 0 0 0 + 254 0 0 0 + 255 0 0 0 diff --git a/colors/ega.clr b/colors/ega.clr new file mode 100644 index 0000000..ced8633 --- /dev/null +++ b/colors/ega.clr @@ -0,0 +1,17 @@ + 0 0 0 0 BLACK + 1 1000 0 0 RED + 2 0 1000 0 GREEN + 3 666 666 1000 BLUE + 4 1000 1000 0 YELLOW + 5 1000 0 1000 VIOLET + 6 0 1000 1000 CYAN + 7 666 666 666 GRAY + 8 1000 666 0 ORANGE + 9 666 333 0 BROWN + 10 0 666 0 DK.GREEN + 11 0 0 1000 DK.BLUE + 12 666 666 0 DK.YELLOW + 13 666 0 666 DK.VIOLET + 14 0 666 666 DK.CYAN + 15 1000 1000 1000 WHITE + \ No newline at end of file diff --git a/colors/fort.clr b/colors/fort.clr new file mode 100644 index 0000000..be6ec09 --- /dev/null +++ b/colors/fort.clr @@ -0,0 +1,12 @@ + 0 0 0 0 + 1 1000 0 0 + 2 666 666 666 + 3 333 701 0 + 4 0 800 1000 + 5 498 1000 0 + 6 0 498 1000 + 7 392 392 392 + 8 0 0 0 + 9 1000 1000 1000 +255 1000 1000 1000 + \ No newline at end of file diff --git a/colors/lesson.clr b/colors/lesson.clr new file mode 100644 index 0000000..d0f24b8 --- /dev/null +++ b/colors/lesson.clr @@ -0,0 +1,17 @@ + 0 0 0 0 + 1 1000 0 0 + 2 1000 1000 0 + 3 1000 666 666 + 4 0 666 0 + 5 666 666 0 + 6 0 666 666 + 7 666 0 666 + 8 666 666 666 + 9 1000 1000 0 + 10 333 666 1000 + 11 0 666 1000 + 12 333 666 0 + 13 333 333 333 + 14 666 666 666 + 15 1000 1000 1000 + \ No newline at end of file diff --git a/colors/luse.clr b/colors/luse.clr new file mode 100644 index 0000000..ab29772 --- /dev/null +++ b/colors/luse.clr @@ -0,0 +1,11 @@ +0 0 0 0 +1 0 1000 0 +2 1000 1000 0 +3 500 500 0 +4 1000 0 1000 +5 500 0 500 +6 0 1000 1000 +7 0 500 500 +8 1000 1000 1000 +9 500 500 500 + \ No newline at end of file diff --git a/colors/names.clr b/colors/names.clr new file mode 100644 index 0000000..741b1dc --- /dev/null +++ b/colors/names.clr @@ -0,0 +1,25 @@ + -1 0 0 0 BLACK + -1 1000 1000 1000 WHITE + -1 0 850 0 GREEN + -1 850 0 0 RED + -1 0 0 850 BLUE + -1 1000 1000 0 YELLOW + -1 1000 0 1000 MAGENTA + -1 0 1000 1000 CYAN + -1 0 1000 0 LT.GREEN + -1 0 498 0 DK.GREEN + -1 0 0 500 DK.BLUE + -1 0 0 1000 LT.BLUE + -1 500 0 0 DK.RED + -1 1000 0 0 LT.RED + -1 666 666 666 GRAY + -1 392 392 392 DK.GRAY + -1 1000 498 0 ORANGE + -1 333 701 0 OLIVE + -1 749 498 0 TAN + -1 666 0 666 PURPLE + -1 701 400 0 BROWN + -1 850 600 298 PEACH + -1 1000 666 666 PINK + -1 1000 800 600 SAND + diff --git a/colors/pal100.clr b/colors/pal100.clr new file mode 100644 index 0000000..7aa71d3 --- /dev/null +++ b/colors/pal100.clr @@ -0,0 +1,256 @@ + 0 600 600 600 + 1 0 396 396 + 2 0 549 549 + 3 0 698 698 + 4 0 847 847 + 5 0 1000 1000 + 6 98 819 996 + 7 196 678 996 + 8 298 576 996 + 9 396 517 996 + 10 498 498 1000 + 11 376 0 376 + 12 533 0 533 + 13 686 0 686 + 14 843 0 843 + 15 1000 0 1000 + 16 996 98 909 + 17 996 196 839 + 18 996 298 788 + 19 996 396 756 + 20 1000 498 749 + 21 0 0 196 + 22 0 0 396 + 23 0 0 596 + 24 0 0 796 + 25 0 0 1000 + 26 152 66 929 + 27 282 137 858 + 28 380 207 788 + 29 454 278 717 + 30 349 349 647 + 31 196 196 0 + 32 396 396 0 + 33 596 596 0 + 34 796 796 0 + 35 1000 1000 0 + 36 929 929 66 + 37 858 858 137 + 38 788 788 207 + 39 717 717 278 + 40 647 647 349 + 41 0 196 0 + 42 0 396 0 + 43 0 596 0 + 44 0 796 0 + 45 0 1000 0 + 46 78 917 78 + 47 156 839 156 + 48 239 756 239 + 49 317 678 317 + 50 400 596 400 + 51 196 0 0 + 52 396 0 0 + 53 596 0 0 + 54 796 0 0 + 55 1000 0 0 + 56 917 78 78 + 57 839 156 156 + 58 756 239 239 + 59 678 317 317 + 60 596 400 400 + 61 247 749 749 + 62 247 635 749 + 63 247 525 749 + 64 247 415 749 + 65 247 301 749 + 66 301 247 749 + 67 415 247 749 + 68 525 247 749 + 69 635 247 749 + 70 749 247 749 + 71 749 247 647 + 72 749 247 549 + 73 749 247 450 + 74 749 247 352 + 75 749 247 254 + 76 749 349 247 + 77 749 447 247 + 78 749 549 247 + 79 749 647 247 + 80 749 749 247 + 81 647 749 247 + 82 423 749 247 + 83 247 749 298 + 84 247 749 521 + 85 247 749 749 + 86 396 164 0 + 87 596 247 0 + 88 796 329 0 + 89 1000 415 0 + 90 1000 529 196 + 91 94 94 94 + 92 200 200 200 + 93 294 294 294 + 94 400 400 400 + 95 494 494 494 + 96 592 592 592 + 97 694 694 694 + 98 792 792 792 + 99 894 894 894 +100 992 992 992 +101 0 498 1000 +102 0 1000 1000 +103 749 498 0 +104 0 850 27 +105 666 0 666 +106 701 400 0 +107 850 600 298 +108 1000 666 666 +109 1000 800 600 +110 0 800 1000 +111 0 1000 800 +112 392 392 392 +113 1000 250 250 +114 1000 666 333 +115 333 333 1000 +116 0 333 1000 +117 1000 333 0 +118 749 250 0 +119 749 94 94 +120 0 0 0 +121 1000 1000 1000 +122 1000 1000 0 +123 1000 0 1000 +124 666 666 666 +125 1000 498 0 +126 1000 0 0 +127 498 1000 0 +128 0 498 0 +129 333 701 0 +130 0 0 1000 +131 0 498 1000 +132 0 1000 1000 +133 749 498 0 +134 0 850 0 +135 666 0 666 +136 701 400 0 +137 850 600 298 +138 1000 666 666 +139 1000 800 600 +140 0 800 1000 +141 0 1000 800 +142 392 392 392 +143 1000 250 250 +144 1000 666 333 +145 333 333 1000 +146 0 333 1000 +147 1000 333 0 +148 749 250 27 +149 749 94 94 +150 0 0 27 +151 1000 1000 1000 +152 1000 1000 0 +153 1000 0 1000 +154 666 666 666 +155 1000 498 0 +156 1000 0 11 +157 498 1000 0 +158 0 498 0 +159 333 701 0 +160 0 0 1000 +161 0 498 1000 +162 0 1000 1000 +163 749 498 0 +164 0 850 0 +165 666 0 666 +166 701 400 0 +167 850 600 298 +168 1000 666 666 +169 1000 800 600 +170 0 800 1000 +171 0 1000 800 +172 392 392 392 +173 1000 250 250 +174 1000 666 333 +175 333 333 1000 +176 0 333 1000 +177 1000 333 0 +178 749 250 27 +179 749 94 94 +180 0 0 0 +181 1000 1000 1000 +182 1000 1000 0 +183 1000 0 1000 +184 666 666 666 +185 1000 498 0 +186 1000 0 0 +187 498 1000 0 +188 0 498 0 +189 333 701 0 +190 0 0 1000 +191 0 498 1000 +192 0 1000 1000 +193 749 498 0 +194 0 850 27 +195 666 0 666 +196 701 400 0 +197 850 600 298 +198 1000 666 666 +199 1000 800 600 +200 0 800 1000 +201 0 1000 800 +202 392 392 392 +203 1000 250 250 +204 1000 666 333 +205 333 333 1000 +206 749 250 0 +207 749 94 94 +208 0 0 11 +209 1000 1000 1000 +210 1000 1000 0 +211 1000 0 1000 +212 666 666 666 +213 1000 498 0 +214 1000 0 0 +215 498 1000 0 +216 0 498 0 +217 333 701 0 +218 0 0 1000 +219 0 498 1000 +220 0 1000 1000 +221 749 498 0 +222 0 850 0 +223 666 0 666 +224 701 400 0 +225 850 600 298 +226 1000 666 666 +227 1000 800 600 +228 0 800 1000 +229 0 1000 800 +230 392 392 392 +231 1000 250 250 +232 1000 666 333 +233 333 333 1000 +234 0 333 1000 +235 1000 333 0 +236 749 250 0 +237 749 94 94 +238 0 0 0 +239 1000 1000 1000 +240 1000 1000 0 +241 1000 0 1000 +242 666 666 666 +243 1000 498 0 +244 1000 27 0 +245 498 1000 0 +246 0 498 0 +247 333 701 0 +248 0 0 1000 +249 0 498 1000 +250 0 1000 1000 +251 749 498 0 +252 0 850 0 +253 666 0 666 +254 701 400 0 +255 0 0 0 diff --git a/colors/pal24.clr b/colors/pal24.clr new file mode 100644 index 0000000..580d5fa --- /dev/null +++ b/colors/pal24.clr @@ -0,0 +1,26 @@ + 0 1000 1000 1000 white + 1 0 1000 1000 cyan + 2 1000 0 1000 magenta + 3 1000 1000 0 yellow + 4 0 0 0 black + 5 500 1000 1000 med. cyan + 6 1000 500 1000 med. magenta + 7 1000 1000 500 med. yellow + 8 500 500 500 grey + 9 750 1000 1000 lt. cyan + 10 1000 750 1000 lt. magenta + 11 1000 1000 750 lt. yellow + 12 750 750 750 lt. grey + 13 240 240 240 dark grey + 14 240 1000 1000 dark cyan + 15 1000 1000 1000 white + 16 1000 0 0 red + 17 0 1000 0 green + 18 0 0 1000 blue + 19 1000 500 500 med. red + 20 500 1000 500 med. green + 21 500 500 1000 med. blue + 22 1000 750 750 lt. red + 23 750 1000 750 lt. green + 24 750 750 1000 lt. blue + \ No newline at end of file diff --git a/colors/pal255.clr b/colors/pal255.clr new file mode 100644 index 0000000..6b1e29d --- /dev/null +++ b/colors/pal255.clr @@ -0,0 +1,256 @@ + 0 0 0 0 + 1 62 62 62 + 2 129 129 129 + 3 196 196 196 + 4 262 262 262 + 5 329 329 329 + 6 396 396 396 + 7 462 462 462 + 8 529 529 529 + 9 596 596 596 + 10 662 662 662 + 11 729 729 729 + 12 796 796 796 + 13 862 862 862 + 14 929 929 929 + 15 996 996 996 + 16 0 0 0 + 17 62 0 0 + 18 129 0 0 + 19 196 0 0 + 20 262 0 0 + 21 329 0 0 + 22 396 0 0 + 23 462 0 0 + 24 529 0 0 + 25 596 0 0 + 26 662 0 0 + 27 729 0 0 + 28 796 0 0 + 29 862 0 0 + 30 929 0 0 + 31 1000 0 0 + 32 0 0 0 + 33 62 3 0 + 34 129 15 0 + 35 196 39 0 + 36 262 70 0 + 37 329 109 0 + 38 396 156 0 + 39 462 215 0 + 40 529 282 0 + 41 596 356 0 + 42 662 443 0 + 43 729 537 0 + 44 796 639 0 + 45 862 749 0 + 46 929 870 0 + 47 1000 1000 0 + 48 0 0 0 + 49 0 62 0 + 50 0 129 0 + 51 0 196 0 + 52 0 262 0 + 53 0 329 0 + 54 0 396 0 + 55 0 462 0 + 56 0 529 0 + 57 0 596 0 + 58 0 662 0 + 59 0 729 0 + 60 0 796 0 + 61 0 862 0 + 62 0 929 0 + 63 0 1000 0 + 64 0 0 0 + 65 0 62 62 + 66 0 129 129 + 67 0 196 196 + 68 0 262 262 + 69 0 329 329 + 70 0 396 396 + 71 0 462 462 + 72 0 529 529 + 73 0 596 596 + 74 0 662 662 + 75 0 729 729 + 76 0 796 796 + 77 0 862 862 + 78 0 929 929 + 79 0 1000 1000 + 80 0 0 0 + 81 0 0 62 + 82 0 0 129 + 83 0 0 196 + 84 0 0 262 + 85 0 0 329 + 86 0 0 396 + 87 0 0 462 + 88 0 0 529 + 89 0 0 596 + 90 0 0 662 + 91 0 0 729 + 92 0 0 796 + 93 0 0 862 + 94 0 0 929 + 95 0 0 1000 + 96 0 0 0 + 97 62 0 62 + 98 129 0 129 + 99 196 0 196 +100 262 0 262 +101 329 0 329 +102 396 0 396 +103 462 0 462 +104 529 0 529 +105 596 0 596 +106 662 0 662 +107 729 0 729 +108 796 0 796 +109 862 0 862 +110 929 0 929 +111 1000 0 1000 +112 372 121 121 +113 501 137 137 +114 643 137 137 +115 792 129 129 +116 898 168 168 +117 941 266 266 +118 976 376 376 +119 1000 498 498 +120 372 372 121 +121 501 501 137 +122 643 643 137 +123 792 792 129 +124 898 898 168 +125 941 941 266 +126 976 976 376 +127 1000 1000 498 +128 121 372 121 +129 137 501 137 +130 137 643 137 +131 129 792 129 +132 168 898 168 +133 266 941 266 +134 376 976 376 +135 498 1000 498 +136 121 372 372 +137 137 501 501 +138 137 643 643 +139 129 792 792 +140 168 898 898 +141 266 941 941 +142 376 976 976 +143 498 1000 1000 +144 121 121 372 +145 137 137 501 +146 137 137 643 +147 129 129 792 +148 168 168 898 +149 266 266 941 +150 376 376 976 +151 498 498 1000 +152 372 121 372 +153 501 137 501 +154 643 137 643 +155 792 129 792 +156 898 168 898 +157 941 266 941 +158 976 376 976 +159 1000 498 1000 +160 309 247 184 +161 435 317 203 +162 572 392 207 +163 729 462 196 +164 847 533 219 +165 913 603 298 +166 964 678 388 +167 1000 749 498 +168 247 309 184 +169 317 435 203 +170 392 572 207 +171 462 729 196 +172 533 847 219 +173 603 913 298 +174 678 964 388 +175 498 1000 749 +176 184 309 247 +177 203 435 317 +178 207 572 392 +179 196 729 462 +180 219 847 533 +181 298 913 603 +182 388 964 678 +183 498 1000 749 +184 184 247 309 +185 203 317 435 +186 207 392 572 +187 196 462 729 +188 219 533 847 +189 298 603 913 +190 388 678 964 +191 498 749 1000 +192 247 184 309 +193 317 203 435 +194 392 207 572 +195 462 196 729 +196 533 219 847 +197 603 298 913 +198 678 388 964 +199 749 498 1000 +200 298 98 98 +201 415 137 137 +202 533 176 176 +203 650 215 215 +204 756 270 270 +205 796 388 388 +206 835 505 505 +207 874 623 623 +208 298 298 98 +209 415 415 137 +210 533 533 176 +211 650 650 215 +212 756 756 270 +213 796 796 388 +214 835 835 505 +215 874 874 623 +216 98 298 98 +217 137 415 137 +218 176 533 176 +219 215 650 215 +220 270 756 270 +221 388 796 388 +222 505 835 505 +223 623 874 623 +224 98 298 298 +225 137 415 415 +226 176 533 533 +227 215 650 650 +228 270 756 756 +229 388 796 796 +230 505 835 835 +231 623 874 874 +232 98 98 298 +233 137 137 415 +234 176 176 533 +235 215 215 650 +236 270 270 756 +237 388 388 796 +238 505 505 835 +239 623 623 874 +240 298 98 298 +241 415 137 415 +242 533 176 533 +243 650 215 650 +244 756 270 756 +245 796 388 796 +246 835 505 835 +247 874 623 874 +248 396 196 0 +249 513 254 0 +250 627 313 0 +251 741 368 0 +252 854 427 0 +253 968 482 0 +254 996 541 82 +255 996 596 196 diff --git a/colors/rainbow.clr b/colors/rainbow.clr new file mode 100644 index 0000000..43f4840 --- /dev/null +++ b/colors/rainbow.clr @@ -0,0 +1,257 @@ + 0 0 0 0 + 1 243 0 258 + 2 235 0 266 + 3 227 0 274 + 4 219 0 282 + 5 211 0 290 + 6 203 0 298 + 7 196 0 305 + 8 188 0 313 + 9 180 0 321 + 10 172 0 329 + 11 164 0 337 + 12 156 0 345 + 13 149 0 352 + 14 141 0 360 + 15 133 0 368 + 16 125 0 376 + 17 117 0 384 + 18 109 0 392 + 19 101 0 400 + 20 94 0 407 + 21 86 0 415 + 22 78 0 423 + 23 70 0 431 + 24 62 0 439 + 25 54 0 447 + 26 47 0 454 + 27 39 0 462 + 28 31 0 470 + 29 23 0 478 + 30 15 0 486 + 31 7 0 494 + 32 0 0 501 + 33 0 15 494 + 34 0 31 486 + 35 0 47 478 + 36 0 62 470 + 37 0 78 462 + 38 0 94 454 + 39 0 109 447 + 40 0 125 439 + 41 0 141 431 + 42 0 156 423 + 43 0 172 415 + 44 0 188 407 + 45 0 203 400 + 46 0 219 392 + 47 0 235 384 + 48 0 250 376 + 49 0 266 368 + 50 0 282 360 + 51 0 298 352 + 52 0 313 345 + 53 0 329 337 + 54 0 345 329 + 55 0 360 321 + 56 0 376 313 + 57 0 392 305 + 58 0 407 298 + 59 0 423 290 + 60 0 439 282 + 61 0 454 274 + 62 0 470 266 + 63 0 486 258 + 64 0 501 250 + 65 11 509 243 + 66 23 517 235 + 67 35 525 227 + 68 47 533 219 + 69 58 541 211 + 70 70 549 203 + 71 82 556 196 + 72 98 564 188 + 73 109 572 180 + 74 121 580 172 + 75 133 588 164 + 76 145 596 156 + 77 156 603 149 + 78 168 611 141 + 79 180 619 133 + 80 196 627 125 + 81 207 635 117 + 82 219 643 109 + 83 231 650 101 + 84 243 658 94 + 85 254 666 86 + 86 266 674 78 + 87 278 682 70 + 88 294 690 62 + 89 305 698 54 + 90 317 705 47 + 91 329 713 39 + 92 341 721 31 + 93 352 729 23 + 94 364 737 15 + 95 376 745 7 + 96 392 752 0 + 97 407 756 0 + 98 427 764 0 + 99 447 772 0 +100 466 780 0 +101 486 788 0 +102 505 796 0 +103 521 803 0 +104 541 811 0 +105 560 819 0 +106 580 827 0 +107 600 835 0 +108 619 843 0 +109 635 850 0 +110 654 858 0 +111 674 866 0 +112 694 874 0 +113 713 882 0 +114 733 890 0 +115 752 898 0 +116 768 905 0 +117 788 913 0 +118 807 921 0 +119 827 929 0 +120 847 937 0 +121 866 945 0 +122 882 952 0 +123 901 960 0 +124 921 968 0 +125 941 976 0 +126 960 984 0 +127 980 992 0 +128 1000 1000 0 +129 1000 980 0 +130 1000 960 0 +131 1000 941 0 +132 1000 921 0 +133 1000 901 0 +134 1000 882 0 +135 1000 866 0 +136 1000 847 0 +137 1000 827 0 +138 1000 807 0 +139 1000 788 0 +140 1000 768 0 +141 1000 752 0 +142 1000 733 0 +143 1000 713 0 +144 1000 694 0 +145 1000 674 0 +146 1000 654 0 +147 1000 635 0 +148 1000 619 0 +149 1000 600 0 +150 1000 580 0 +151 1000 560 0 +152 1000 541 0 +153 1000 521 0 +154 1000 505 0 +155 1000 486 0 +156 1000 466 0 +157 1000 447 0 +158 1000 427 0 +159 1000 407 0 +160 1000 392 0 +161 1000 376 11 +162 1000 364 23 +163 1000 352 35 +164 1000 341 47 +165 1000 329 58 +166 1000 317 70 +167 1000 305 82 +168 1000 294 98 +169 1000 278 109 +170 1000 266 121 +171 1000 254 133 +172 1000 243 145 +173 1000 231 156 +174 1000 219 168 +175 1000 207 180 +176 1000 196 196 +177 1000 180 207 +178 1000 168 219 +179 1000 156 231 +180 1000 145 243 +181 1000 133 254 +182 1000 121 266 +183 1000 109 278 +184 1000 98 294 +185 1000 82 305 +186 1000 70 317 +187 1000 58 329 +188 1000 47 341 +189 1000 35 352 +190 1000 23 364 +191 1000 11 376 +192 1000 0 392 +193 988 0 400 +194 980 0 411 +195 968 0 419 +196 960 0 431 +197 952 0 439 +198 941 0 450 +199 933 0 458 +200 925 0 470 +201 913 0 478 +202 905 0 490 +203 898 0 498 +204 886 0 509 +205 878 0 517 +206 870 0 529 +207 858 0 537 +208 850 0 549 +209 843 0 556 +210 831 0 568 +211 823 0 576 +212 815 0 588 +213 803 0 596 +214 796 0 607 +215 788 0 615 +216 776 0 627 +217 768 0 635 +218 760 0 647 +219 749 0 654 +220 741 0 666 +221 733 0 674 +222 721 0 686 +223 713 0 694 +224 705 0 705 +225 694 0 690 +226 682 0 674 +227 674 0 662 +228 662 0 647 +229 650 0 631 +230 643 0 619 +231 631 0 603 +232 623 0 592 +233 611 0 576 +234 600 0 560 +235 592 0 549 +236 580 0 533 +237 568 0 517 +238 560 0 505 +239 549 0 490 +240 541 0 478 +241 529 0 462 +242 549 0 447 +243 509 0 435 +244 498 0 419 +245 486 0 403 +246 478 0 392 +247 466 0 376 +248 458 0 364 +249 447 0 349 +250 435 0 333 +251 427 0 321 +252 415 0 305 +253 403 0 290 +254 396 0 278 +255 1000 1000 1000 + \ No newline at end of file diff --git a/colors/random.clr b/colors/random.clr new file mode 100644 index 0000000..763cc23 --- /dev/null +++ b/colors/random.clr @@ -0,0 +1,256 @@ + 0 0 0 0 + 1 1000 1000 1000 + 2 1000 0 1000 + 3 1000 1000 0 + 4 1000 0 1000 + 5 666 666 666 + 6 1000 498 0 + 7 1000 0 0 + 8 498 1000 0 + 9 0 498 0 + 10 333 701 0 + 11 0 0 1000 + 12 0 498 1000 + 13 0 1000 1000 + 14 749 498 0 + 15 0 850 0 + 16 666 0 666 + 17 701 400 0 + 18 850 600 298 + 19 1000 666 666 + 20 1000 800 600 + 21 0 800 1000 + 22 0 1000 800 + 23 392 392 392 + 24 1000 250 250 + 25 1000 666 333 + 26 333 333 1000 + 27 0 333 1000 + 28 1000 333 27 + 29 749 250 0 + 30 749 94 94 + 31 0 0 0 + 32 1000 1000 1000 + 33 1000 1000 0 + 34 1000 0 1000 + 35 666 666 666 + 36 1000 498 0 + 37 1000 0 0 + 38 498 1000 0 + 39 0 498 0 + 40 333 701 0 + 41 0 0 1000 + 42 0 498 1000 + 43 0 1000 1000 + 44 749 498 0 + 45 0 850 0 + 46 666 0 666 + 47 701 400 0 + 48 850 600 298 + 49 1000 666 666 + 50 1000 800 600 + 51 0 800 1000 + 52 0 1000 800 + 53 392 392 392 + 54 1000 250 250 + 55 1000 666 333 + 56 333 333 1000 + 57 0 333 1000 + 58 1000 333 0 + 59 749 250 0 + 60 749 94 94 + 61 0 0 0 + 62 1000 1000 1000 + 63 1000 1000 0 + 64 1000 0 1000 + 65 666 666 666 + 66 1000 498 11 + 67 1000 0 0 + 68 498 1000 0 + 69 0 498 0 + 70 333 701 0 + 71 0 0 1000 + 72 0 0 1000 + 73 0 498 1000 + 74 0 1000 1000 + 75 749 498 0 + 76 0 850 27 + 77 666 0 666 + 78 701 400 0 + 79 850 600 298 + 80 1000 666 666 + 81 1000 800 600 + 82 0 800 1000 + 83 0 1000 800 + 84 392 392 392 + 85 1000 250 250 + 86 1000 666 333 + 87 333 333 1000 + 88 0 333 1000 + 89 1000 333 0 + 90 749 250 0 + 91 1000 1000 0 + 92 749 94 94 + 93 1000 0 1000 + 94 666 666 666 + 95 1000 498 0 + 96 1000 0 0 + 97 498 1000 0 + 98 0 498 11 + 99 0 0 1000 +100 333 701 27 +101 0 498 1000 +102 0 1000 1000 +103 749 498 0 +104 0 850 27 +105 666 0 666 +106 701 400 0 +107 850 600 298 +108 1000 666 666 +109 1000 800 600 +110 0 800 1000 +111 0 1000 800 +112 392 392 392 +113 1000 250 250 +114 1000 666 333 +115 333 333 1000 +116 0 333 1000 +117 1000 333 0 +118 749 250 0 +119 749 94 94 +120 0 0 0 +121 1000 1000 1000 +122 1000 1000 0 +123 1000 0 1000 +124 666 666 666 +125 1000 498 0 +126 1000 0 0 +127 498 1000 0 +128 0 498 0 +129 333 701 0 +130 0 0 1000 +131 0 498 1000 +132 0 1000 1000 +133 749 498 0 +134 0 850 0 +135 666 0 666 +136 701 400 0 +137 850 600 298 +138 1000 666 666 +139 1000 800 600 +140 0 800 1000 +141 0 1000 800 +142 392 392 392 +143 1000 250 250 +144 1000 666 333 +145 333 333 1000 +146 0 333 1000 +147 1000 333 0 +148 749 250 27 +149 749 94 94 +150 0 0 27 +151 1000 1000 1000 +152 1000 1000 0 +153 1000 0 1000 +154 666 666 666 +155 1000 498 0 +156 1000 0 11 +157 498 1000 0 +158 0 498 0 +159 333 701 0 +160 0 0 1000 +161 0 498 1000 +162 0 1000 1000 +163 749 498 0 +164 0 850 0 +165 666 0 666 +166 701 400 0 +167 850 600 298 +168 1000 666 666 +169 1000 800 600 +170 0 800 1000 +171 0 1000 800 +172 392 392 392 +173 1000 250 250 +174 1000 666 333 +175 333 333 1000 +176 0 333 1000 +177 1000 333 0 +178 749 250 27 +179 749 94 94 +180 0 0 0 +181 1000 1000 1000 +182 1000 1000 0 +183 1000 0 1000 +184 666 666 666 +185 1000 498 0 +186 1000 0 0 +187 498 1000 0 +188 0 498 0 +189 333 701 0 +190 0 0 1000 +191 0 498 1000 +192 0 1000 1000 +193 749 498 0 +194 0 850 27 +195 666 0 666 +196 701 400 0 +197 850 600 298 +198 1000 666 666 +199 1000 800 600 +200 0 800 1000 +201 0 1000 800 +202 392 392 392 +203 1000 250 250 +204 1000 666 333 +205 333 333 1000 +206 749 250 0 +207 749 94 94 +208 0 0 11 +209 1000 1000 1000 +210 1000 1000 0 +211 1000 0 1000 +212 666 666 666 +213 1000 498 0 +214 1000 0 0 +215 498 1000 0 +216 0 498 0 +217 333 701 0 +218 0 0 1000 +219 0 498 1000 +220 0 1000 1000 +221 749 498 0 +222 0 850 0 +223 666 0 666 +224 701 400 0 +225 850 600 298 +226 1000 666 666 +227 1000 800 600 +228 0 800 1000 +229 0 1000 800 +230 392 392 392 +231 1000 250 250 +232 1000 666 333 +233 333 333 1000 +234 0 333 1000 +235 1000 333 0 +236 749 250 0 +237 749 94 94 +238 0 0 0 +239 1000 1000 1000 +240 1000 1000 0 +241 1000 0 1000 +242 666 666 666 +243 1000 498 0 +244 1000 27 0 +245 498 1000 0 +246 0 498 0 +247 333 701 0 +248 0 0 1000 +249 0 498 1000 +250 0 1000 1000 +251 749 498 0 +252 0 850 0 +253 666 0 666 +254 701 400 0 +255 1000 1000 1000 diff --git a/dll/Makefile b/dll/Makefile new file mode 100644 index 0000000..da04b2b --- /dev/null +++ b/dll/Makefile @@ -0,0 +1,47 @@ +CC=gcc +FGIS_HOME=/usr/lib/fgis +CFLAGS=-g -Wall -pedantic -fPIC\ + -I/usr/openwin/include -I/usr/local/include -I../include \ + -DFGIS_HOME=\"${FGIS_HOME}\" +LDFLAGS=-L../lib -L/usr/openwin/lib -L/usr/local/lib +LOADLIBES=-ldl -lm -lepp -lX11 -ltcl8.0 -ltk8.0 + +OBJS=\ +fgisInit.o\ +fgisMisc.o\ +fgisPalette.o\ +fgisRaster.o\ +fgisPlanchet.o\ +fgisEppCalc.o\ +fgisEppDraw.o\ +fgisVector.o\ +fgisPatterns.o\ +fgisProjection.o +SRC=\ +RCS/fgisInit.c,v\ +RCS/fgisMisc.c,v\ +RCS/fgisPalette.c,v\ +RCS/fgisRaster.c,v\ +RCS/fgisVector.c,v\ +RCS/fgisPlanchet.c,v\ +RCS/fgisEppCalc.c,v\ +RCS/fgisEppDraw.c,v\ +RCS/fgisVector.c,v\ +RCS/fgisPatterns.c,v\ +RCS/fgisProjection.c,v\ +RCS/fgis.h,v\ +RCS/fgisInt.h,v + +RCS/%,v : % + ci $< +%.E : %.c + gcc ${CFLAGS} -E $< > $* +all: fgis.so +fgis.so: ${OBJS} +# cc -G ${OBJS} ../lib/*.o -o fgis.so -lm -ltcl8.0 -L/usr/local/lib + gcc -shared -o fgis.so ${OBJS} ../lib/*.o -lm -ltcl8.0 +rcs: ${SRC} +test: fgis.so + echo load ./fgis.so|wish +clean: + rm -f ${OBJS} fgis.so diff --git a/dll/fgis.h b/dll/fgis.h new file mode 100644 index 0000000..06500b3 --- /dev/null +++ b/dll/fgis.h @@ -0,0 +1,122 @@ +#ifndef FGIS_H +#define FGIS_H + +#include +#include +#include +#include "fgisInt.h" + + +#define CACHE_THRESHOLD 4000000L +/* maximum size of cache, allowed for raster files */ + +#define MAX_PALETTE_SIZE 20480 +/* The size of palette file wihch never would be exceeded + (256 lines, 80 chars each - is it enough?) + */ + +/* This header file contain all definition of routines, + which implements EPTcl commands. Neccessary for Eptcl_Init + */ + +void Fgis_DefDeleteProc(ClientData client_data); +/* Empty command delete proc */ + +/* Argument parsing and checking*/ + +int Fgis_GetInt(Tcl_Interp *interp,int argc,char **argv,int index, + int min, int max,int *result, char *name); +/* Fetches int argument from argv array at index, checking for its presence, + format and range. Puts into result. name is descriptive name for errir + reporting + */ +int Fgis_GetLimits(Tcl_Interp *interp,char *list,double *X1,double *Y1, + double *X2,double *Y2); +/* Parses four element list of doubles, representing region on map or + window */ +int Fgis_CkArgs(Tcl_Interp *interp,int cond, char *cmd, char *msg); +/* + * Palette - related procedures + */ +PATTERNS Fgis_GetPatterns(Tcl_Interp *interp,char *name); + +int Fgis_Palette(ClientData data,Tcl_Interp *interp,int argc,char **argv); +/* palette object construction */ + +int Fgis_PaletteObj(ClientData data,Tcl_Interp *interp,int argc,char **argv); +/* Command procedure for palette object command */ + +void Fgis_DeletePalette(ClientData data); +/* all the same for pattern sets */ +int Fgis_CreatePatterns(ClientData data,Tcl_Interp *interp,int argc,char **argv); +int Fgis_PatternObj(ClientData data,Tcl_Interp *interp, int argc, char **argv); +void Fgis_DeletePatterns(ClientData data); +/* + * Accessible from other modules Returns palette, corresponding with + * tcl command name in interp. Don't try to fool it, passing non palette-object + * command! Returns NULL and leaves message in interpreter in case of error. + */ +PALETTE Fgis_GetPalette(Tcl_Interp *interp, char *name); +/* Allows to fetch palette, if its Tcl name is given */ + +/* Raster related stuff */ + +int Fgis_Raster(ClientData data,Tcl_Interp *interp,int argc,char **argv); +/* implements raster command */ +int Fgis_RasterObj(ClientData data,Tcl_Interp *interp,int argc, char **argv); +/* implements object command of raster objects */ + +void Fgis_DeleteRaster(ClientData data); +/* delete proc for command raster - desroys global tables*/ +void Fgis_DeleteRasterObj(ClientData data); +/* delete proc for raster object command - destroys raster itself*/ + +RASTER_OBJECT Fgis_GetRaster(Tcl_Interp *interp, char *name); +/* vector related stuff */ + +int Fgis_Vector(ClientData data,Tcl_Interp *interp,int argc,char **argv); +int Fgis_VectorObj(ClientData data,Tcl_Interp *interp,int argc,char **argv); +void Fgis_DeleteVectorObj(ClientData data); + +/* projection object */ +int Fgis_Projection(ClientData data,Tcl_Interp* interp,int argc, char **argv); +int Fgis_ProjObject(ClientData data,Tcl_Interp* interp,int argc, char **argv); +void Fgis_DeleteProj(ClientData data); +/* Drawing objects */ + +int Fgis_RasterImage(ClientData data,Tcl_Interp* interp,int argc, + char **argv); + + +/* Planchet methods */ +int Fgis_MapX(ClientData data,Tcl_Interp* interp,int argc, char **argv); +int Fgis_MapY(ClientData data,Tcl_Interp* interp,int argc, char **argv); +int Fgis_ScrY(ClientData data,Tcl_Interp* interp,int argc, char **argv); +int Fgis_ScrX(ClientData data,Tcl_Interp* interp,int argc, char **argv); +int Fgis_Fit(ClientData data,Tcl_Interp* interp,int argc, char **argv); + +/* Functions for access planchet from C code */ +double Fgis_AltX(Tcl_Interp *interp,char *planchet ,int x); +double Fgis_AltY(Tcl_Interp *interp,char *planchet ,int y); +int Fgis_PlanchetX(Tcl_Interp *interp, char *planchet ,double x); +int Fgis_PlanchetY(Tcl_Interp *interp, char *planchet ,double y); +int Fgis_ValidPlanchet(Tcl_Interp *interp, char *planchet); +int Fgis_CreateObjectCommand(Tcl_Interp *interp,char *prefix, + Tcl_CmdProc *proc,ClientData data, Tcl_CmdDeleteProc deleteProc); +/* handy defines */ + +/* Makes dynamically allocante copy of string, using Tcl allocator */ +#define stralloc(x) (strcpy(Tcl_Alloc(strlen(x)+1),x)) + +/* Body of non-implemented procedure. When it goes away, I would be + VERY happy*/ +#define NOT_YET {Tcl_SetResult(interp,"Not implemented yet",TCL_STATIC); return TCL_ERROR;} + +/* Set result and return error */ +#define ERROR_MESSAGE(msg,mode) {Tcl_SetResult(interp,msg,mode);return TCL_ERROR;} + +/* Set result and return success */ +#define RETURN(value,mode) {Tcl_SetResult(interp,value,mode);return TCL_OK;} +/* Given raster object, returns EPP* */ +#define epp(x) (x->file->e) +#endif diff --git a/dll/fgisCount.c b/dll/fgisCount.c new file mode 100644 index 0000000..26522cb --- /dev/null +++ b/dll/fgisCount.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include "fgisInt.h" +#include "fgis.h" +/* + * This file is part of fGIS C library + * fgisCount.c Various routines to perform area counting on rasters + */ +int count_to_array(Tcl_Interp *interp,RASTER_OBJECT raster,char *array /* here geomerty spec should be*/) +{ EPP *e=epp(raster); + int *accumulate; + RECLASS r=raster->reclass; + int v,i,j,size=Fgis_RasterMax(raster)+1; + accumulate=calloc(ize,sizeof(int)); +/* loop should vary according to geometry specifications */ + for (i=e->fr;ilr;i++) + for (j=e->fc;jlc;j++) { + v=epp_get(e,j,i); + if (v!=e->offsite)) { + accumulate[r[v]]++; + } + } + for (i=0;icell_area,result); + sprintf(index,"%d",i); + Tcl_SetVar2(interp,array.index,result) + } + } + free(accumulate) + return TCL_OK; +} diff --git a/dll/fgisEppCalc.c b/dll/fgisEppCalc.c new file mode 100644 index 0000000..2aa6c16 --- /dev/null +++ b/dll/fgisEppCalc.c @@ -0,0 +1,161 @@ +#include +#include +#include +#include "fgisInt.h" +#include "fgis.h" +/* + * fgisEppCalc.c + * + * Functions to deal with raster objects, which are not directly interfaces + * TCL + */ + +/* Some global variables are defined here */ +/* Default reclass - property of reclass command + Something wrong with it. It should be allocated once, not upon each + intiialization of package + */ +RECLASS def_reclass; +/* Points to list of all open rasters. This is good, becouse it would + correctly handle access to open rasters from multiple interptreters + */ +XEPP *first_raster=NULL; +RASTER_OBJECT firstobject=NULL; +/* + * Returns maximal value of raster, using current reclass + * + */ +int Fgis_RasterMax(RASTER_OBJECT handle) +{ + EPP *e=epp(handle); + int max,i; + if(handle->reclass==def_reclass) + max=e->max; + else { + max=0; + for(i=e->min;i<=e->max;i++) + if (i!=e->offsite&&handle->reclass[i]>max) + max=handle->reclass[i]; + } + return max; +} + +/* + * Returns minimal value of raster, taking into account current reclass + * + */ +int Fgis_RasterMin(RASTER_OBJECT handle) +{ + EPP *e=epp(handle); + int min,i; + if(handle->reclass==def_reclass) + min=e->min; + else { + min=65535; + for(i=e->min;i<=e->min;i++) + if (i!=e->offsite&&handle->reclass[i]reclass[i]; + } + return min; +} +/* + * Reopens file in new mode. Returns 0 on success, non-zero on failure. + * If fails, file remains open in old mode. + */ + + +/* + * Creates new XEPP object from open EPP* object. + * + */ + +XEPP* Fgis_NewXEPP(EPP *file,char *filename) +{XEPP* xptr; + + xptr=malloc(sizeof(XEPP)); + xptr->e=file; + xptr->linkcount=1; + xptr->filename=stralloc(filename); + xptr->next=first_raster; + xptr->editable=1; + first_raster=xptr; + return xptr; +} +/* + * Opens existing epp file. If file already opened, returns pointer + * to it + */ + +XEPP* Fgis_OpenXEPP(char *filename,EPP *(*openfunc)(char *)) +{ + EPP* epp_ptr; + XEPP * xptr=first_raster; + RASTER_OBJECT obj; + int reclass_size; + while (xptr) { + if (!strcmp(xptr->filename,filename)) break; + xptr=xptr->next; + } + + if (!xptr) { + /* îÅÔ ÔÁËÏÇÏ × ÔÁÂÌÉÃÅ, ÏÔËÒÙ×ÁÅÍ ÎÏ×ÙÊ*/ + epp_ptr=openfunc(filename); + if (!epp_ptr) { + return NULL; + } + xptr=Fgis_NewXEPP(epp_ptr,filename); + xptr->editable=(openfunc==load_epp); + + } else { + (xptr->linkcount)++; + /* if it was open in read-only mode and now we want it to + be read-write */ + if (!xptr->editable&&openfunc==load_epp) { + /* close it */ + close_epp(xptr->e); + /* reopen for read-write */ + xptr->e=load_epp(filename); + /* if failed, restore it back in readonly mode and return NULL*/ + if (!xptr->e) { + xptr->e=open_epp(filename); + xptr->linkcount--; + return NULL; + } + /* fix reclass tables for all objects, which refers to this file*/ + reclass_size=1<<(xptr->e->kind); + for (obj=firstobject;obj!=NULL;obj=obj->next) { + if (obj->file==xptr) { + obj->reclass=realloc(obj->reclass,reclass_size*sizeof(short)); + } + } + + } + } + return xptr; + +} + +/* + * Gets rid of XEPP object (if only reference - deletes, otherwise + * decrements link count) + */ + +void Fgis_CloseXEPP(XEPP* file) +{ + file->linkcount--; + if(!file->linkcount) { + /* Remove it from list */ + if (first_raster==file) { + first_raster=file->next; + } else { + XEPP* tmp=first_raster; + while (tmp->next!=file) + tmp=tmp->next; + tmp->next=file->next; + } + /* Close eppfile */ + close_epp(file->e); + free(file->filename); + free(file); + } +} diff --git a/dll/fgisEppDraw.c b/dll/fgisEppDraw.c new file mode 100644 index 0000000..7cd9017 --- /dev/null +++ b/dll/fgisEppDraw.c @@ -0,0 +1,364 @@ +#include +#include +#include +#include +#include +#include "fgis.h" +#include "fgisInt.h" +unsigned short int *border_buffer1, *border_buffer2, *bbuf_ptr1, *bbuf_ptr2; + +void init_border (int width, int offsite) +{ + int i; + border_buffer1 = (unsigned short int *)Tcl_Alloc ( + (width + 1) * sizeof (unsigned short int)); + border_buffer2 = (unsigned short int *)Tcl_Alloc ( + (width + 1) * sizeof (unsigned short int)); + *border_buffer2 = offsite; + for (i = 0, bbuf_ptr1 = border_buffer1; i <= width; i++, bbuf_ptr1++) + *bbuf_ptr1 = offsite; +} +void new_border_row () +{ + unsigned short int *tmp; + tmp = border_buffer1; + border_buffer1 = border_buffer2; + border_buffer2 = tmp; + bbuf_ptr1 = border_buffer1; + bbuf_ptr2 = border_buffer2; + +} int check_border (int class) +{ + *(++bbuf_ptr1) = class; + bbuf_ptr2++; + return *bbuf_ptr2 != class || *(bbuf_ptr1 - 1) != + class || *(bbuf_ptr2 - 1) != class; +} +void done_border () +{ + Tcl_Free ((char*)border_buffer1); + Tcl_Free ((char*)border_buffer2); +} +/* + +òÉÓÕÅÔ ÕËÁÚÁÎÎÙÊ ËÕÓÏË ÒÁÓÔÒÁ (× ÁÌØÔÅÒÎÁÔÉ×ÎÙÈ ËÏÏÒÄÉÎÁÔÁÈ) +*/ + +int Fgis_MakePhotoImage (Tk_PhotoHandle imghandle, + int xl, int yb, int xr, int yt, + double XL, double XR, double YT, double YB, + RASTER_OBJECT handle, + int border,/* 0 - ÎÉÞÅÇÏ, 1, ÐÒÉ ÎÅÓÏ×ÐÁÄÅÎÉÉ + Ã×ÅÔÏ× ÐÏÓÌÅ ÒÅËÌÁÓÓÁ, + 2 - ÐÒÉ ÎÅÓÏ×ÐÁÄÅÎÉÉ Ã×ÅÔÏ× + ÂÁÚÏ×ÏÇÏ ÒÁÓÔÒÁ + */ + PALETTE palette, + int bordercolor, + int mapmode /* 0 - wrap (x&0xFF), -1 x>255?255:x, + >0 map + */ + ) +{ + Tk_PhotoImageBlock block = + {NULL, 0, 1, 1000, 4, +#ifdef LSB_FIRST + {2, 1, 0} +#else + {1, 2, 3} +#endif + }; + + EPP *e = epp (handle); + RECLASS r = handle->reclass; + int width = xr - xl, height = yb - yt; + int *irow, *rp; + int *pal; + int *coltab, *col; + double W_Alt = XR - XL, H_Alt = YB - YT; + int x, y, row, i, j, maxclass=0; + int max_base_class; + int base ; +/* + ÜÔÏ ÂÕÆÅÒ ÄÌÑ ÈÒÁÎÅÎÉÑ ÐÒÏÒÉÓÏ×ÁÎÎÏÊ ÓÔÒÏËÉ + */ + irow =(int *) Tcl_Alloc (width * sizeof (int)); + max_base_class = epp_table_size (e) + 1; +/* + íÁÓÓÉ× ×ÈÏÄÏ× × ÐÁÌÉÔÒÕ ÄÌÑ ËÌÁÓÓÏ× ÂÁÚÏ×ÏÇÏ ÒÁÓÔÒÁ + */ + pal = (int *)Tcl_Alloc(max_base_class * sizeof (int)); + if (mapmode > 0) + maxclass = Fgis_RasterMax (handle); + for (i = 0; i < max_base_class; i++) { + int index; + index = r[i]; + if (index > 255) + switch (mapmode) { + case 0: + index &= 0xFF; + break; /* + wrap + */ + case -1: + index = 255; + break; /* + no wrap + */ + default: + index = index * mapmode / maxclass; + if (i == e->offsite) + index = 255; + + } + pal[i] = palette[index]; + if (i!= e->offsite) + pal[i]|=0xff000000; + } + /* + ÜÔÏ ÔÁÂÌÉÃÁ ÐÏÒÑÄËÏ×ÙÈ ÎÏÍÅÒÏ× ËÏÌÏÎÏË × epp-ÆÁÊÌÅ, ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÈ + ÐÉËÓÅÌÁÍ ÒÁÓÔÒÁ + */ + coltab =(int *) Tcl_Alloc (width * sizeof (int)); + for (i = xl, col = coltab, j = 0; i < xr; i++, j++, col++) { + *col = epp_col (e, W_Alt * (j + 0.5) / width + XL); + } +/* + úÁÐÏÌÎÉÍ ÔÅ ÐÏÌÑ ÓÔÒÕËÔÕÒÙ block, ËÏÔÏÒÙÅ ÍÙ ÎÅ ÍÏÇÌÉ ÉÎÉÃÉÁÌÉÚÉÒÏ×ÁÔØ + */ + block.pixelPtr = (unsigned char *) irow; + block.width = width; + block.pitch = width * sizeof (int); + if (border) { + if (border == 1) + init_border (width, r[e->offsite]); + else + init_border (width, e->offsite); + } + /* ðÏÞÉÓÔÉÍ image */ + Tk_PhotoBlank(imghandle); + for (y = yt, i = 0; y < yb; y++, i++) { + row = epp_row (e, H_Alt * (i + 0.5) / height + YT); + if (border) + new_border_row (); + for (x = xl, j = 0, col = coltab, rp = irow; x < xr; + j++, col++, rp++, x++) { + base = epp_get (e, *col, row); + if (border) { + if (border == 1 ? check_border (r[base]) : + check_border (base)) { + *rp = bordercolor; + continue; + } + } + *rp = pal[base]; + } + Tk_PhotoPutBlock (imghandle, &block, xl, y, width, 1); + } + done_border (); + Tcl_Free ((char *)pal); + Tcl_Free ((char *)irow); + Tcl_Free ((char *)coltab); + return TCL_OK; + +} + +void Fgis_PlotPatterns(Tcl_Interp *interp, + char *bitmap_image, + int xl,int yb,int xr,int yt, + double XL, double XR,double YT,double YB, + RASTER_OBJECT handle, + int bordermode, PATTERNS patterns,XColor* color,int mapmode) +{ /* NOT IMPLEMENTED YET */ +} +void Fgis_PlotSymbols(Tcl_Interp *interp, + char *bitmap_image, + int xl,int yb,int xr,int yt, + double XL,double XR,double YT,double YB, + RASTER_OBJECT handle, + PATTERNS patterns, XColor* color, + int mapmode) +{ /*NOT IMPLEMENTED YET*/ + +} +/* + * Fgis_RasterImage + * - implementation of command fgisRasterColorImage and + * fgisRasterBWImage + */ +EXPORT(int, Fgis_RasterImage) (ClientData data, Tcl_Interp *interp, + int argc, char **argv) +{ + int listc; char **listv; /* for parsing result of $planchet bbox $item */ + Tk_PhotoHandle imghandle=NULL; + int colorplot=(int)data; /* how to distinguish between color and bw */ + char *bitmap_image=NULL; + enum {PATTERNS_MODE,SYMBOLS_MODE} symbolmode=PATTERNS_MODE; + int mapmode=0; + int bordercolor=0; + int bordermode=((int)data)?0:1; + PATTERNS patterns=NULL; + PALETTE palette=default_palette; + RASTER_OBJECT raster; + int i; + int xl=0,yt=0,xr,yb,imgstartx,imgstarty; + double XL,YT,XR,YB; + XColor *clr; + Tk_Window canvas=Tk_NameToWindow(interp,argv[2],Tk_MainWindow(interp)); + + clr=Tk_GetColor(interp,canvas,"black"); + if (Fgis_CkArgs(interp,argc<5, + argv[0],"raster planchet item ?options?")) + return TCL_ERROR; + if (!Fgis_ValidPlanchet(interp,argv[2])) + return TCL_ERROR; + if (Tcl_VarEval(interp,argv[2]," bbox ",argv[3],NULL)!=TCL_OK) + return TCL_ERROR; + if (Tcl_SplitList(interp,interp->result,&listc,&listv)!=TCL_OK) + return TCL_ERROR; + imgstartx=atol(listv[0]); + imgstarty=atol(listv[1]); + xr=atol(listv[2]); + yb=atol(listv[3]); + XL=Fgis_AltX(interp,argv[2],imgstartx); + XR=Fgis_AltX(interp,argv[2],xr+1); + YT=Fgis_AltY(interp,argv[2],imgstarty); + YB=Fgis_AltY(interp,argv[2],yb+1); + xr-=imgstartx; + yb-=imgstarty; + Tcl_Free((char *)listv); + if (Tcl_VarEval(interp,argv[2]," itemcget ",argv[3]," -image",NULL)!=TCL_OK) + return TCL_ERROR; + if (colorplot) { + imghandle=Tk_FindPhoto(interp,interp->result); + if (!imghandle) { + Tcl_AppendResult(interp,"No valid image for item ",argv[3], + " in planchet ", argv[2],NULL); + return TCL_ERROR; + } + } else { + if (interp->result) + bitmap_image=stralloc(interp->result); + else { + Tcl_AppendResult(interp,"No valid image for item ",argv[3], + " in planchet ", argv[2],NULL); + return TCL_ERROR; + } + } + raster=Fgis_GetRaster(interp,argv[1]); + if (!raster) { + Tcl_AppendResult(interp,argv[1]," is not valid raster",NULL); + return TCL_ERROR; + } + +for(i=4;ired&0xff)<<16)|((clr->green&0xff)<<8)| + (clr->blue&0xff); + } + } else + if (!strcmp(argv[i],"-map")) { + if (mapmode) + ERROR_MESSAGE("Duplicate color remapping specification",TCL_STATIC); + i++; + if (!strcmp(argv[i],"wrap")) { + mapmode=0; + } else + if (!strcmp(argv[i],"none")) { + mapmode=-1; + } else + if (Fgis_GetInt(interp, argc, argv, ++i, 0, 256, &mapmode, + "color index") !=TCL_OK) { + return TCL_ERROR; + } + } else + if (!strcmp(argv[i],"-update")) { + double X1,Y1,X2,Y2; + int x1,y1,x2,y2; + if (++i==argc) + ERROR_MESSAGE("List of four doubles expected",TCL_STATIC); + if (Fgis_GetLimits(interp,argv[i],&X1,&Y1,&X2,&Y2)!=TCL_OK) + return TCL_ERROR; + x1=Fgis_PlanchetX(interp,argv[2],X1)-imgstartx; + x2=Fgis_PlanchetX(interp,argv[2],X2)-imgstartx; + if (x20) {xl=x1;XL=Fgis_AltX(interp,argv[2],x1+imgstartx);} + if (x20) {yt=y1;YT=Fgis_AltY(interp,argv[2],y1+imgstarty);} + if (y2 +#include +#include +#include +char *mapErrorExplanation[]={NULL, + "Coordinates outside physical borders of file", + "Raster is not editable", + "File read error", + "File write error", + "Memory exhaused", + "File access denied", + "File not found", + "File doesn't conform format", + "File creation error", + }; +/* + * Checks if given EPP file is open in read-write mode and + * given value is good class value for it. + * Should be called each time when one of drawing routines from + * this file is about to be called. + * Returns TCL_ERROR and leaves error message in interp->result + */ +int Fgis_RasterEditable(Tcl_Interp *interp,EPP *epp,char *rastername,int value) +{ if (!(epp->mode&MAP_LOADED)) { + Tcl_AppendResult(interp,"Raster ",rastername," is read-only",NULL); + return TCL_ERROR; + } + if (value>=(1<kind)) { + Tcl_SetResult(interp,"Value too large for this raster",TCL_STATIC); + return TCL_ERROR; + } + return TCL_OK; +} + +/* + * Modifies given cell. + * Return value: 0 on success, nonzero if error + * Side effects: modifies raster if arguments are good + * leaves error message in interp->result, if they are bad + */ +int Fgis_DrawCell(Tcl_Interp *interp,EPP* epp,double x,double y, int value) +{ + map_error=0; + epp_put(epp,epp_col(epp,x),epp_row(epp,y),value); + if (map_error) { + Tcl_SetResult(interp,mapErrorExplanation[map_error],TCL_STATIC); + map_error=0; + return TCL_ERROR; + } + return TCL_OK; +} + +/* + * Draws circle with center in given point and radius given in + * map units + * + */ +int Fgis_DrawCircle(Tcl_Interp *interp,EPP* epp,double x,double y,double r, + int value) +{ + return TCL_OK; +} + +/* + * Draws circle with center in given point and radius given in + * raster cells + * + */ +int Fgis_DrawCircleInt(Tcl_Interp *interp, EPP *epp, double x, double y, + int r, int value) +{ + return TCL_OK; +} +/* + * Draws filled rectangle + * + * + */ + +int Fgis_DrawBox(Tcl_Interp *interp, EPP *epp, double x1, double y1, + double x2, double y2, int value) +{int i, + row1=epp_row(epp,y1), + row2=epp_row(epp,y2), + col1=epp_col(epp,x1), + col2=epp_col(epp,x2); + if (row1fr) row1=epp->fr; + if (row2>=epp->lr) row2=epp->lr-1; + if (row1>row2) { + Tcl_SetResult(interp,mapErrorExplanation[ME_POINT_OUTSIDE],TCL_STATIC); + return TCL_ERROR; + } + map_error=0; + for (i=row1;i<=row2;i++) { + epp_putline(epp,col1,col2,i,value); + if (map_error) { + Tcl_SetResult(interp,mapErrorExplanation[map_error],TCL_STATIC); + map_error=0; + return TCL_ERROR; + } + } + return TCL_OK; +} +/* + * Draws rectangular frame with width, given in pixels + * + * + */ + +int Fgis_DrawFrame(Tcl_Interp *interp, EPP *epp, double x1, double y1, + double x2, double y2, int width, int value) +{ + return TCL_OK; +} +/* + * Draws polyline + * + */ +int Fgis_DrawLine(Tcl_Interp *interp, EPP *epp, int pointc, double *pointv, + int width, int value) +{ + + return TCL_OK; +} + +/* + * Draws filled polygon + * + */ +int Fgis_DrawPolygon(Tcl_Interp *interp, EPP *epp, int pointc, double *pointv, + int value) +{ + + return TCL_OK; +} +/* + * Fills area of raster until encounters different class than in starting + * point. Takes into account four neighbours (left, right, top, bottom) + * + */ +int Fgis_Fill4(Tcl_Interp *interp, EPP *epp, double x, double y, int value) +{ + + return TCL_OK; +} + +/* + * Fills area of raster until encounters given class + * Takes into account four neighbours (left, right, top, bottom) + * + */ +int Fgis_Fill4Until(Tcl_Interp *interp, EPP *epp, double x, double y, + int value, int stopValue) +{ + return TCL_OK; + +} + +/* + * Fills area of raster until encounters different class than in starting + * point. Takes into account eight neighbours (left, right, top, bottom + * and four diagonals) + */ +int Fgis_Fill8(Tcl_Interp *interp, EPP *epp, double x, double y, int value) +{ + return TCL_OK; +} + +/* + * Fills area of raster until encounters given class + * Takes into account eight neighbours (left, right, top, bottom + * and four diagonals) + */ +int Fgis_Fill8Until(Tcl_Interp *interp, EPP *epp, double x, double y, + int value, int stopValue) +{ + return TCL_OK; + +} + + diff --git a/dll/fgisEppEdit.h b/dll/fgisEppEdit.h new file mode 100644 index 0000000..e366d14 --- /dev/null +++ b/dll/fgisEppEdit.h @@ -0,0 +1,26 @@ +#ifndef FGIS_EDIT_H +#define FGIS_EDIT_H +extern char *mapErrorExplanation[]; + +int Fgis_RasterEditable(Tcl_Interp *interp,EPP *epp,char *rastername,int value); +int Fgis_DrawCell(Tcl_Interp *interp,EPP* epp,double x,double y, int value); + +int Fgis_DrawCircle(Tcl_Interp *interp,EPP* epp,double x,double y,double r, + int value); +int Fgis_DrawCircleInt(Tcl_Interp *interp, EPP *epp, double x, double y, + int r, int value); +int Fgis_DrawBox(Tcl_Interp *interp, EPP *epp, double x1, double y1, + double x2, double y2, int value); +int Fgis_DrawFrame(Tcl_Interp *interp, EPP *epp, double x1, double y1, + double x2, double y2, int width, int value); +int Fgis_DrawLine(Tcl_Interp *interp, EPP *epp, int pointc, double *pointv, + int width, int value); +int Fgis_DrawPolygon(Tcl_Interp *interp, EPP *epp, int pointc, double *pointv, + int value); +int Fgis_Fill4(Tcl_Interp *interp, EPP *epp, double x, double y, int value); +int Fgis_Fill4Until(Tcl_Interp *interp, EPP *epp, double x, double y, + int value, int stopValue); +int Fgis_Fill8(Tcl_Interp *interp, EPP *epp, double x, double y, int value); +int Fgis_Fill8Until(Tcl_Interp *interp, EPP *epp, double x, double y, + int value, int stopValue); +#endif diff --git a/dll/fgisInit.c b/dll/fgisInit.c new file mode 100644 index 0000000..59f2fd5 --- /dev/null +++ b/dll/fgisInit.c @@ -0,0 +1,126 @@ +/* + *fgisInit.c - + *initialization procedure for Fgis package + * Copyright (C) by SoftWeyr, 1997 + */ +#include +#include +#include +#include + +#include +#include +#include "fgis.h" + +int check_for_rc(Tcl_Interp *interp,char *home,char *path); +/* Global variables */ + +/* + * Initialization procedure for Environmental Planning Tcl extension + * Return value TCL_OK if success + * Side effects: + * defines commands raster vector palette fgisPlanchet_mapx fgisPlanchet_mapy + * fgisPlanchet_scrx fgisPlanchet_scry fgisPlanchet_fit defaultpalette + * defines default (1:1) reclass table + * defines fGIS_HOME variable to directory, containing fgis.rc + * Directories are searched in following order + * FGIS_HOME as defined in Makefile + * ~/lib/fgis + * executes fgis.rc + */ +EXPORT(int, Fgis_Init)(Tcl_Interp *interp) +{ + char *fGIS_HOME; + char buffer[1024]; +/* Defining commands */ + +/* Palette objects */ + if (!Tcl_CreateCommand(interp,"palette",Fgis_Palette,NULL, + Fgis_DefDeleteProc)) + return TCL_ERROR; + if (!Tcl_CreateCommand(interp,"defaultpalette",Fgis_PaletteObj, + (ClientData)default_palette,Fgis_DeletePalette)) + return TCL_ERROR; +/* Pattern objects */ + if (!Tcl_CreateCommand(interp,"patterns",Fgis_CreatePatterns, + NULL,Fgis_DefDeleteProc)) + return TCL_ERROR; +/* Raster objects */ + if (!Tcl_CreateCommand(interp,"raster",Fgis_Raster, + NULL,Fgis_DeleteRaster)) + return TCL_ERROR; +/* Vector objects */ + if (!Tcl_CreateCommand(interp,"vector",Fgis_Vector,NULL,Fgis_DefDeleteProc)) + return TCL_ERROR; + /* Tk dependent fgis commands. Should eventually go into separate package*/ + /* Object Drawing */ + if (!Tcl_CreateCommand(interp,"fgisRasterColorImage",Fgis_RasterImage, + (ClientData)1,Fgis_DefDeleteProc)) return TCL_ERROR; + if (!Tcl_CreateCommand(interp,"fgisRasterBWImage",Fgis_RasterImage, + NULL,Fgis_DefDeleteProc)) return TCL_ERROR; + /* planchet widget subcommands, written on C */ + if (!Tcl_CreateCommand(interp,"fgisPlanchet_mapx",Fgis_MapX,NULL, + Fgis_DefDeleteProc)) + return TCL_ERROR; + if (!Tcl_CreateCommand(interp,"fgisPlanchet_mapy",Fgis_MapY,NULL, + Fgis_DefDeleteProc)) + + return TCL_ERROR; + if (!Tcl_CreateCommand(interp,"fgisPlanchet_scrx",Fgis_ScrX,NULL, + Fgis_DefDeleteProc)) + return TCL_ERROR; + if (!Tcl_CreateCommand(interp,"fgisPlanchet_scry",Fgis_ScrY,NULL, + Fgis_DefDeleteProc)) + return TCL_ERROR; + if (!Tcl_CreateCommand(interp,"fgisPlanchet_fit",Fgis_Fit,NULL, + Fgis_DefDeleteProc)) + return TCL_ERROR; + if (!Tcl_CreateCommand(interp,"projection",Fgis_Projection,NULL, + Fgis_DefDeleteProc)) + return TCL_ERROR; + + /* Searching for fgis.rc and executing it */ + /* First, check if fGIS_HOME already set */ + if ((fGIS_HOME=Tcl_GetVar(interp,"fGIS_HOME",TCL_GLOBAL_ONLY))==NULL) { + fGIS_HOME=buffer; + /* Check if compilied in default is valid */ + if (!check_for_rc(interp,fGIS_HOME,FGIS_HOME)&& +#ifdef __unix__ + !check_for_rc(interp,fGIS_HOME,"/usr/local/lib/fgis")&& + !check_for_rc(interp,fGIS_HOME,"/usr/lib/fgis")&& + !check_for_rc(interp,fGIS_HOME,"~/fgis") +#else + !check_for_rc(interp,fGIS_HOME,"C:/FGIS") && + !check_for_rc(interp,fGIS_HOME,"C:/Program Files/fGIS") && + !check_for_rc(interp,fGIS_HOME,"C:/TCL/LIB/fGIS") +#endif + ) { + Tcl_SetResult(interp,"Cannot determine fGIS home directory", + TCL_STATIC); + return TCL_ERROR; + }; + Tcl_SetVar(interp,"fGIS_HOME",fGIS_HOME,TCL_GLOBAL_ONLY); + } + + if (Tcl_EvalFile(interp,FGIS_HOME "/fgis.rc")!=TCL_OK) { + Tcl_SetResult(interp,"Error in initialization file",TCL_STATIC); + return TCL_ERROR; + } + /* Providing package for Tcl versions, which supports it */ +#if (TCL_MAJOR_VERSION>7)||((TCL_MAJOR_VERSION==7)&&(TCL_MINOR_VERSION>=5)) + Tcl_PkgProvide(interp,"Fgis","0.1"); +#endif + return TCL_OK; +} + +int check_for_rc (Tcl_Interp *interp,char *home,char *path) +{ char buffer[1024]; + int result; + sprintf(buffer,"file readable [file join {%s} fgis.rc]",path); + Tcl_Eval(interp,buffer); + if (Tcl_GetInt(interp,interp->result,&result)==TCL_OK&& result) { + strcpy(home,path); + return 1; + } + return 0; +} diff --git a/dll/fgisInt.h b/dll/fgisInt.h new file mode 100644 index 0000000..4a1caaa --- /dev/null +++ b/dll/fgisInt.h @@ -0,0 +1,72 @@ +#ifndef FGISINT_H +#define FGISINT_H +#include +#include +#include +typedef int *PALETTE; +extern PALETTE default_palette; + +/* raster related types and variables*/ + + +typedef struct XEPP { int linkcount; /*Count of links */ + char *filename; /* name of raster file */ + struct XEPP* next; /* to chain all open rasters + into list*/ + EPP *e; + int editable; + } XEPP; +typedef struct RASTER_OBJECT { XEPP *file; + RECLASS reclass; + struct RASTER_OBJECT *next; + } *RASTER_OBJECT ; + +extern XEPP *first_raster; /* This pointer intentionally made global. + even if there are serveral Tcl interpreters, + they all should share same list of open rasters*/ +extern RASTER_OBJECT firstobject; + +#define MAX_PATTERN_SIZE (32*256) + + +typedef struct PATTERNS { struct PATTERNS *next; /* patterns are linked in order + to be re-used */ + char *name; + int width,height; + unsigned int bits[MAX_PATTERN_SIZE]; + } *PATTERNS; +#define patternSize(width,height) ((height*256)*sizeof(int)+sizeof (struct PATTERNS)-MAX_PATTERN_SIZE*sizeof(int)) + + +extern PATTERNS def_patterns; + +int Fgis_RasterMin(RASTER_OBJECT handle); + +int Fgis_RasterMax(RASTER_OBJECT handle); + +void Fgis_CloseXEPP(XEPP *file); + +XEPP* Fgis_OpenXEPP(char *filename,EPP *(*openfunc)(char *)); + +XEPP* Fgis_NewXEPP(EPP* file, char *filename); + + +#define FGIS_INVALID_RECLASS ((RECLASS)0x1) +#define MAX_EPP_CLASS 65535 + +/* EXPORT macro to cope with ugly Win32 DDLs */ +#ifdef WIN32 +# if defined(_MSC_VER) +# define EXPORT(a,b) __declspec(dllexport) a b +# define DllEntryPoint DllMain +# else +# if defined(__BORLANDC__) +# define EXPORT(a,b) a _export b +# else +# define EXPORT(a,b) a b +# endif +# endif +#else /* ! WIN32 */ +# define EXPORT(a,b) a b +#endif /* WIN32 */ +#endif diff --git a/dll/fgisMisc.c b/dll/fgisMisc.c new file mode 100644 index 0000000..1056177 --- /dev/null +++ b/dll/fgisMisc.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include "fgis.h" +/* + * Utility functions, I need to program fgis + * Copyright (c) Softweyr, 1997 + */ +/* + * If passed condition is true, puts standard error message, appended + * by msg argument to interp->result. + * Returns cond + * + */ +int Fgis_CkArgs(Tcl_Interp *interp,int cond,char *cmd, char *msg) +{ static char buffer[256]="Wrong # args. Should be "; + if (cond) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp,buffer,cmd," ",msg,NULL); + } + return cond; +} +/* + * Get integer value from command argument and checks it for valid range. + * ARGUMENTS: + * interp: Tcl interpreter to leave error message + * argc, argv - command arguments + * index - position of argument in question in argv + * min, max - range limits + * name - string name of parameter to report errors more clearly + * RETURNS: + * TCL_OK on success, TCL_ERROR on failure + * SIDE EFFECTS: + * Places read integer in location, specified by result + */ + +int Fgis_GetInt(Tcl_Interp *interp,int argc,char **argv,int index, + int min, int max,int *result, char *name) +{ + int tmp;/* Temporary place to hold result */ + char msg[1024]; /* place to format error messages */ + + if (index==argc) { + Tcl_SetResult(interp, "Integer value expected",TCL_STATIC); + return TCL_ERROR; + } + + if (Tcl_GetInt(interp,argv[index],&tmp)!=TCL_OK) + return TCL_ERROR; + if (tmp<=min||tmp>=max) { + sprintf(msg,"Invalid %s: %d. Should be between %d and %d", + name,tmp,min,max); + Tcl_SetResult(interp,msg,TCL_VOLATILE); + return TCL_ERROR; + } + *result=tmp; + return TCL_OK; +} +char *inttostr(long src,char *dest) +{ sprintf(dest,"%ld",src); + return dest; +} + +/* + * Searches for free command name with given prefix and creates command + * with it. Places name of command into interp->result + * Returns TCL_OK on success, TCL_ERROR otherwise + */ +int Fgis_CreateObjectCommand(Tcl_Interp *interp,char *prefix, + Tcl_CmdProc *proc,ClientData data,Tcl_CmdDeleteProc deleteProc) + +{ int num=0; + static char token[30],*numstart; + Tcl_CmdInfo info; + strcpy(token,prefix); + numstart=token+strlen(prefix); + while (1) { + inttostr(num,numstart); + if (Tcl_GetCommandInfo(interp,token,&info)) num++; else break; + } + Tcl_SetResult(interp,token,TCL_VOLATILE); + if (!Tcl_CreateCommand(interp,token,proc,data,deleteProc)) { + (*deleteProc)(data); return TCL_ERROR; + } else { + return TCL_OK; + } +} + + +/* + * Standard TclDeleteProc for commads, which have no ClientData + * Does nothing, successifully + */ +EXPORT(void, Fgis_DefDeleteProc)(ClientData clientdata) +{ +} + +/* + * Fgis_GetLimits - parses four-element list of doubles, putting them + * into four specified global variables + * ARGUMENTS: interp - Tcl interpreter to return error + * list - string to parse + * X1,Y1,X2,Y2 - double variables to put results + * RETURNS: TCL_OK on success, TCL_ERROR otherwise + * SIDE EFFECTS: Fills four double variables + */ +int Fgis_GetLimits(Tcl_Interp *interp,char *list,double *X1,double *Y1, + double *X2,double *Y2) +{ + int no_error;/* Temporary flag, to pass success around Tcl_Free */ + int listc; char **listv; /* for TclSplitList */ + double x1,y1,x2,y2; /* Temporary place for results to avoid overriding if + error occurs */ + + if(Tcl_SplitList(interp,list,&listc,&listv)==TCL_ERROR) + return TCL_ERROR; + if (listc!=4) { + Tcl_SetResult(interp,"Invalid limits list",TCL_STATIC); + Tcl_Free((char *)listv); + return TCL_ERROR; + } + no_error = (Tcl_GetDouble(interp,listv[0],&x1)==TCL_OK) && + (Tcl_GetDouble(interp,listv[1],&y1)==TCL_OK) && + (Tcl_GetDouble(interp,listv[2],&x2)==TCL_OK) && + (Tcl_GetDouble(interp,listv[3],&y2)==TCL_OK); + Tcl_Free((char*)listv); + if (no_error) { + *X1=x1; *Y1=y1; *X2=x2; *Y2=y2; + return TCL_OK; + } else { + return TCL_ERROR; + } +} diff --git a/dll/fgisPalette.c b/dll/fgisPalette.c new file mode 100644 index 0000000..d6e129d --- /dev/null +++ b/dll/fgisPalette.c @@ -0,0 +1,272 @@ +#include +#include +#include +#include +#include "fgis.h" +/* + * fgisclr.c - palette handling for Fgis + * Copyringht (C) by SoftWeyr, 1997 + */ +/* + * Global variables + */ + +/* + *# Default palette array + */ +int defarray[]={ +#include "defpal.h" +}; + +PALETTE default_palette=defarray; +/* + * Creates new palette. Optionally fills from existing palette. If no existing + * palette supplied, all colors will be white + */ + +PALETTE new_palette(PALETTE copy_from) +{ PALETTE new_p= (PALETTE)Tcl_Alloc(256*sizeof(int)); + if (copy_from) { + memcpy(new_p,copy_from,256*sizeof(int)); + } else { + int i,*c; + for (i=0,c=new_p;i<256;i++) + *(c++)=0xffffff; + } + return new_p; +} +/* + * Parses string, containing pallette in EPPL7 file format EPPL7 + */ +PALETTE parse_palette(Tcl_Interp *interp,char *string) +{ PALETTE pal; + int index,r,g,b; + char *start=string,*end, line[80]; + pal=new_palette(default_palette); + /* ASSIGNMENT INSIDE IF */ + while (( end=strchr(start,'\n'))) { + int n=(end-start); + if (n==0) continue; /*won't bother with empty lines */ + if (n>79) n=79; + strncpy(line,start,n); + start=end+1; + if (sscanf(line,"%d %d %d %d",&index,&r,&g,&b)!=4) { + Tcl_Free((char *)pal); + return NULL; + } + if (index>255||index<0) + continue; + pal[index]=(r*255/1000)<<16|(g*255/1000)<<8|(b*255/1000); + } ; + return pal; +} +/* + * Returns index entry of palette in form #RRGGBB + * + */ + + +char *Xcolor_string(PALETTE palette,int index) +{ int value; + static char buffer[24]; + if(index>=0&&index<255) + value=palette[index]; + else + value=palette[255]; + sprintf(buffer,"#%06x",value); + return buffer; +} +/* + * parses RGB specification in form #RRGGBB. + * Returns integer value or 0x1000000 in case of error. + */ +int ParseRGB(Tcl_Interp *interp,char *spec) +{ int val;char *endptr; + val= strtol(spec+1,&endptr,16); + if ((*endptr)||(spec[0]!='#')||(strlen(spec)!=7)) { + Tcl_SetResult(interp,"Only #RRGGBB color specification is supported", + TCL_STATIC); + return 0x1000000; + } + return val; +} +/* + * Implements "palette" fgis command. + * input - argv[1] subcommand, argv[2] parameter, if required. + * subcommands: + * read filename + * parse string + * copy palettename + * blank + * Returns (in interp result) - name of newly created palette + * Side effects: defines new Tcl command to handle this palette + */ +EXPORT(int, Fgis_Palette)(ClientData data,Tcl_Interp *interp,int argc,char **argv) +{ PALETTE pal; + if (argc<2) { + Tcl_SetResult(interp,"Wrong # of args. Should be palette command ?arg?", + TCL_STATIC); return TCL_ERROR; + } + if (!strcmp(argv[1],"read")) { + Tcl_Channel f; /* no comments */ + int size; /* return value from Tcl_Read. its size,yes but used just for + error checking */ + char buf[MAX_PALETTE_SIZE];/* place to hold readed file */ + + if (Fgis_CkArgs(interp,argc!=3,argv[0]," read filename")) return TCL_ERROR; + f=Tcl_OpenFileChannel(interp,argv[2],"r",0666); + if (!f) return TCL_ERROR; + size=Tcl_Read(f,buf,MAX_PALETTE_SIZE); + Tcl_Close(interp,f); + if (size==-1) {return TCL_ERROR;} + if (!(pal=parse_palette(interp,buf))) return TCL_ERROR; + } else if (!strcmp(argv[1],"parse")) { + if (Fgis_CkArgs(interp,argc!=3,argv[0]," parse string")) return TCL_ERROR; + if (!(pal=parse_palette(interp,argv[2]))) { + return TCL_ERROR; + } + } else if (!strcmp(argv[1],"set")) { + int listc,i;char **listv; + if (Fgis_CkArgs(interp,argc!=3,argv[0]," set list")) return TCL_ERROR; + pal=new_palette(default_palette); + if (TCL_ERROR==Tcl_SplitList(interp,argv[2],&listc,&listv)) + return TCL_ERROR; + for (i=0;i>16)*1000/255, + ((clr[i]>>8) & 0xFF)*1000/255, + (clr[i] & 0xff)*1000/255); + Tcl_AppendResult(interp,buffer,NULL); + } + return TCL_OK; + } else + if (!strcmp(argv[1],"get")) { + int index; + if (Fgis_CkArgs(interp,argc!=3,argv[0], + " get index")) + return TCL_ERROR; + if (Tcl_GetInt(interp,argv[2],&index)==TCL_ERROR) return TCL_ERROR; + if (index<0||index>255) { + Tcl_SetResult(interp,"#ffffff",TCL_STATIC); + } else { + Tcl_SetResult(interp,Xcolor_string(clr,index),TCL_VOLATILE); + } + return TCL_OK; + } + else + if (!strcmp(argv[1],"set")) { + int index,RGB; + if (read_only) { + Tcl_AppendResult(interp,argv[0]," is read only",NULL); + return TCL_ERROR; + } + if (Fgis_CkArgs(interp,argc!=4,argv[0], + " set index color")) + return TCL_ERROR; + if (Tcl_GetInt(interp,argv[2],&index)==TCL_ERROR) return TCL_ERROR; + if (index<0||index>255) { + Tcl_SetResult(interp, "Palette index must be from 0 to 255", + TCL_STATIC); + return TCL_ERROR; + } + if ((RGB=ParseRGB(interp,argv[3]))>0xFFFFFF) return TCL_ERROR; + clr[index]=RGB; + return TCL_OK; + } + else + if (!strcmp(argv[1],"list")) { + int i; + if (Fgis_CkArgs(interp,argc!=2,argv[0]," list")) + return TCL_ERROR; + for(i=0;i<256;i++) + { Tcl_AppendElement(interp,Xcolor_string(clr,i)); + } + return TCL_OK; + } + else + if (!strcmp(argv[1],"delete")) { + if (Fgis_CkArgs(interp,argc!=2,argv[0]," delete")) return TCL_ERROR; + if (read_only) { + Tcl_AppendResult(interp,buffer," is read only",NULL); + return TCL_ERROR; + } + Tcl_DeleteCommand(interp,argv[0]); + return TCL_OK; + } + else + { Tcl_SetResult(interp,"Wrong option. Should be one of print, get, set, " + " list, delete", TCL_STATIC); + return TCL_ERROR; + } + return TCL_OK; +} + +EXPORT(void, Fgis_DeletePalette)(ClientData data) +{ + if (data == default_palette) return; + Tcl_Free((char *)data); +} diff --git a/dll/fgisPatterns.c b/dll/fgisPatterns.c new file mode 100644 index 0000000..2f24267 --- /dev/null +++ b/dll/fgisPatterns.c @@ -0,0 +1,402 @@ +#include +#include +#include +#include +#include "fgis.h" +struct { struct PATTERNS* next; + char *name; + int width; + int height; + int bits[1]; + } empty_patterns={NULL,"empty",0,0,{0}}; + +/* WARNING - this is internal function from tkImgBmap.c which is + used here. It might not be exported from tk80.dll on Windows + and might changed in future releases. It is prototyped in + tkInt.h, but I prefer declare it explicitely in order to put this + warning comment here */ +char * TkGetBitmapData(Tcl_Interp *interp, char *string, + char *filename, int *widthPtr, int *heightPtr, + int *hotXPtr, int *hotYPtr); + +PATTERNS def_patterns=(PATTERNS)&empty_patterns; +PATTERNS first_patterns=(PATTERNS)&empty_patterns; + +/* Forward declarations of functions from this file*/ +PATTERNS Fgis_ParsePatterns(Tcl_Interp *interp,char *patterns); +PATTERNS new_patterns(int width,int height,char *name); +void print_patterns(Tcl_Interp *interp,PATTERNS ptn) ; +void make_xbm(Tcl_Interp *interp,int index,PATTERNS data,int width, + int height, int frame); +int parse_xbm(Tcl_Interp *interp,int index,char *data,PATTERNS ptn); + + + +EXPORT(PATTERNS, Fgis_GetPatterns)(Tcl_Interp *interp,char *name) +{ + if (name==NULL||name[0]=='\0') { + return def_patterns; + } else { + Tcl_CmdInfo info;char buffer[255]="Invalid pattern set name: "; + if (!Tcl_GetCommandInfo(interp,name,&info)) return NULL; + if (info.proc!=&Fgis_PatternObj) { + strcat(buffer,name); + Tcl_SetResult(interp,buffer,TCL_VOLATILE); + return NULL; + } + return (PATTERNS)(info.clientData); + } +} +/* + * Implementation of ``patterns'' command + * + */ +EXPORT(int, Fgis_CreatePatterns)(ClientData clientData, Tcl_Interp *interp, int argc, + char **argv) +{ PATTERNS ptn; + if (Fgis_CkArgs(interp,argc<2,argv[0],"command ?arg?")) { + return TCL_ERROR; + } + if (!strcmp(argv[1],"read")) { + FILE *f; + int size; + char *s; + if (Fgis_CkArgs(interp,argc!=3,argv[0],"read filename")) { + return TCL_ERROR; + } + if (!(f=fopen(argv[2],"rb"))) { + Tcl_AppendResult(interp,"Cannot open ",argv[2],": ", + Tcl_PosixError(interp),NULL); + return TCL_ERROR; + } + fseek(f,0,SEEK_END); + size=ftell(f); + fseek(f,0,SEEK_SET); + s=Tcl_Alloc(size+1); + fread(s,1,size,f); + fclose(f); + *(s+size)=0; + if (!(ptn=Fgis_ParsePatterns(interp,s))) { + Tcl_Free(s); + return TCL_ERROR; + } + Tcl_Free(s); + } else if (!strcmp(argv[1],"set")) { + if (Fgis_CkArgs(interp,argc!=3,argv[0],"read string")) { + return TCL_ERROR; + } + if (!(ptn=Fgis_ParsePatterns(interp,argv[2]))) + return TCL_ERROR; + } else if (!strcmp(argv[1],"blank")) { + int sizex,sizey; + if (Fgis_CkArgs(interp,argc<3||argc>4,argv[0],"blank sizex ?sizey?")) { + return TCL_ERROR; + } + if (Tcl_GetInt(interp,argv[2],&sizex)!=TCL_OK) { + return TCL_ERROR; + } + if (argc==4) { + if (Tcl_GetInt(interp,argv[3],&sizey)!=TCL_OK) { + return TCL_ERROR; + } + } else { + sizey=sizex; + } + if (sizex<0||sizex>32||sizey<0||sizey>32) { + Tcl_SetResult(interp,"pattern size should be in range 0 - 32", + TCL_STATIC); + return TCL_ERROR; + } + ptn=new_patterns(sizex,sizey,NULL); + } else if (!strcmp(argv[1],"copy")) { + PATTERNS old; + int size; + if (!(old=Fgis_GetPatterns(interp,argv[2]))) { + return TCL_ERROR; + } + ptn=new_patterns(old->width,old->height,old->name); + memmove(ptn,old,size); + } else { + Tcl_AppendResult(interp,"Wrong option. Should be one of ", + " set, read, copy, blank",NULL); + return TCL_ERROR; + } + return Fgis_CreateObjectCommand(interp,"pattern",Fgis_PatternObj, + (ClientData)ptn,Fgis_DeletePatterns); + +} + +/* + * Deletes pattern + * + */ +EXPORT(void, Fgis_DeletePatterns)(ClientData data) { + PATTERNS ptn=(PATTERNS) data; + if (ptn->name) Tcl_Free(ptn->name); + Tcl_Free((char *)ptn); +} +/* + * Implementation of pattern object command. + * + */ +EXPORT(int, Fgis_PatternObj)(ClientData data,Tcl_Interp *interp, int argc, char **argv) +{ if (Fgis_CkArgs(interp,argc<=1,argv[0],"option ?arg?")) { + return TCL_ERROR; + } + if (!strcmp(argv[1],"print")) { + if (Fgis_CkArgs(interp,argc!=2,argv[0],"print")) + return TCL_ERROR; + print_patterns(interp,(PATTERNS)data); + } else if (!strcmp(argv[1],"set")) { + int index; + if (Fgis_CkArgs(interp,argc!=4,argv[0],"set index dataString")) { + return TCL_ERROR; + } + if (Tcl_GetInt(interp,argv[2],&index)!=TCL_OK) { + return TCL_ERROR; + } + if (index<0||index>255) { + Tcl_SetResult(interp,"pattern index should be in 0..255 range", + TCL_STATIC); + return TCL_ERROR; + } + if (!parse_xbm(interp,index,argv[3],(PATTERNS)data)) { + return TCL_ERROR; + } + } else if (!strcmp(argv[1],"get")) { + int i,index,width,height,frame=0; + if (Fgis_CkArgs(interp,argc<3,argv[0],"index ?-width n? ?-height n? ?-frame bool?")) { + return TCL_ERROR; + } + if (Tcl_GetInt(interp,argv[2],&index)!=TCL_OK) { + return TCL_ERROR; + } + if (index<0||index>255) { + Tcl_SetResult(interp,"pattern index should be in 0..255 range", + TCL_STATIC); + return TCL_ERROR; + } + i=3; + width=((PATTERNS)data)->width; + height=((PATTERNS)data)->height; + while (i3,argv[0],"name ?new name?")) { + return TCL_ERROR; + } + if (argc==3) { + int len; + if (p->name) Tcl_Free(p->name); + len = strlen(argv[2]); + p->name=Tcl_Alloc(len>80?81:len+1); + strncpy(p->name,argv[2],80); + if (len>80) p->name[80]=0; + } + Tcl_SetResult(interp,p->name,TCL_VOLATILE); + } else if (!strcmp(argv[1],"delete")) { + if (Fgis_CkArgs(interp,argc!=2,argv[0],"delete")) return TCL_ERROR; + Tcl_DeleteCommand(interp,argv[0]); + } else { + Tcl_SetResult(interp,"invalid option. Should be one of name, print, get, set, delete",TCL_STATIC); + return TCL_ERROR; + } + return TCL_OK; +} +/* + * Parses string, which looks like content of EPPL symbol file and + * returns PATTERNS structure (or NULL, if there was parsing error) + * + */ +PATTERNS Fgis_ParsePatterns(Tcl_Interp *interp, char *str) { + PATTERNS ptn; + char namebuf[256]=""; + char hex[9] = {0,0,0,0,0,0,0,0,0}; + char *next_line,*p; + char *name; + int block_size,index, old_index; + unsigned int *bitptr; + int width,height; + + Tcl_SetResult(interp,"Invalid pattern file",TCL_STATIC); + if (sscanf(str,"%d %d%[^\n]",&width,&height,namebuf)<=2) { + return NULL; + } + if (width<-32||width>-1||height<-32||height>-1) { + return NULL; + } + width=-width; + height=-height; + name=namebuf+strlen(namebuf)-1; + while (name>=namebuf&&isspace(*name)) name--; + *(++name)=0; + next_line =strchr(str,'\n'); + if (!next_line) return NULL; + name=namebuf; + while(*name&&isspace(*name))name++; + + ptn=new_patterns(width,height,name); + block_size=width<=16?4:8; + while (*next_line&&*(++next_line)) { + while(*next_line&&isspace(*next_line)) next_line++; + if (!*next_line) break; + p=next_line; + index=strtol(next_line,&p,10); + if (!isspace(*p)) { + Fgis_DeletePatterns((ClientData)ptn); + return NULL; + } + p++; + if (index != old_index) { + bitptr=ptn->bits+index*height; + old_index = index; + } + while (*p&&*p!='\n' && *p!='\r') { + strncpy(hex,p,block_size); + p+=block_size; + *(bitptr++)=strtol(hex,NULL,16); + } + next_line=p; + } + Tcl_ResetResult(interp); + return ptn; +} + +PATTERNS new_patterns(int width,int height,char *name) { + PATTERNS p=(PATTERNS)Tcl_Alloc(patternSize(width,height)); + char *name_ptr=NULL; + + if (name && *name) { + name_ptr=Tcl_Alloc(strlen(name)+1); + strcpy(name_ptr,name); + } + p->width=width; + p->height=height; + p->next=NULL; + p->name=name_ptr; + memset(&p->bits,0,sizeof(int)*height*256); + return p; +} +/* + Puts in interp->result printable representation of pattern set + ptn in EPPL symbol file format + */ +void print_patterns(Tcl_Interp *interp,PATTERNS ptn) +{ int i,j,l;char *name=""; + unsigned int *a,*b; + char buffer[256],num[9]; + char *fmt=ptn->width>16?"%08X":"%04X"; + int d=ptn->width>16?8:4; + if (ptn->name) name=ptn->name; + sprintf(buffer,"%3d %3d %s\n",-ptn->width,-ptn->height,name); + Tcl_AppendResult(interp,buffer,NULL); + for (i=0,a=ptn->bits;i<=255;i++,a+=ptn->height) { + /* Check if pattern is empty */ + unsigned int sum=0; + for (j=0,b=a;jheight;j++,b++) sum|=*b; + if (!sum) continue; + /* print pattern */ + sprintf(buffer,"%3d ",i); + for (j=0,l=0,b=a;jheight;j++,b++) { + sprintf(num,fmt,*b); + strcat(buffer,num); + l+=d; + if (l>=64) { + l=0; + Tcl_AppendResult(interp,buffer,"\n",NULL); + buffer[4]=0; + } + } + if (l) Tcl_AppendResult(interp,buffer,"\n",NULL); + } +} +/* + Parses xbm file given by data argiment and replaces by it pattern N + index in pattern set ptn + returns 0 and leaves error message in interp if something goes wrong. +*/ +int parse_xbm(Tcl_Interp *interp,int index,char *data,PATTERNS ptn) { +char *bitmap,*b; +int width,height,hotX,hotY; +int mask, i,j, bm; +unsigned int *p; + bitmap = TkGetBitmapData(interp, data, NULL, &width, &height, + &hotX, &hotY); + if (!bitmap) return 0; + if (width!=ptn->width || height!=ptn->height) { + ckfree(bitmap); + Tcl_SetResult(interp,"bitmap size doesn't match pattern size", + TCL_STATIC); + return 0; + } + b=bitmap; + /*Now copy bitmap data into patterns structure*/ + for (i=0,p=ptn->bits+index*ptn->height;iheight;i++,p++) { + *p=0; + for(j=0,mask=1<<(ptn->width-1), bm=1;jwidth;j++,mask>>=1) { + if (*b&bm) *p|=mask; + bm<<=1; + if (bm>0x80) { + b++; bm=1; + } + } + if (bm!=1) b++; + } + ckfree(bitmap); + return 1; +} +void make_xbm(Tcl_Interp *interp, int index,PATTERNS data,int width, + int height, int frame) +{ char buffer[256]; + int i,j,row,bit; + unsigned int mask, *bitp, current; + int value; + sprintf(buffer,"#define pattern_width %d\n#define pattern_height %d\n" + "static char pattern_bits[] = {\n",width,height); + Tcl_AppendResult(interp,buffer,NULL); + for (i=0,row=33;i=data->height) { + row=0; + bitp=data->bits+(index*(data->height)); + } + current=*bitp; + value=0; + for (j=0,mask=0,bit=1;j>=1) { + if (!mask) { + mask=1<<(data->width-1); + } + if (current & mask) value|=bit; + + if ((bit<<=1)==0x100) { + sprintf(buffer," 0x%02x,",value); + Tcl_AppendResult(interp,buffer,NULL); + bit=1; + value=0; + } + } + if (bit==1) { + Tcl_AppendResult(interp,"\n",NULL); + } else { + sprintf(buffer,"0x%02x,\n",value); + Tcl_AppendResult(interp,buffer,NULL); + } + } + Tcl_AppendResult(interp,"};\n",NULL); +} diff --git a/dll/fgisPlanchet.c b/dll/fgisPlanchet.c new file mode 100644 index 0000000..c194bd4 --- /dev/null +++ b/dll/fgisPlanchet.c @@ -0,0 +1,255 @@ +#include +#include +#include +#include "fgis.h" +/* + * fgisPlanchet.c - coordinate recalculating commands for planchet widget, + * implemented in C + * Copyright (c) by softweyr + */ + +/* internal converting function */ + +/* + * Fills x1 y1 x2 y2 with limits of planchet coordinate system + * Returns TCL_OK on success + */ +int Fgis_GetPlanchetLimits(Tcl_Interp *interp,char *planchet, + double *x1,double *y1,double *x2, double *y2) +{ + char *list; + list=Tcl_GetVar2(interp,planchet,"limits",TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + if (!list) return TCL_ERROR; + return Fgis_GetLimits(interp,list,x1,y1,x2,y2); +} + +int Fgis_GetPlanchetWidth(Tcl_Interp *interp,char *planchet) +{ + Tk_Window p=Tk_NameToWindow(interp,planchet,Tk_MainWindow(interp)); + if (p==NULL) return 0; + + return Tk_ReqWidth(p); +} +int Fgis_GetPlanchetHeight(Tcl_Interp *interp,char *planchet) +{ + + Tk_Window p=Tk_NameToWindow(interp,planchet,Tk_MainWindow(interp)); + if (p==NULL) return 0; + return Tk_ReqHeight(p); +} + + +/* + * Returns alternative (map) x, given planchet x in pixels + * No error checking - fast, for internal use. In case of error returns 0 + * + */ +double Fgis_AltX(Tcl_Interp *interp,char *planchet,int x) +{double X1,Y1,X2,Y2,result; + int width=Fgis_GetPlanchetWidth(interp,planchet); + if (!width||Fgis_GetPlanchetLimits(interp,planchet,&X1,&Y1,&X2,&Y2)==TCL_ERROR) + return 0.0; + result= (x*(X2-X1)/width+X1); + return result; +} + +/* + * Returns alternative (map) y, given planchet y in pixels + * No error checking - fast, for internal use. In case of error returns 0 + * + */ +double Fgis_AltY(Tcl_Interp *interp,char *planchet,int y) +{double X1,Y1,X2,Y2,result; + int height=Fgis_GetPlanchetHeight(interp,planchet); + if (!height||Fgis_GetPlanchetLimits(interp,planchet,&X1,&Y1,&X2,&Y2) + ==TCL_ERROR) + return 0.0; + result= ((height-y)*(Y2-Y1)/height+Y1); + return result; +} + +/* + * Returns planchet x coordinate in pixels, given alternative (map) coordinate + */ +int Fgis_PlanchetX(Tcl_Interp *interp,char *planchet,double x) +{double X1,Y1,X2,Y2; + if (Fgis_GetPlanchetLimits(interp,planchet,&X1,&Y1,&X2,&Y2)==TCL_ERROR) + return 0; + return floor((x-X1)/(X2-X1)*Fgis_GetPlanchetWidth(interp,planchet)); +} + + +/* + * Returns planchet y coordinate in pixels, given alternative (map) coordinate + */ +int Fgis_PlanchetY(Tcl_Interp *interp,char *planchet,double y) +{double X1,Y1,X2,Y2; + if (Fgis_GetPlanchetLimits(interp,planchet,&X1,&Y1,&X2,&Y2)==TCL_ERROR) + return 0; + return floor((y-Y2)/(Y1-Y2)*Fgis_GetPlanchetHeight(interp,planchet)); +} + +/* + * Tcl commands to deal with coordinates. These commands duplicates + * functionality of quick-and-dirty ones above, but adds more error-cheking + * and eliminates duplication in Tk data structures access + */ + +/* + * Tcl command fgisPlanchet_mapx implementation + */ +EXPORT (int, Fgis_MapX)(ClientData data,Tcl_Interp* interp,int argc, char **argv) +{ char result [255]; + int x,width; + double X1,Y1,X2,Y2; + Tk_Window p; + if (argc!=3) { + sprintf(result,"Wrong # args. Should be %s planchet value",argv[0]); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_ERROR; + } + p=Tk_NameToWindow(interp,argv[1],Tk_MainWindow(interp)); + if (!p) return TCL_ERROR; + if (Tk_GetPixels(interp,p,argv[2],&x)==TCL_ERROR) return TCL_ERROR; + if (Fgis_GetPlanchetLimits(interp,argv[1],&X1,&Y1,&X2,&Y2)==TCL_ERROR) + return TCL_ERROR; + width=Tk_ReqWidth(p); + if (width==0) { + sprintf(result,"Planchet %s is not mapped",argv[1]); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_ERROR; + } + Tcl_PrintDouble(interp,(x*(X2-X1)/width+X1),result); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_OK; +} + +/* + * Tcl command fgisPlanchet_mapy implementation + */ +EXPORT(int, Fgis_MapY)(ClientData data,Tcl_Interp* interp,int argc, char **argv) +{ char result [255]; + int y,height; + double X1,Y1,X2,Y2; + Tk_Window p; + if (argc!=3) { + sprintf(result,"Wrong # args. Should be %s planchet value",argv[0]); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_ERROR; + } + p=Tk_NameToWindow(interp,argv[1],Tk_MainWindow(interp)); + if (!p) return TCL_ERROR; + if (Tk_GetPixels(interp,p,argv[2],&y)==TCL_ERROR) return TCL_ERROR; + if (Fgis_GetPlanchetLimits(interp,argv[1],&X1,&Y1,&X2,&Y2)==TCL_ERROR) + return TCL_ERROR; + height=Tk_ReqHeight(p); + if (height==0) { + sprintf(result,"Planchet %s is not mapped",argv[1]); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_ERROR; + } + Tcl_PrintDouble(interp,((height-y)*(Y2-Y1)/height+Y1),result); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_OK; +} + +/* + * Tcl command fgisPlanchet_scrx implementation + */ +EXPORT(int, Fgis_ScrX)(ClientData data,Tcl_Interp* interp,int argc, char **argv) +{ char result [255]; + int width; + double x,X1,Y1,X2,Y2; + Tk_Window p; + if (argc!=3) { + sprintf(result,"Wrong # args. Should be %s planchet value",argv[0]); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_ERROR; + } + p=Tk_NameToWindow(interp,argv[1],Tk_MainWindow(interp)); + if (!p) return TCL_ERROR; + if (Tcl_GetDouble(interp,argv[2],&x)==TCL_ERROR) return TCL_ERROR; + if (Fgis_GetPlanchetLimits(interp,argv[1],&X1,&Y1,&X2,&Y2)==TCL_ERROR) + return TCL_ERROR; + width=Tk_ReqWidth(p); + if (width==0) { + sprintf(result,"Planchet %s is not mapped",argv[1]); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_ERROR; + } + sprintf(result,"%d",(int)floor((x-X1)/(X2-X1)*width)); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_OK; +} + +/* + * Tcl command fgisPlanchet_scry implementation + */ +EXPORT(int, Fgis_ScrY)(ClientData data,Tcl_Interp* interp,int argc, char **argv) +{ char result [255]; + int height; + double y,X1,Y1,X2,Y2; + Tk_Window p; + if (argc!=3) { + sprintf(result,"Wrong # args. Should be %s planchet value",argv[0]); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_ERROR; + } + p=Tk_NameToWindow(interp,argv[1],Tk_MainWindow(interp)); + if (!p) return TCL_ERROR; + if (Tcl_GetDouble(interp,argv[2],&y)==TCL_ERROR) return TCL_ERROR; + if (Fgis_GetPlanchetLimits(interp,argv[1],&X1,&Y1,&X2,&Y2)==TCL_ERROR) + return TCL_ERROR; + height=Tk_ReqHeight(p); + if (height==0) { + sprintf(result,"Planchet %s is not mapped",argv[1]); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_ERROR; + } + sprintf(result,"%d",(int)floor((y-Y2)/(Y1-Y2)*height)); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_OK; +} + +EXPORT(int, Fgis_Fit)(ClientData data,Tcl_Interp* interp,int argc, char **argv) +{ char result [255]; + double xrel,yrel,x,y,X1,Y1,X2,Y2; + if (argc!=4) { + sprintf(result,"Wrong # args. Should be %s planchet x y",argv[0]); + Tcl_SetResult(interp,result,TCL_VOLATILE); + return TCL_ERROR; + } + if (Tcl_GetDouble(interp,argv[2],&x)==TCL_ERROR) return TCL_ERROR; + if (Tcl_GetDouble(interp,argv[3],&y)==TCL_ERROR) return TCL_ERROR; + if (Fgis_GetPlanchetLimits(interp,argv[1],&X1,&Y1,&X2,&Y2)==TCL_ERROR) + return TCL_ERROR; + xrel=(x-X1)/(X2-X1); + yrel=(y-Y1)/(Y2-Y1); + if (yrel>0.0 && yrel<1.0 && xrel>0.0 && yrel<1.0) + Tcl_SetResult(interp,"1",TCL_STATIC); + else + Tcl_SetResult(interp,"0",TCL_STATIC); + return TCL_OK; +} + +/* + * Checks if given window is really planchet and coordinate system + * is defined. returns 0 on failure, 1 on success + */ + +int Fgis_ValidPlanchet(Tcl_Interp *interp,char *planchet) +{ double a; + Tk_Window p=Tk_NameToWindow(interp,planchet,Tk_MainWindow(interp)); + if (!p) return 0; + if (Tk_GetUid("Canvas")!=Tk_Class(p)) { + Tcl_AppendResult(interp,planchet," is not Planchet window",NULL); + return 0; + } + if (Fgis_GetPlanchetLimits(interp,planchet,&a,&a,&a,&a)!=TCL_OK) { + Tcl_AppendResult(interp,planchet," has no coordinate system defined", + NULL); + return 0; + } + return 1; +} + diff --git a/dll/fgisProjection.c b/dll/fgisProjection.c new file mode 100644 index 0000000..9407ecb --- /dev/null +++ b/dll/fgisProjection.c @@ -0,0 +1,25 @@ +#include +#include +#include "fgis.h" + +/* + * fgisProjection - definition for projection handling objects + * Copyright (c) SoftWeyr,1997 + * + */ + + +EXPORT(int, Fgis_ProjectionObj)(ClientData data,Tcl_Interp *interp,int +argc, char **argv) { + return TCL_ERROR; +} + +EXPORT(void,Fgis_DeleteProjection)(ClientData data) { + +} + +EXPORT(int, Fgis_Projection)(ClientData data,Tcl_Interp *interp,int argc, char **argv) +{ + Tcl_SetResult(interp,"Projection objects not implemented",TCL_STATIC); + return TCL_ERROR; +} diff --git a/dll/fgisRaster.c b/dll/fgisRaster.c new file mode 100644 index 0000000..ddd5215 --- /dev/null +++ b/dll/fgisRaster.c @@ -0,0 +1,998 @@ +/* This is an implementation for EPP handling in fgis*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fgis.h" +#include "fgisInt.h" +#include "fgisEppEdit.h" +/* + * Declaration + * + */ + + +int Fgis_CreateNewRaster(ClientData data,Tcl_Interp *interp, + int argc,char **argv); + + +typedef int (Fgis_CmdProc)(RASTER_OBJECT handle,Tcl_Interp *interp, + int argc, char **argv); +Fgis_CmdProc SaveRaster, ReturnBaseRaster, + ReturnCellValue, ReturnLimits, RasterComments, ChangeReclass, + ReturnRow, ReturnCol, DumpReclass, ReturnBPP, OffsiteValue, + XLeft, XRight, YTop, YBottom, + ShiftCoords, ListClasses, CountClass, FindUnused, CalcExtents, + SetRasterCache, GetMinValue, GetMaxValue, CellUnit, + ModifyCell, PlotLine, PlotFrame, PlotBox, PlotContour, FillContour, + PlotCircle, ReturnCell, ReturnCellLimits, + CountContour, CountTranssect; + +RECLASS Fgis_ListToReclass(Tcl_Interp *interp,char *list,RECLASS src,int size); +RECLASS Fgis_ParseReclass(Tcl_Interp *interp,char *program,RECLASS src,int size); + + +int DumpReclassToList(Tcl_Interp *interp,RECLASS reclass,int size); +int DumpReclassToProgram(Tcl_Interp *interp,RASTER_OBJECT handle); +/* + * Cleans up global data, used by raster objects. Probably, should also + * clean up all existing raster objects (?) + */ + +EXPORT(void, Fgis_DeleteRaster)(ClientData table) +{ +} +/* + * parses standard raster options -reclass and -table. + * Returns pointer to reclass on success, NULL if option is not one of these + * and FGIS_INVALID_RECLASS + * if there was error parsing option argument. + */ +RECLASS Fgis_StdRasterOptions(Tcl_Interp *interp, int size, char **arg) +{ RECLASS table; + if (!strcmp(*arg,"-reclass")) { + table=Fgis_ParseReclass(interp,*(arg+1),create_reclass_table(size),size); + } else if (!strcmp(*arg,"-table")) { + table=Fgis_ListToReclass(interp,*(arg+1),create_reclass_table(size),size); + } else return NULL; + if (!table) + return FGIS_INVALID_RECLASS; + else + return table; +} + +/* + * Implements raster Tcl command - various ways to create new raster object + * (deals itself with existing raster files and calls CreateNewRaster for new + * ones. + */ + +EXPORT(int, Fgis_Raster)(ClientData data,Tcl_Interp *interp, + int argc, + char **argv) +{ + RASTER_OBJECT curfile; + XEPP* xptr; + int reclass_size; + EPP *(*openfunc)(char *)=open_epp; + if (Fgis_CkArgs(interp,argc<2,argv[0],"?mode? filename ?options?")) { + return TCL_ERROR; + } + if (!strcmp(argv[1],"load")) { + argc--; + argv++; + openfunc=load_epp; + } else if (!strcmp(argv[1],"new")){ + return Fgis_CreateNewRaster(data,interp,argc-2,argv+2); + } + if (Fgis_CkArgs(interp,argc!=2&&argc!=4,argv[0],"filename ?options?")) { + return TCL_ERROR; + } + /* Open file, or get pointer to existing one */ + xptr=Fgis_OpenXEPP(argv[1],open_epp); + if (!xptr) { + if (map_error==ME_NO_FILE||map_error==ME_CREATE_ERROR) { + Tcl_AppendResult(interp,"Cannot open ",argv[1],": ", + Tcl_PosixError(interp),NULL); + } else { + Tcl_AppendResult(interp,"Invalid epp file:",argv[1],NULL); + } + return TCL_ERROR; + } + /* Create reclass table with size of epp_max, if file is not loaded, + or 1<editable) { + reclass_size=1<<(xptr->e->kind); + } else { + reclass_size=xptr->e->kind==8?256:epp_table_size(xptr->e); + } + + /* Allocate new raster object */ + curfile=malloc(sizeof(struct RASTER_OBJECT)); + curfile->file=xptr; + if (argc>2) { + /* If there is reclass option, parse it */ + curfile->reclass=Fgis_StdRasterOptions(interp,reclass_size,argv+2); + if (!(curfile->reclass)||curfile->reclass==FGIS_INVALID_RECLASS) { + curfile->reclass=NULL; + Fgis_CloseXEPP(curfile->file); + return TCL_ERROR; + } + } else { + /* otherwise create empty reclass */ + curfile->reclass=create_reclass_table(reclass_size); + } + curfile->next=firstobject; + firstobject=curfile; + return Fgis_CreateObjectCommand(interp,"raster",Fgis_RasterObj, + (ClientData)curfile, Fgis_DeleteRasterObj); +} + +/* + * Creates new raster object. returns TCL_ERROR if file already exists + * + */ + +EXPORT(int, Fgis_CreateNewRaster)(ClientData data,Tcl_Interp *interp,int argc, + char **argv) +{ struct stat BUF; + RECLASS table=NULL,t1; + int i,width=0,height=0,offsite=-1,explicit_limits=0; + EPP *e,*pattern=NULL; + XEPP *xptr; + double X1,Y1,X2,Y2; + RASTER_OBJECT object; + int bits=16; + char filename[1024]; + strcpy(filename,argv[1]); + /* checking file existence */ + if (stat(filename,&BUF)||errno!=ENOENT) { + Tcl_AppendResult(interp,"File ",filename," already exists",NULL); + return TCL_ERROR; + } + /* Option parsing loop */ + for(i=0;i255&&offsite!=65535) { + if (table) free(table); + ERROR_MESSAGE("Invalid offsite for 8-bit file",TCL_STATIC); + } + + if(offsite<0) { + if (bits==8) + offsite=255; + else + offsite=65535; + } + if (!pattern) { + if (!width || !height) { + if (table) free(table); + ERROR_MESSAGE("Raster size is not specified",TCL_STATIC); + } + if (!explicit_limits||X1==X2||Y1==Y2) { + X1=0;X2=width;Y1=height;Y2=0; + } + e=creat_epp(filename,1,1,width,height,X1,Y1,X2,Y2,100,0,offsite); + if (!e) { + if (table) free(table); + Tcl_AppendResult(interp,"Error creating file ",filename,":", + Tcl_PosixError(interp),NULL); + return TCL_ERROR; + } + } else { + if (width || height) { + if (table) free(table); + ERROR_MESSAGE("Raster size is specified twice",TCL_STATIC); + } + if (explicit_limits) { + if (table) free(table); + ERROR_MESSAGE("Coordinate system is specified twice",TCL_STATIC); + } + e=creat_epp_as(filename,pattern); + if (!e) { + if (table) free(table); + Tcl_AppendResult(interp,"Error creating file ",filename,":", + Tcl_PosixError(interp),NULL); + return TCL_ERROR; + } + e->offsite=offsite; + } + /* Fill entire raster with offsite value */ + /* And load it into memory to make editable */ + load_new_epp(e); + /* Now create raster object around it */ + xptr=Fgis_NewXEPP(e,filename); + xptr->editable=1; + object=malloc(sizeof (struct RASTER_OBJECT)); + object->file=xptr; + if (!table) { + object->reclass=create_reclass_table(1<kind); + } else { + object->reclass=table; + } + object->next=firstobject; + firstobject=object; + return Fgis_CreateObjectCommand(interp,"raster",Fgis_RasterObj, + (ClientData)object, Fgis_DeleteRasterObj); +} + +/* + * Fgis_GetRaster + * returns pointer to raster object, associated with tcl command + * + * + */ +EXPORT(RASTER_OBJECT, Fgis_GetRaster)(Tcl_Interp *interp, char *name) +{ + Tcl_CmdInfo info;char buffer[255]="Invalid palette: "; + if (!Tcl_GetCommandInfo(interp,name,&info)) return NULL; + if (info.proc!=&Fgis_RasterObj) { + strcat(buffer,name); + Tcl_SetResult(interp,name,TCL_VOLATILE); + return NULL; + } + return (RASTER_OBJECT)(info.clientData); +} + + +/* + * + * Fgis_DeleteRasterObj - deletes raster object, associated with + * command. Called as Tcl_CmdDeleteProc, but not for base rasters. + * + */ + +EXPORT(void, Fgis_DeleteRasterObj)(ClientData data) +{ RASTER_OBJECT r=(RASTER_OBJECT)data; + RASTER_OBJECT prev; + /* Remove it from list */ + if (firstobject==r) { + firstobject=r->next; + } else { + for (prev=firstobject;prev->next!=r;prev=prev->next); + prev->next=r->next; + } + Fgis_CloseXEPP(r->file); + free(r->reclass); + free(r); +} + +/* + * Fgis_RasterObj - implementation of object command for rasters. + * mostly calls some procedure according to first argument. But few commands, + * which returns info of object itself, rather then of raster or reclass, + * are inlined, as well as delete command. + */ +EXPORT(int, Fgis_RasterObj)(ClientData data,Tcl_Interp *interp, int argc, char **argv) +{ + RASTER_OBJECT object=(RASTER_OBJECT)data; + + if (Fgis_CkArgs(interp,argc<2,argv[0], " option ?args?")) + return TCL_ERROR; + + /* Checking for valid options*/ + /* delete */ + if (!strcmp(argv[1],"delete")) { + if (Fgis_CkArgs(interp,argc!=2,argv[0], "delete")) + return TCL_ERROR; + Tcl_DeleteCommand(interp,argv[0]); + return TCL_OK; + /* filename */ + } else if (!strcmp(argv[1],"filename")) { + if (Fgis_CkArgs(interp,argc!=2,argv[0], + " filename")) + return TCL_ERROR; + RETURN(object->file->filename,TCL_VOLATILE); + /*load */ + } else if (!strcmp(argv[1],"cell")) { + return ReturnCell(object,interp,argc,argv); + } else if (!strcmp(argv[1],"save")) { + return SaveRaster(object,interp,argc,argv); + } else if (!strcmp(argv[1],"bpp")) { + return ReturnBPP(object,interp,argc,argv); + } else if (!strcmp(argv[1],"cache")) { + return SetRasterCache(object,interp,argc,argv); + }else if (!strcmp(argv[1],"get")) { + return ReturnCellValue(object,interp,argc,argv); + }else if (!strcmp(argv[1],"limits")) { + return ReturnLimits(object,interp,argc,argv); + }else if (!strcmp(argv[1],"comment")) { + return RasterComments(object,interp,argc,argv); + }else if (!strcmp(argv[1],"reclass")) { + return ChangeReclass(object,interp,argc,argv); + }else if (!strcmp(argv[1],"offsite")) { + return OffsiteValue(object,interp,argc,argv); + }else if (!strcmp(argv[1],"row")) { + return ReturnRow(object,interp,argc,argv); + }else if (!strcmp(argv[1],"col")) { + return ReturnCol(object,interp,argc,argv); + }else if (!strcmp(argv[1],"put")) { + return ModifyCell(object,interp,argc,argv); + }else if (!strcmp(argv[1],"line")) { + return PlotLine(object,interp,argc,argv); + }else if (!strcmp(argv[1],"frame")) { + return PlotFrame(object,interp,argc,argv); + }else if (!strcmp(argv[1],"box")) { + return PlotBox(object,interp,argc,argv); + }else if (!strcmp(argv[1],"fill")) { + return FillContour(object,interp,argc,argv); + }else if (!strcmp(argv[1],"circle")) { + return PlotCircle(object,interp,argc,argv); + }else if (!strcmp(argv[1],"classes")) { + return ListClasses(object,interp,argc,argv); + }else if (!strcmp(argv[1],"count")) { + return CountClass(object,interp,argc,argv); + }else if (!strcmp(argv[1],"unused")) { + return FindUnused(object,interp,argc,argv); + }else if (!strcmp(argv[1],"extents")) { + return CalcExtents(object,interp,argc,argv); + }else if (!strcmp(argv[1],"celllimits")) { + return ReturnCellLimits(object,interp,argc,argv); + }else if (!strcmp(argv[1],"xleft")) { + return XLeft(object,interp,argc,argv); + }else if (!strcmp(argv[1],"xright")) { + return XRight(object,interp,argc,argv); + }else if (!strcmp(argv[1],"ytop")) { + return YTop(object,interp,argc,argv); + }else if (!strcmp(argv[1],"ybottom")) { + return YBottom(object,interp,argc,argv); + }else if (!strcmp(argv[1],"shift")) { + return ShiftCoords(object,interp,argc,argv); + }else if (!strcmp(argv[1],"max")) { + return GetMaxValue(object,interp,argc,argv); + }else if (!strcmp(argv[1],"min")) { + return GetMinValue(object,interp,argc,argv); + }else if (!strcmp(argv[1],"unit")) { + return CellUnit(object,interp,argc,argv); + }else { + Tcl_SetResult(interp,"Invalid option. Should be one of " + "box bpp cache circle classes col comment count delete " + "extents filename fill first_row first_col frame get " + "limits line load max min " + "polygon put reclass row save shift transect unused unit" + "xleft xright ybottom ytop",TCL_STATIC); + return TCL_ERROR; + } +} +int SaveRaster (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) + NOT_YET + + +int ReturnCellValue (RASTER_OBJECT data, Tcl_Interp *interp, int argc, + char **argv) +{ char buffer[10]; + EPP *e=data->file->e; + double X,Y; + int value; + + if (Fgis_CkArgs(interp,(argc != 4&&!(argc==5&&!strcmp(argv[4],"-base"))), + argv[0],"get x y ?-base?")) return TCL_ERROR; + if (Tcl_GetDouble(interp,argv[2],&X)!=TCL_OK) + return TCL_ERROR; + if (Tcl_GetDouble(interp,argv[3],&Y)!=TCL_OK) + return TCL_ERROR; + value= epp_get(e,epp_col(e,X),epp_row(e,Y)); + sprintf(buffer,"%d",argc!=5?data->reclass[value]:value); + RETURN(buffer,TCL_VOLATILE); +} + +int ReturnLimits (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + char buffer[255]; + EPP *e=epp(data); + + if (Fgis_CkArgs(interp,argc!=2,argv[0],"limits")) + return TCL_ERROR; + Tcl_PrintDouble(interp,e->XLeft,buffer); + Tcl_AppendElement(interp,buffer); + Tcl_PrintDouble(interp,e->YBottom,buffer); + Tcl_AppendElement(interp,buffer); + Tcl_PrintDouble(interp,e->XRight,buffer); + Tcl_AppendElement(interp,buffer); + Tcl_PrintDouble(interp,e->YTop,buffer); + Tcl_AppendElement(interp,buffer); + return TCL_OK; +} +int RasterComments (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + + switch (argc) { + case 3: /* set comment */ + if (!data->file->editable) + ERROR_MESSAGE("Raster is read-only.",TCL_STATIC); + setcomment(e,argv[2]); + /* NO BREAK HERE */ + case 2: /* return comment */ + RETURN(getcomment(e),TCL_VOLATILE); + default:{ + Tcl_AppendResult(interp,"Wrong #args. Should be ", + argv[0], " comment ?string?",NULL); + return TCL_ERROR; + } + } +} +int OffsiteValue (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + char result[7]; + int new_offsite; + + switch (argc) { + case 3: /*set new offsite value*/ + if (!data->file->editable); + ERROR_MESSAGE("Raster is read-only",TCL_STATIC); + if (Fgis_GetInt(interp,argc,argv,2,-1, + (1<kind)-1,&new_offsite,"offsite value")!=TCL_OK) + return TCL_ERROR; + if (new_offsite<0) new_offsite=65535; + e->offsite=new_offsite; + /* NO BREAK HERE!!*/ + case 2: /* return offsite value */ + sprintf(result,"%d",data->reclass[e->offsite]); + RETURN(result,TCL_VOLATILE); + default: Tcl_AppendResult(interp, + "Wrong # args. Should be ",argv[0]," offsite ?value?",NULL); + return TCL_ERROR; + } +} + +int CellUnit (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + static char *units[]={"undefined","ft","m","km","mile","ha","acre",NULL}; + EPPHEADER h; + + get_epp_header(e,&h); + if (h.area_unit>6) h.area_unit=0; + if (argc==3) { + char **u; + if (!data->file->editable) + ERROR_MESSAGE("Raster is read-only",TCL_STATIC); + for(u=units;*u&&strcmp(*u,argv[2]);u++); + if (!*u) { + Tcl_SetResult(interp,"Wrong area unit. should be one of: ", + TCL_STATIC); + for(u=units;*u;u++) + Tcl_AppendResult(interp,*u," ",NULL); + return TCL_ERROR; + } + h.area_unit=u-units; + change_epp_header(e,h); + } else if (Fgis_CkArgs(interp,argc!=2,argv[0], + " unit ?new-unit?")) { + return TCL_ERROR; + } + RETURN(units[(int)h.area_unit],TCL_STATIC); +} + +int GetMaxValue (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + char result[255]; + + if (Fgis_CkArgs(interp,argc!=2,argv[0],"max")) + return TCL_ERROR; + sprintf(result,"%d",Fgis_RasterMax(data)); + RETURN(result,TCL_VOLATILE); +} + +int GetMinValue (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + char result[255]; + + if (Fgis_CkArgs(interp,argc!=2,argv[0],"min")) + return TCL_ERROR; + sprintf(result,"%d",Fgis_RasterMin(data)); + RETURN(result,TCL_VOLATILE); +} + +int ReturnBPP (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + if (Fgis_CkArgs(interp,argc!=2,argv[0],"bpp")) + return TCL_ERROR; + RETURN(e->kind==8?"8":"16",TCL_STATIC); +} + +int ReturnCell (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + char result[32]; + if (Fgis_CkArgs(interp,argc!=2&&!(argc==3&&!strcmp(argv[2],"-area")),argv[0], + "cell ?-area?")) + return TCL_ERROR; + if (argc==3) { + Tcl_PrintDouble(interp,e->cell_area,result); + } else { + Tcl_PrintDouble(interp,fabs(e->XRight-e->XLeft)/(e->lc-e->fc),result); + } + RETURN(result,TCL_VOLATILE); +} +int ReturnCellLimits (RASTER_OBJECT data, Tcl_Interp *interp, + int argc, char **argv) +{ + EPP *e=epp(data); + char result[7]; + if (Fgis_CkArgs(interp,argc!=2,argv[0],"celllimits")) + return TCL_ERROR; + sprintf(result,"%d",e->fc); + Tcl_AppendElement(interp,result); + sprintf(result,"%d",e->lr-1); + Tcl_AppendElement(interp,result); + sprintf(result,"%d",e->lc-1); + Tcl_AppendElement(interp,result); + sprintf(result,"%d",e->fr); + Tcl_AppendElement(interp,result); + return TCL_OK; +} + +int XLeft (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + char result[64]; + if (argc==3) { + EPPHEADER h; + double tmp; + + if (!data->file->editable) + ERROR_MESSAGE("Raster is read-only",TCL_STATIC); + if (Tcl_GetDouble(interp,argv[2],&tmp)!=TCL_OK) + return TCL_ERROR; + get_epp_header(e,&h); + h.fcx=tmp; + e->XLeft=tmp; + change_epp_header(e,h); + } else if (argc!=2) { + Tcl_AppendResult(interp,"Wrong # args. Should be", argv[0]," ", + argv[1]," ?value?", NULL); + } + Tcl_PrintDouble(interp,e->XLeft,result); + RETURN(result,TCL_VOLATILE); +} +int XRight (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + char result[64]; + if (argc==3) { + EPPHEADER h; + double tmp; + + if (!data->file->editable) + ERROR_MESSAGE("Raster is read-only",TCL_STATIC); + if (Tcl_GetDouble(interp,argv[2],&tmp)!=TCL_OK) + return TCL_ERROR; + get_epp_header(e,&h); + h.lcx=tmp; + e->XRight=tmp; + change_epp_header(e,h); + } else if (argc!=2) { + Tcl_AppendResult(interp,"Wrong # args. Should be", argv[0]," ", + argv[1]," ?value?", NULL); + } + Tcl_PrintDouble(interp,e->XRight,result); + RETURN(result,TCL_VOLATILE); +} +int YTop (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + char result[64]; + if (argc==3) { + EPPHEADER h; + double tmp; + + if (!data->file->editable) + ERROR_MESSAGE("Raster is read-only",TCL_STATIC); + if (Tcl_GetDouble(interp,argv[2],&tmp)!=TCL_OK) + return TCL_ERROR; + get_epp_header(e,&h); + h.fry=tmp; + e->YTop=tmp; + change_epp_header(e,h); + } else if (argc!=2) { + Tcl_AppendResult(interp,"Wrong # args. Should be", argv[0]," ", + argv[1]," ?value?", NULL); + } + Tcl_PrintDouble(interp,e->YTop,result); + RETURN(result,TCL_VOLATILE); +} +int YBottom (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + char result[64]; + if (argc==3) { + EPPHEADER h; + double tmp; + + if (!data->file->editable) + ERROR_MESSAGE("Raster is read-only",TCL_STATIC); + if (Tcl_GetDouble(interp,argv[2],&tmp)!=TCL_OK) + return TCL_ERROR; + get_epp_header(e,&h); + h.lry=tmp; + e->YBottom=tmp; + change_epp_header(e,h); + } else if (argc!=2) { + Tcl_AppendResult(interp,"Wrong # args. Should be", argv[0]," ", + argv[1]," ?value?", NULL); + } + Tcl_PrintDouble(interp,e->YBottom,result); + RETURN(result,TCL_VOLATILE); +} + +int ShiftCoords (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + EPPHEADER h; + double dx,dy; + if (Fgis_CkArgs(interp,argc!=4,argv[0], "shift dx dy")) { + return TCL_ERROR; + } + + if (!data->file->editable) + ERROR_MESSAGE("Raster is read-only",TCL_STATIC); + if (Tcl_GetDouble(interp,argv[2],&dx)!=TCL_OK) + return TCL_ERROR; + if (Tcl_GetDouble(interp,argv[3],&dy)!=TCL_OK) + return TCL_ERROR; + get_epp_header(e,&h); + h.fcx=e->XLeft+=dx; + h.lcx=e->XRight+=dx; + h.fry=e->YTop+=dy; + h.lry=e->YBottom+=dy; + change_epp_header(e,h); + return TCL_OK; +} + +int ChangeReclass(RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + RECLASS tmp; + EPP *e=epp(data); + if (argc==2) + return DumpReclassToList(interp,data->reclass,epp_table_size(e)); + if (!strcmp(argv[2],"-table")) { + if (Fgis_CkArgs(interp,(argc!=4), argv[0],"reclass -table list")) { + return TCL_ERROR; + } + tmp=Fgis_ListToReclass(interp,argv[3],data->reclass, + epp_table_size(e)); + } else + if (!strcmp(argv[2],"-statements")) { + if (Fgis_CkArgs(interp,argc!=3, argv[0], "reclass -statements")) { + return TCL_ERROR; + } + return DumpReclassToProgram(interp,data); + } else { + if (Fgis_CkArgs(interp,argc!=3, argv[0], " reclass ?option? arg")) { + return TCL_ERROR; + } + tmp=Fgis_ParseReclass(interp,argv[2],data->reclass,epp_table_size(e)); + } + if(!tmp) return TCL_ERROR; + free(data->reclass); + data->reclass=tmp; + return TCL_OK; +} + +int ReturnRow (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + char result[7]; + int row; + double Y; + if (Fgis_CkArgs(interp,argc != 3, argv[0],"row y")) { + return TCL_ERROR; + } + if (Tcl_GetDouble(interp,argv[2],&Y)!=TCL_OK) return TCL_ERROR; + row=epp_row(e,Y); + if (rowfr||row>=e->lr) + ERROR_MESSAGE("Y coordinate outside file boundaries",TCL_STATIC); + sprintf(result,"%d",row); + RETURN(result,TCL_VOLATILE); +} +int ReturnCol (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + EPP *e=epp(data); + char result[7]; + int col; + double X; + if (Fgis_CkArgs(interp,argc != 3,argv[0],"col x")) { + return TCL_ERROR; + } + if (Tcl_GetDouble(interp,argv[2],&X)!=TCL_OK) return TCL_ERROR; + col=epp_col(e,X); + if (colfc||col>=e->lc) + ERROR_MESSAGE("X coordinate outside file boundaries",TCL_STATIC); + sprintf(result,"%d",col); + RETURN(result,TCL_VOLATILE); +} + +int SetRasterCache (RASTER_OBJECT data, Tcl_Interp *interp, int argc, + char **argv) +{ +EPP *e=epp(data); +char result[7]; + +if (Fgis_CkArgs(interp,argc>3,argv[0],"cache ?cache-size?")) { + return TCL_ERROR; +} +if (argc==2) { + if (e->mode&MAP_LOADED) + RETURN("loaded",TCL_STATIC); + /* Otherwise cache size would be returned, as it is done after change */ +} else { + int newsize; + if (e->mode&MAP_LOADED) { + Tcl_AppendResult(interp,argv[0]," already loaded into memory",NULL); + return TCL_ERROR; + } + if (Fgis_GetInt(interp,argc,argv,2,-1,CACHE_THRESHOLD/ + (e->width*(e->kind>>3)), + &newsize,"cache size")!=TCL_OK) return TCL_ERROR; + set_epp_cache(e,newsize); +} +sprintf(result,"%d",e->cache_size); +RETURN(result,TCL_VOLATILE); +} +/* +# $raster put value x y +# modifies raster (if modifiable). Value should be specified in +# terms of base raster, not of current raster object. +# +*/ +int ModifyCell (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ EPP *e=epp(data); + int row,col,value; + double X,Y; + if (Fgis_CkArgs(interp,argc!=5,argv[0]," put value x y")) { + return TCL_ERROR; + } + if (!(e->mode&MAP_LOADED)) { + Tcl_AppendResult(interp,"Raster \"",argv[0],"\" is read-only",NULL); + return TCL_ERROR; + } + if (Tcl_GetInt(interp,argv[2],&value)==TCL_ERROR) { + return TCL_ERROR; + } + if (Tcl_GetDouble(interp,argv[3],&X)==TCL_ERROR) { + return TCL_ERROR; + } + if (Tcl_GetDouble(interp,argv[4],&Y)==TCL_ERROR) { + return TCL_ERROR; + } + if (value<0||value>=MAX_EPP_CLASS) { + Tcl_AppendResult(interp,"Value ",argv[2]," is out of range",NULL); + return TCL_ERROR; + } + row=epp_row(e,Y); + col=epp_col(e,X); + if (rowfr||row>=e->lr||colfc||col>=e->lc) { + Tcl_AppendResult(interp,"Point ",argv[3],",",argv[4]," is out of physical" + " boundaries of file", NULL); + return TCL_ERROR; + } + /* If we have value, which does't fit to 8 */ + if (value>=(1<kind)) { + Tcl_AppendResult(interp,"Value ",argv[2]," doesn't fit into raster ", + argv[0],NULL); + return TCL_ERROR; + } + epp_put(e,col,row,value); + return TCL_OK; +} +int PlotLine (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) + NOT_YET +int PlotFrame (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) + NOT_YET +int PlotBox (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) + NOT_YET +int FillContour (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) + NOT_YET +int PlotCircle (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) + NOT_YET + +int ListClasses (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) +{ + int value,i; + char result[7]; + EPP *e=epp(data); + if( Fgis_CkArgs(interp,argc!=3,argv[0]," classes value")) { + return TCL_ERROR; + } + if (Fgis_GetInt(interp,argc,argv,2,0,65535,&value,"cell value")!=TCL_OK) + return TCL_ERROR; + + for(i=e->min;i<=e->max;i++) + if ((i!=e->offsite)&&(data->reclass[i]==value)) { + sprintf(result,"%d",i); + Tcl_AppendElement(interp,result); + } + return TCL_OK; +} +int CountClass (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) + NOT_YET +int FindUnused (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) + NOT_YET +int CalcExtents (RASTER_OBJECT data, Tcl_Interp *interp, int argc, char **argv) + NOT_YET + +#define LIST_ERROR(msg,mode) { Tcl_Free((char *)listv);free(table);\ + Tcl_SetResult(interp,msg,mode);\ + return NULL;} + +RECLASS Fgis_ListToReclass(Tcl_Interp *interp,char *list,RECLASS src,int size) +{ + int listc,i,index,value; + char **listv; + RECLASS table; + + if (Tcl_SplitList(interp,list,&listc,&listv)!=TCL_OK) + return NULL; + table=memcpy(malloc((size+1)*sizeof(short int)), + src, + (size+1)*sizeof(short int)); + + for(i=0;i=0) + table[index]=value; + } + return table; +} + +unsigned char *reclass_program; + +static int get_prog_char() +{ + return *(reclass_program++); +} + +RECLASS Fgis_ParseReclass(Tcl_Interp *interp,char *program,RECLASS src,int size) +{ + RECLASS table; + reclass_program = (unsigned char *) program; + table=memcpy(malloc((size+1)*sizeof(short int)), + src, + (size+1)*sizeof(short int)); + table = parse_statements(size,table, get_prog_char); + if (!table) { + Tcl_SetResult (interp, "Error in reclass statements", TCL_STATIC); + } + return table; +} + + + +int DumpReclassToList(Tcl_Interp *interp,RECLASS reclass,int size) +{ + int i; + char result[15]; + + for (i=0;i<=size;i++) { + if (reclass[i]!=i) { + sprintf(result,"%d %d",i,reclass[i]); + Tcl_AppendElement(interp,result); + } + } + return TCL_OK; +} +struct STATEMENT {int newclass; + char *list; + int lastclass; + int rangestart; + }; + +char *addtostring(char *source,char separator,int class) +{ + char tmp[10]; + sprintf(tmp,"%c%d",separator,class); + if(!source) + return strcpy(malloc(strlen(tmp)+1),tmp); + else + return strcat(realloc(source,strlen(source)+strlen(tmp)+1),tmp); + +} + +void add_class(struct STATEMENT *stmt,int class) +{ + if (!(stmt->list)) { + stmt->list=addtostring(NULL,'=',class); + stmt->rangestart=stmt->lastclass=class; + } else + if ((stmt->lastclass==class-1)|| + ((class==stmt->newclass+1)&&(stmt->lastclass==class-2))) { + stmt->lastclass=class; + } else { + if (stmt->lastclass!=stmt->rangestart) + stmt->list=addtostring(stmt->list,':',stmt->lastclass); + stmt->list=addtostring(stmt->list,' ',class); + stmt->rangestart=stmt->lastclass=class; + } +} +int DumpReclassToProgram(Tcl_Interp *interp,RASTER_OBJECT data) +{ + int max=Fgis_RasterMax(data)+1,i; + struct STATEMENT *p,*cur; + EPP *e=epp(data); + RECLASS r=data->reclass; + p=malloc(max*sizeof(struct STATEMENT)); + memset(p,0,max*sizeof(struct STATEMENT)); + for(i=0;imax;i++) { + if(i!=e->offsite&&r[i]!=i) + add_class(p+r[i],i); + } + for(i=0,cur=p;ilist) { + char n[7]; + if (cur->lastclass!=cur->rangestart) + cur->list=addtostring(cur->list,':',cur->lastclass); + sprintf(n,"%d",cur->newclass); + Tcl_AppendResult(interp,n,cur->list,"\n",NULL); + free(cur->list); + } + } + free(p); + return TCL_OK; +} diff --git a/dll/fgisVector.c b/dll/fgisVector.c new file mode 100644 index 0000000..c49791c --- /dev/null +++ b/dll/fgisVector.c @@ -0,0 +1,12 @@ + +/* This is an implementation for DGT handling in EP tcl*/ +#include +#include +#include +#include "fgis.h" + +EXPORT(int, Fgis_Vector)(ClientData data,Tcl_Interp *interp,int argc, char **argv) +{ + Tcl_SetResult(interp,"Vector objects not implemented",TCL_STATIC); + return TCL_ERROR; +} diff --git a/dll/patterns.n b/dll/patterns.n new file mode 100644 index 0000000..34870f3 --- /dev/null +++ b/dll/patterns.n @@ -0,0 +1,13 @@ + +patterns set - ÓÏÚÄÁÔØ ÎÁÂÏÒ ÛÔÒÉÈÏ×ÏË ÉÚ ÓÔÒÏËÉ +patterns read - ÐÒÏÞÉÔÁÔØ ÆÁÊÌ ÛÔÒÉÈÏ×ÏË + +patternName print - ×ÙÄÁÔØ ÎÁÂÏÒ ÛÔÒÉÈÏ×ÏË × ×ÉÄÅ, ÐÒÉÅÍÌÅÍÏÍ ÄÌÑ patterns set +patternName get index ?-width n? ?-height n? ?frame -boolean? - ×ÏÚ×ÒÁÝÁÅÔ +ÚÁÄÁÎÎÕÀ ÛÔÒÉÈÏ×ËÕ ËÁË xbm. ðÏ ÕÍÏÌÞÁÎÉÀ Ó ÒÏÄÎÙÍ ÒÁÚÍÅÒÏÍ ÛÔÒÉÈÏ×ËÉ. åÓÌÉ ÚÁÄÁÎÙ width É height, + ÐÒÑÍÏÕÇÏÌØÎÉË ÕËÁÚÁÎÎÏÇÏ ÒÁÚÍÅÒÁ. +patternName set index string + ÉÚÍÅÎÑÅÔ ÕËÁÚÁÎÎÕÀ ÛÔÒÉÈÏ×ËÕ. string ÓÏÄÅÒÖÉÔ ÄÁÎÎÙÅ × xbm ÆÏÒÍÁÔÅ + ÐÒÁ×ÉÌØÎÏÇÏ ÒÁÚÍÅÒÁ + + diff --git a/doc/.log b/doc/.log new file mode 100644 index 0000000..eceff34 --- /dev/null +++ b/doc/.log @@ -0,0 +1,40 @@ +This is TeX, Version 3.14159 (C version 6.1) (format=latex 96.11.10) 29 JAN 1998 13:46 +**epu_doc +(/usr/lib/texmf/texmf/tex/latex/tools/.tex +! Interruption. +l.1 + %% +? +LaTeX2e <1996/06/01> +File ignored) +*\bye +! Undefined control sequence. +<*> \bye + +? + +*\end +! Interruption. +<*> + \end +? + +*\end +! TeX capacity exceeded, sorry [parameter stack size=60]. +\end #1-> + \csname end#1\endcsname \@checkend {#1}\expandafter \endgroup \if@e... +<*> \end + +If you really absolutely need more capacity, +you can ask a wizard to enlarge me. + + +Here is how much of TeX's memory you used: + 4 strings out of 10942 + 52 string characters out of 72781 + 40742 words of memory out of 262141 + 2948 multiletter control sequences out of 9500 + 3640 words of font info for 14 fonts, out of 150000 for 255 + 14 hyphenation exceptions out of 607 + 60i,0n,61p,82b,7s stack positions out of 300i,40n,60p,3000b,4000s +No pages of output. diff --git a/doc/3rd.attempt b/doc/3rd.attempt new file mode 100644 index 0000000..0258900 --- /dev/null +++ b/doc/3rd.attempt @@ -0,0 +1,282 @@ + +÷ ÄÁÎÎÏÍ ÔÅËÓÔÅ ÐÒÅÄÌÁÇÁÅÔÓÑ ÎÏ×ÙÊ ÐÏÄÈÏÄ Ë ÐÒÅÄÓÔÁ×ÌÅÎÉÀ +ÐÒÏÓÔÒÁÎÓÔ×ÅÎÎÏÊ ÉÎÆÏÒÍÁÃÉÉ. ïÎ ÎÅ ÓÏ×ÓÅÍ ÎÏ×ÙÊ. íÎÏÇÉÅ ÓÕÝÅÓÔ×ÕÀÝÉÅ +çéó, ÏÓÏÂÅÎÎÏ ÏÒÉÅÎÔÉÒÏ×ÁÎÎÙÅ ÎÁ ÏÂÒÁÂÏÔËÕ ÓÎÉÍËÏ×, ÎÅÑ×ÎÏ ÉÓÐÏÌØÚÕÀÔ +ÅÇÏ. îÏ ÎÉËÔÏ ÅÝÅ ÎÅ ÐÙÔÁÌÓÑ × Ñ×ÎÏÍ ×ÉÄÅ ÓÆÏÒÍÕÌÉÒÏ×ÁÔØ ÅÇÏ É ÐÏËÁÚÁÔØ +ÅÇÏ ÄÏÓÔÁÔÏÞÎÏÓÔØ ÄÌÑ ÂÏÌØÛÉÎÓÔ×Á çéó-ÚÁÄÁÞ. + +1. ïÐÒÅÄÅÌÅÎÉÅ + îÁÚÏ×ÅÍ ËÁÒÔÏÊ ÆÕÎËÃÉÀ ÏÔ ËÏÏÒÄÉÎÁÔ, ÏÐÒÅÄÅÌÅÎÎÕÀ ÎÁ ÎÅËÏÔÏÒÏÍ + ÐÏÄÍÎÏÖÅÓÔ×Å ÐÏ×ÅÒÈÎÏÓÔÉ ÚÅÍÎÏÇÏ ÛÁÒÁ É ÐÒÉÎÉÍÁÀÝÕÀ ÌÉÂÏ ÞÉÓÌÏ×ÙÅ + (×ÅÝÅÓÔ×ÅÎÎÙÅ) ÚÎÁÞÅÎÉÑ, ÌÉÂÏ ÚÎÁÞÅÎÉÑ ÉÚ ËÁËÏÇÏ-ÔÏ ËÏÎÅÞÎÏÇÏ ÍÎÏÖÅÓÔ×Á. + + ðÏÞÅÍÕ ÜÔÏÇÏ ÄÏÓÔÁÔÏÞÎÏ? + 1. ïÂÌÁÓÔØ ÏÐÒÅÄÅÌÅÎÉÑ ÍÏÖÅÔ ÂÙÔØ ÌÉÂÏ ÎÅÐÒÅÒÙ×ÎÙÍ ÕÞÁÓÔËÏÍ ÔÅÒÒÉÔÏÒÉÉ, + ÅÓÌÉ ÎÁÓ ÉÎÔÅÒÅÓÕÅÔ ÆÅÎÏÍÅÎ, ÉÍÅÀÝÉÊ ÐÌÏÝÁÄÎÕÀ ÐÒÉÒÏÄÕ, + ÌÉÂÏ ÍÎÏÖÅÓÔ×ÏÍ ÌÉÎÉÊ (ÄÏÒÏÖÎÁÑ ÓÅÔØ, ÒÅÞÎÁÑ ÓÅÔØ), ÌÉÂÏ ËÏÎÅÞÎÙÍ +ÍÎÏÖÅÓÔ×ÏÍ ÉÚÏÌÉÒÏ×ÁÎÎÙÈ ÔÏÞÅË (ÎÁÓÅÌÅÎÎÙÅ ÐÕÎËÔÙ, ÔÏÞËÉ ÏÐÒÏÂÏ×ÁÎÉÑ). + + ïÞÅ×ÉÄÎÏ, ÞÔÏ ×ÓÅ ÓÕÝÅÓÔ×ÕÀÝÉÅ ÓÐÏÓÏÂÙ ËÁÒÔÏÇÒÁÆÉÞÅÓËÏÇÏ ÉÚÏÂÒÁÖÅÎÉÑ + ÐÏÚ×ÏÌÑÀÔ ÉÚÏÂÒÁÚÉÔØ ÏÂßÅËÔÙ, ÏÔÎÏÓÑÝÉÅÓÑ Ë ÏÄÎÏÊ ÉÚ ÔÒÅÈ ÜÔÉÈ ÇÒÕÐÐ. + + 2. ìÀÂÏÊ ÐÁÒÁÍÅÔÒ, ËÏÔÏÒÙÊ ÍÙ ÍÏÖÅÍ ÉÚÏÂÒÁÚÉÔØ ÎÁ ËÁÒÔÅ, ÌÉÂÏ + ËÏÌÉÞÅÓÔ×ÅÎÎÙÊ, ÌÉÂÏ ËÁËÉÍ-ÔÏ ÏÂÒÁÚÏÍ ËÌÁÓÓÉÆÉÃÉÒÏ×ÁÎ. åÓÌÉ ÍÙ ÒÁÓÓÍÏÔÒÉÍ + ËÌÁÓÓÉÆÉËÁÃÉÀ ËÁË ËÏÎÅÞÎÏÅ ÍÎÏÖÅÓÔ×Ï ËÌÁÓÓÏ×, ÔÏ ÓÔÁÎÅÔ ÏÞÅ×ÉÄÎÏ, ÞÔÏ + ×ÓÅ ËÁÒÔÙ ËÁÞÅÓÔ×ÅÎÎÙÈ ÐÒÉÚÎÁËÏ× (ÐÏÞ×ÅÎÎÙÅ, ÒÁÓÔÉÔÅÌØÎÙÅ É ÄÁÖÅ ÁÄÍÉÎÉÓÔÒÁ- + ÔÉ×ÎÏÅ ÒÁÊÏÎÉÒÏ×ÁÎÉÅ) ÐÏÐÁÄÁÀÔ ÐÏÄ ÎÁÛÅ ÏÐÒÅÄÅÌÅÎÉÅ. + +åÄÉÎÓÔ×ÅÎÎÏÅ × ÎÁÛÅÍ ÏÐÒÅÄÅÌÅÎÉÉ, ÞÔÏ ÍÏÖÅÔ ×ÏÚÍÕÔÉÔØ ÞÅÌÏ×ÅËÁ, ÐÒÉ×ÙËÛÅÇÏ +ÒÁÂÏÔÁÔØ Ó ÂÕÍÁÖÎÙÍÉ ËÁÒÔÁÍÉ, ÜÔÏ ÔÏ, ÞÔÏ ÍÙ ÐÏÚ×ÏÌÑÅÍ ËÁÒÔÅ ÉÚÏÂÒÁÖÁÔØ ÔÏÌØËÏ +ÏÄÉÎ ÐÏËÁÚÁÔÅÌØ, × ÔÏ ×ÒÅÍÑ ËÁË ÎÁ ÂÕÍÁÖÎÙÈ ËÁÒÔÁÈ ÏÂÙÞÎÏ ÏÄÎÏ×ÒÅÍÅÎÎÏ +ÉÚÏÂÒÁÖÁÅÔÓÑ ÎÅÓËÏÌØËÏ ÔÅÍÁÔÉÞÅÓËÉ ÓÈÏÄÎÙÈ ÐÏËÁÚÁÔÅÌÅÊ, ÎÅ ÓÞÉÔÁÑ +ÏÂÝÅÇÅÏÇÒÁÆÉÞÅÓËÏÊ ÓÉÔÕÁÃÉÉ. + +íÙ ÎÁÍÅÒÅÎÎÏ ÉÄÅÍ ÎÁ ÜÔÏ ÏÇÒÁÎÉÞÅÎÉÅ, ÐÏÓËÏÌØËÕ ÏÎÏ ÏÂÌÅÇÞÁÅÔ ÄÁÌØÎÅÊÛÕÀ +ÒÁÂÏÔÕ Ó ËÁÒÔÁÍÉ. òÁÚÄÅÌÉ× ËÁÖÄÕÀ ÉÓÈÏÄÎÕÀ ËÁÒÔÕ ÎÁ ÎÅÓËÏÌØËÏ ÓÌÏÅ×, +ËÁÖÄÙÊ ÉÚ ËÏÔÏÒÙÈ ÏÔ×ÅÞÁÅÔ ÔÏÌØËÏ ÚÁ ÏÄÉÎ ÐÏËÁÚÁÔÅÌØ, ÍÙ ÐÏÌÕÞÁÅÍ ÐÏÌÎÕÀ +Ó×ÏÂÏÄÕ ÐÒÉ ÐÏÓÔÒÏÅÎÉÉ ÐÒÏÉÚ×ÏÄÎÙÈ ËÁÒÔ. íÙ ÍÏÖÅÍ ÉÓÐÏÌØÚÏ×ÁÔØ ÐÒÉ +ÁÎÁÌÉÚÅ ÌÀÂÙÅ ÐÏËÁÚÁÔÅÌÉ, ÎÅ ÏÂÒÁÝÁÑ ×ÎÉÍÁÎÉÅ ÎÁ ÔÏ, ËÁËÉÍ ÐÕÔÅÍ +ÜÔÁ ÉÎÆÏÒÍÁÃÉÑ ÐÏÌÕÞÅÎÁ. ÷ÓÅ ËÁÒÔÙ Õ ÎÁÓ ÎÅÚÁ×ÉÓÉÍÙ É ÒÁ×ÎÏÐÒÁ×ÎÙ. + +2. ôÏÞÎÏÓÔØ ËÁÒÔÙ. + +ìÀÂÁÑ ÉÎÆÏÒÍÁÃÉÑ Ï ÒÅÁÌØÎÏ ÓÕÝÅÓÔ×ÕÀÝÉÈ ÏÂßÅËÔÁÈ ÉÍÅÅÔ ÏÇÒÁÎÉÞÅÎÎÕÀ ÔÏÞÎÏÓÔØ. +ðÏÜÔÏÍÕ ÎÕÖÎÏ ××ÅÓÔÉ ÓÐÏÓÏ ÏÃÅÎËÉ ÔÏÞÎÏÓÔÉ ËÁÒÔ. +õ ÐÒÏÂÌÅÍÙ ÔÏÞÎÏÓÔÉ ËÁÒÔÙ ÅÓÔØ Ä×Å ÓÔÏÒÏÎÙ: + 1. ôÏÞÎÏÓÔØ ÏÐÒÅÄÅÌÅÎÉÑ ËÏÏÒÄÉÎÁÔ + 2. ôÏÞÎÏÓÔØ ÉÎÆÏÒÍÁÃÉÉ Ï ÚÎÁÞÅÎÉÉ ËÁÒÔÙ. + +ôÏÞÎÏÓÔØ ÏÐÒÅÄÅÌÅÎÉÑ ËÏÏÒÄÉÎÁÔ ÜË×É×ÁÌÅÎÔÎÁ ÔÏÞÎÏÓÔÉ ÐÒÏ×ÅÄÅÎÉÑ +ËÏÎÔÕÒÏ× ÉÓÈÏÄÎÏÊ ËÁÒÔÙ É ÏÂÙÞÎÏ ÎÅ ÐÒÅ×ÙÛÁÅÔ 1-2 ÍÍ × ÍÁÓÛÔÁÂÅ ÉÓÈÏÄÎÏÊ +ËÁÒÔÙ. ïÐÒÅÄÅÌÅÎÎÙÅ ÐÏÇÒÅÛÎÏÓÔÉ ×ÎÏÓÉÔ É ××ÏÄ ËÁÒÔ × ÍÁÛÉÎÕ, ÎÏ ÏÎÉ +ÏÂÙÞÎÏ ÎÁ ÐÏÒÑÄÏË ÍÅÎØÛÅ. + +÷ ËÁÞÅÓÔ×Å ÏÃÅÎËÉ ËÏÏÒÄÉÎÁÔÎÏÊ ÔÏÞÎÏÓÔÉ ËÁÒÔÙ ÍÙ ÂÕÄÅÍ ÉÓÐÏÌØÚÏ×ÁÔØ +ÐÒÏÓÔÒÁÎÓÔ×ÅÎÎÏÅ ÒÁÚÒÅÛÅÎÉÅ. üÔÏ ÍÉÎÉÍÁÌØÎÏÅ ÒÁÓÓÔÏÑÎÉÅ ÍÅÖÄÕ ÔÏÞËÁÍÉ +× ËÏÔÏÒÙÈ ËÁÒÔÁ ÍÏÖÅÔ ÉÍÅÔØ ÒÁÚÌÉÞÎÙÅ ÚÎÁÞÅÎÉÅ. ôÅ ËÏÍÕ ÐÒÉÈÏÄÉÌÏÓØ +ÒÁÂÏÔÁÔØ Ó ÏÔÓËÁÎÉÒÏ×ÁÎÎÙÍÉ ÉÚÏÂÒÁÖÅÎÉÑÍÉ ÓÒÁÚÕ ÚÁÍÅÔÑÔ ÓÈÏÄÓÔ×Ï +ÜÔÏÇÏ ÐÏÎÑÔÉÑ Ó ÒÁÚÒÅÛÅÎÉÅÍ ÒÁÓÔÒÏ×ÏÇÏ ÉÚÏÂÒÁÖÅÎÉÑ. üÔÏ ÄÅÊÔÓ×ÉÔÅÌØÎÏ +ÏÄÎÏ É ÔÏ ÖÅ ÐÏÎÑÔÉÅ, ÐÏÓËÏÌØËÕ ÄÌÑ ÈÒÁÎÅÎÉÑ ËÁÒÔ ÉÓÐÏÌØÚÕÅÔÓÑ ÒÁÓÔÒÏ×ÙÊ +ÆÏÒÍÁÔ. + +þÔÏ ËÁÓÁÅÔÓÑ ÔÏÞÎÏÓÔÉ ÚÎÁÞÎÅÎÉÊ, ÔÏ ÔÕÔ ×ÏÐÒÏÓ ÂÏÌÅÅ ÓÌÏÖÎÙÊ. +äÁÔØ ÆÏÒÍÁÌÉÚÏ×ÁÎÎÕÀ ÏÃÅÎËÕ ÔÏÞÎÏÓÔÉ ËÌÁÓÓÉÆÉËÁÃÉÉ ÎÅÌØÚÑ, ÅÓÌÉ ÔÏÌØËÏ +ÜÔÁ ËÌÁÓÓÉÆÉËÁÃÉÑ ÎÅ ÐÏÌÕÞÅÎÁ × ÒÅÚÕÌØÔÁÔÅ ËÁËÏÇÏ-ÌÉÂÏ ÓÔÁÔÉÓÔÉÞÅÓËÏÇÏ +ÍÅÔÏÄÁ. + +ôÅÏÒÉÑ ÔÏÞÎÏÓÔÉ ÉÚÍÅÒÅÎÉÊ ËÏÌÉÞÅÓÔ×ÅÎÎÙÈ ÐÏËÁÚÁÔÅÌÅÊ É ÔÏÞÎÏÓÔÉ +ÉÎÔÅÒÐÏÌÑÃÉÉ, ÎÁÐÒÏÔÉ×, ÈÏÒÏÛÏ ÒÁÚÒÁÂÏÔÁÎÁ. + +ëÒÏÍÅ ÔÏÇÏ ÓÕÝÅÓÔ×ÕÅÔ ÔÏÞÎÏÓÔØ ÐÒÅÄÓÔÁ×ÌÅÎÉÑ ÞÉÓÅÌ × ËÏÍÐØÀÔÅÒÅ. + +ðÏÜÔÏÍÕ ÄÌÑ ËÁÒÔ ËÏÌÉÞÅÓÔ×ÅÎÎÙÈ ÐÁÒÁÍÅÔÒÏ× ËÒÏÍÅ ÒÁÚÒÅÛÅÎÉÑ ÉÓÐÏÌØÚÕÅÔÓÑ +ÐÏÎÑÔÉÅ Z-ÔÏÞÎÏÓÔÉ - ÍÉÎÉÍÁÌØÎÁÑ ÒÁÚÎÉÃÁ ÍÅÖÄÕ ÚÎÁÞÅÎÉÑÍÉ ËÁÒÔÙ, +ÐÒÉ ËÏÔÏÒÙÈ ÜÔÉ ÚÎÁÞÅÎÉÑ ÓÞÉÔÁÀÔÓÑ ÎÅÒÁ×ÎÙÍÉ. Z-ÔÏÞÎÏÓÔØ ÜÔÏ + +3. çÄÅ ÖÅ ËÏÎÔÕÒ? + +÷Ï ×ÓÅÍ ×ÙÛÅÉÚÌÏÖÅÎÎÏÍ ÞÅÌÏ×ÅË ÐÒÉ×ÙËÛÉÊ ÒÁÂÏÔÁÔØ Ó ËÁÒÔÁÍÉ ÎÅ ÎÁÊÄÅÔ +ÏÄÎÏÇÏ ×ÁÖÎÏÇÏ ÐÏÎÑÔÉÑ --- ËÏÎÔÕÒÁ. åÇÏ ÚÄÅÓØ ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÎÅÔ. + +ëÏÎÔÕÒ ÜÔÏ Ó×ÑÚÎÏÅ ÍÎÏÖÅÓÔ×Ï ÔÏÞÅË, × ËÏÔÏÒÙÈ ËÁÒÔÁ ÉÍÅÅÔ ÏÄÉÎÁËÏ×ÏÅ ÚÎÁÞÅÎÉÅ. +åÓÌÉ ÍÙ ÒÁÓÓÍÏÔÒÉÍ ËÁÒÔÕ ËÏÌÉÞÅÓÔ×ÅÎÎÏÇÏ ÐÏËÁÚÁÔÅÌÑ, ËÏÔÏÒÁÑ ÏÂÙÞÎÏ +ÉÚÏÂÒÁÖÁÅÔÓÑ Ó ÐÏÍÏÝØÀ ÐÏÓÌÏÊÎÏÊ ÒÁÓËÒÁÓËÉ, ÔÏ ÍÙ Õ×ÉÄÉÍ, ÞÔÏ +ËÏÎÔÕÒ ÚÄÅÓØ - ÏÂÌÁÓÔØ × ËÏÔÏÒÏÊ ÚÎÁÞÅÎÉÑ ÐÏËÁÚÁÔÅÌÑ ÚÁËÌÀÞÅÎÙ × ÏÐÒÅÄÅÌÅÎÎÏÍ +ÉÎÔÅÒ×ÁÌÅ - ÏÔ ÏÄÎÏÊ ÉÚÏÌÉÎÉÉ ÄÏ ÓÏÓÅÄÎÅÊ. åÓÌÉ ÍÙ ÉÚÍÅÎÉÍ ÇÒÁÎÉÃÙ +ÉÎÔÅÒ×ÁÌÏ×, ÉÚÍÅÎÉÔÓÑ É ×ÓÑ ËÏÎÔÕÒÎÁÑ ÓÅÔØ, ÈÏÔÑ ÓÁÍÁ ËÁÒÔÁ, ÔÏ ÅÓÔØ +ÐÒÏÓÔÒÁÎÓÔ×ÅÎÎÏÅ ÒÁÓÐÒÅÄÅÌÅÎÉÅ ÚÎÁÞÅÎÉÊ ÐÏËÁÚÁÔÅÌÑ, ÏÓÔÁÌÁÓØ ÐÒÅÖÎÅÊ. + +äÌÑ ËÁÒÔ ËÌÁÓÓÉÆÉËÁÃÉÊ ËÏÎÔÕÒ --- ×ÅÝØ ÂÏÌÅÅ ÕÓÔÏÊÞÉ×ÁÑ. ïÎ ÍÏÖÅÔ +ÉÚÍÅÎÉÔØÓÑ ÅÓÌÉ ÐÏ ËÁËÉÍ-ÔÏ ÐÒÉÞÉÎÁÍ ÉÚÍÅÎÉÔÓÑ ËÌÁÓÓÉÆÉËÁÃÉÑ ÌÉÂÏ +ÎÁÛÉ ÚÎÁÎÉÑ Ï ÔÅÒÒÉÔÏÒÉÉ. + +ðÏÜÔÏÍÕ ÄÌÑ ÜÔÉÈ ËÁÒÔ ×ÏÚÍÏÖÎÁ ÒÁÂÏÔÁ ÎÁ ÕÒÏ×ÎÅ ËÏÎÔÕÒÏ×. ÷ ÏÓÎÏ×ÎÏÍ +ÏÐÅÒÁÃÉÉ Ó ËÏÎÔÕÒÁÍÉ ÜÔÏ ÉÈ ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÏÅ ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ, ËÏÔÏÒÏÅ +Ó ÔÏÞËÉ ÚÒÅÎÉÑ ÆÕÎËÃÉÏÎÁÌØÎÏÊ ËÁÒÔÙ ÏÚÎÁÞÁÅÔ: ÍÙ ×ÙÄÅÌÑÅÍ ËÁËÕÀ-ÔÏ ÇÒÕÐÐÕ +ÔÏÞÅË (ÎÁÐÒÉÍÅÒ, ÎÁÒÉÓÏ×Á× ÚÁÍËÎÕÔÕÀ ÌÉÎÉÀ) É ÇÏ×ÏÒÉÍ: ÚÎÁÞÅÎÉÅ ËÁÒÔÙ +× ÜÔÉÈ ÔÏÞËÁÈ ÔÅÐÅÒØ ÂÕÄÅÔ ÔÁËÏÅ-ÔÏ. + +ïÞÅ×ÉÄÎÏ, ÜÔÏÊ ÏÐÅÒÁÃÉÅÊ ÎÁÄÏ ÐÏÌØÚÏ×ÁÔØÓÑ Ó ÏÓÔÏÒÏÖÎÏÓÔØÀ, ÏÓÔÁ×É× +ÅÇÏ ÄÌÑ ÜÔÁÐÏ× ÐÅÒ×ÉÞÎÏÇÏ ××ÏÄÁ ÉÎÆÏÒÍÁÃÉÉ É ÅÅ ÏÂÎÏ×ÌÅÎÉÑ. + +4. ïÐÅÒÁÃÉÉ Ó ËÁÒÔÁÍÉ. + +ôÅÐÅÒØ ÐÅÒÅÊÄÅÍ Ë ÔÏÍÕ, ÄÌÑ ÞÅÇÏ ×ÓÅ ÜÔÏ ÚÁÔÅ×ÁÌÏÓØ - Ë ÏÐÅÒÁÃÉÑÍ ÁÎÁÌÉÚÁ +ËÁÒÔ. + +éÈ ÍÏÖÎÏ ÓÒÁÚÕ ÒÁÚÄÅÌÉÔØ ÎÁ Ä×Å ÂÏÌØÛÉÅ ÇÒÕÐÐÙ: +1) ëÏÇÄÁ ÎÁÍ × ÒÅÚÕÌØÔÁÔÅ ÎÕÖÎÏ ÐÏÌÕÞÉÔØ ËÁÒÔÕ +2) ëÏÇÄÁ × ÒÅÚÕÌØÔÁÔÅ ÍÙ ÐÏÌÕÞÁÅÍ ËÁËÕÀ-ÔÏ ÓÕÍÍÁÒÎÕÀ ÉÎÆÏÒÍÁÃÉÀ + (ÏÂÙÞÎÏ × ÆÏÒÍÅ ÔÁÂÌÉÃÙ). + +ïÇÒÁÎÉÞÉÍÓÑ ÐÏËÁ ÐÅÒ×ÏÊ ÇÒÕÐÐÏÊ ÏÐÅÒÁÃÉÊ. + +1. úÁÞÁÓÔÕÀ, ÞÔÏÂÙ ÐÏÌÕÞÉÔØ ÉÎÔÅÒÅÓÕÀÝÉÊ ÎÁÓ ÐÏËÁÚÁÔÅÌØ × ËÁËÏÊ-ÔÏ +ÔÏÞËÅ, ÎÁÍ +ÄÏÓÔÁÔÏÞÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÔÏÌØËÏ ÚÎÁÞÅÎÉÑ ÎÅËÏÔÏÒÙÈ ÄÒÕÇÉÈ ÐÏËÁÚÁÔÅÌÅÊ +× ÔÏÊ ÖÅ ÔÏÞËÅ. + +îÁÐÒÉÍÅÒ, ÄÌÑ ÒÁÓÞÅÔÁ ÐÏÔÅÎÃÉÁÌØÎÏÊ ÜÒÏÚÉÉ ÎÁÍ ÎÕÖÎÙ Ó×ÅÄÅÎÉÑ Ï +ÍÅÈÁÎÉÞÅÓËÏÍ ÓÏÓÔÁ×Å ÐÏÞ×, ÕËÌÏÎÁÈ, ÄÌÉÎÅ ÓËÌÏÎÏ×, ÎÁÐÏÞ×ÅÎÎÏÍ ÐÏËÒÏ×Å +É Ô.Ä. åÓÌÉ ×ÓÅ ÜÔÉ ÄÁÎÎÙÅ ÅÓÔØ Õ ÎÁÓ × ×ÉÄÅ ËÁÒÔ, ÔÏ ÐÒÉÍÅÎÉ× +ÉÚ×ÅÓÔÎÏÅ ÕÒÁ×ÎÅÎÉÅ Ë ËÁÖÄÏÊ ÔÏÞËÅ ÔÅÒÒÉÔÏÒÉÉ, ÍÙ ÐÏÌÕÞÉÍ ÎÏ×ÕÀ ËÁÒÔÕ. + +ôÒÁÄÉÃÉÏÎÎÏ × ÄÌÑ ÜÔÏÇÏ ÓÎÁÞÁÌÁ ÎÁËÌÁÄÙ×ÁÀÔ ÄÒÕÇ ÎÁ ÄÒÕÇÁ ×ÓÅ ÉÓÈÏÄÎÙÅ +ËÁÒÔÙ É ÐÏÌÕÞÁÀÔ ÓÅÔËÕ ÍÉÎÉÍÁÌØÎÙÈ ËÏÎÔÕÒÏ×, × ËÏÔÏÒÙÈ ×ÓÅ ÉÓÈÏÄÎÙÅ +ÐÏËÁÚÁÔÅÌÉ ÏÄÎÏÒÏÄÎÙ, Á ÐÏÔÏÍ ÄÌÑ ËÁÖÄÏÇÏ ÔÁËÏÇÏ ËÏÎÔÕÒÁ ÒÁÓÞÉÔÙ×ÁÀÔ +ÉÔÏÇÏ×ÙÊ ÐÏËÁÚÁÔÅÌØ. + +åÓÌÉ ÖÅ ÍÙ ×ÙÐÏÌÎÉÍ ÒÁÓÓÞÅÔ ÄÌÑ ËÁÖÄÏÊ ÔÏÞËÉ ËÁÒÔÙ (Á ÉÈ ËÏÎÅÞÎÏÅ ÞÉÓÌÏ, +ÐÏÓËÏÌØËÕ ×ÓÅ ÉÓÈÏÄÎÙÅ ËÁÒÔÙ ÉÍÅÀÔ ËÏÎÅÞÎÏÅ ÒÁÚÒÅÛÅÎÉÅ), ÔÏ +ÉÔÏÇÏ×ÙÅ ËÏÎÔÕÒÁ ÏÂÒÁÚÕÀÔÓÑ ÓÁÍÉ, ËÁË ÇÒÕÐÐÙ ÔÏÞÅË ÇÄÅ ×ÙÞÉÓÌÅÎÎÙÊ +ÐÏËÁÚÁÔÅÌØ ÉÍÅÅÔ ÏÄÉÎÁËÏ×ÙÅ ÚÎÁÞÅÎÉÑ. + +íÁÔÅÍÁÔÉÞÅÓËÉ ÜÔÏ ÏÐÉÓÙ×ÁÅÔÓÑ ÐÏÎÑÔÉÅÍ ÆÕÎËÃÉÏÎÁÌÁ - ÏÐÅÒÁÃÉÉ, +ËÏÔÏÒÁÑ ÐÏ ÎÅÓËÏÌØËÉÍ ÉÓÈÏÄÎÙÍ ÆÕÎËÃÉÑÍ ÓÔÒÏÉÔ ÒÅÚÕÌØÔÉÒÕÀÝÕÀ. + +ó ÐÒÁËÔÉÞÅÓËÏÊ ÔÏÞËÉ ÚÒÅÎÉÑ ÐÒÏ×ÅÓÔÉ ×ÙÞÉÓÌÅÎÉÑ × ÎÅÓËÏÌØËÉÈ ÍÉÌÌÉÏÎÁÈ +ÔÏÞÅË ÇÏÒÁÚÄÏ ÂÙÓÔÒÅÅ, ÞÅÍ ×ÙÞÉÓÌÑÔØ ÐÅÒÅÓÅÞÅÎÉÑ ÓÏÔÅÎ ËÏÎÔÕÒÏ×. + +2. éÎÏÇÄÁ ÄÌÑ ×ÙÞÉÓÌÅÎÉÑ ÚÎÁÞÅÎÉÑ ÐÏËÁÚÁÔÅÌÑ × ÔÏÞËÅ ÎÁÍ ÎÕÖÎÁ + ÉÎÆÏÒÍÁÃÉÑ Ï ÎÅËÏÔÏÒÏÊ ÏËÒÅÓÔÎÏÓÔÉ ÜÔÏÊ ÔÏÞËÅ (ÔÅÏÒÅÔÉÞÅÓËÉ - +× ÂÅÓËÏÎÅÞÎÏ ÍÁÌÏÊ, ÎÁ ÐÒÁËÔÉËÅ - ÎÅ ÍÅÎØÛÅ ÒÁÚÒÅÛÅÎÉÑ ËÁÒÔÙ) +ëÌÁÓÓÉÞÅÓËÉÊ ÐÒÉÍÅÒ ÔÁËÏÊ ÚÁÄÁÞÉ - ÎÁÈÏÖÄÅÎÉÅ ÕËÌÏÎÏ× ÐÏ +ÇÉÐÓÏÍÅÔÒÉÞÅÓËÏÊ ËÁÒÔÅ. äÒÕÇÏÊ, ÓÔÏÌØ ÖÅ ÈÁÒÁËÔÅÒÎÙÊ ÐÒÉÍÅÒ - ÔÅËÓÔÕÒÁ +ÉÚÏÂÒÁÖÅÎÉÑ ÎÁ ÁÜÒÏÆÏÔÏÓÎÉÍËÅ. + +3. é, ÎÁËÏÎÅÃ, ÉÎÏÇÄÁ ÎÁÍ ÎÕÖÎÙ ÕÄÁÌÅÎÎÙÅ ÔÏÞËÉ, ÏÂÌÁÄÁÀÝÉÅ +ÏÐÒÅÄÅÌÅÎÎÙÍÉ Ó×ÏÊÓÔ×ÁÍÉ. îÁÐÒÉÍÅÒ, ×Ï ÍÎÏÇÉÈ ÚÁÄÁÞÁÈ ÒÁÚÍÅÝÅÎÉÑ +ÎÁÓ ÉÎÔÅÒÅÓÕÅÔ ÒÁÓÓÔÏÑÎÉÅ ÄÏ ÂÌÉÖÁÊÛÅÊ ÄÏÒÏÇÉ, ÐÒÉ ÐÏÓÔÒÏÅÎÉÉ +ËÁÒÔ ÈÉÍÉÞÅÓËÏÇÏ ÓÏÓÔÁ×Á ÎÁÓ ÉÎÔÅÒÅÓÕÀÔ ÎÅÓËÏÌØËÏ ÂÌÉÖÁÊÛÉÈ ÔÏÞÅË +ÏÐÒÏÂÏ×ÏÁÎÉÑ. + +éÎÔÅÒÅÓÎÏÊ ÔÅÍÏÊ ÄÌÑ ÉÓÓÌÅÄÏ×ÁÎÉÑ Ñ×ÌÑÅÔÓÑ ×ÏÚÍÏÖÎÏÓÔØ ËÏÍÐÏÚÉÃÉÉ +ÆÕÎËÃÉÏÎÁÌÏ×, ÐÏÓËÏÌØËÕ ÒÁÂÏÔÁ Ó ËÏÍÐÏÚÉÃÉÑÍÉ ÆÕÎËÃÉÏÎÁÌÏ× +ÐÏÚ×ÏÌÑÅÔ ÓÞÉÔÁÔØ ÓÌÏÖÎÙÅ ÍÏÄÅÌÉ ÚÁ ÏÄÉÎ ÐÒÏÈÏÄ, ÂÅÚ ÓÏÚÄÁÎÉÑ +ÓÌÏÖÎÙÈ ÐÒÏÍÅÖÕÔÏÞÎÙÈ ËÁÒÔ. + +ïÞÅ×ÉÄÎÏ, Ë ÏÐÅÒÁÃÉÑÍ 1-Ê ÇÒÕÐÐÙ ËÏÍÐÏÚÉÃÉÑ ÐÒÉÍÅÎÉÍÁ ×ÓÅÇÄÁ +z=f(g(x)) ÐÏÓÞÉÔÁÔØ ÎÅ ÓÌÏÖÎÅÅ ÞÅÍ y=g(x) z=f(y). + +óÌÏÖÎÅÅ Ó ÏÐÅÒÁÃÉÑÍÉ ×ÔÏÒÏÊ ÇÒÕÐÐÙ, ÐÏÓËÏÌØËÕ ÅÓÌÉ × ×ÙÞÉÓÌÅÎÉÉ +f(x) ÕÞÁÓÔ×ÕÀÔ ÚÎÁÞÅÎÉÑ g(x+dx) ÉÈ ÎÁÄÏ ×ÙÞÉÓÌÉÔØ ÚÁÒÁÎÅÅ, Á ÅÓÌÉ +É ÏÎÉ ÔÒÅÂÕÀÔ ÏËÒÅÓÔÎÏÓÔÉ... óÒÁ×ÎÉÔÅ, ÎÁÐÒÉÍÅÒ, Ó ÆÏÒÍÕÌÏÊ ×ÔÏÒÏÊ +ÐÒÏÉÚ×ÏÄÎÏÊ ÓÌÏÖÎÏÊ ÆÕÎËÃÉÉ. + +åÓÌÉ ÖÅ ÒÅÞØ ÉÄÅÔ Ï ÎÅÌÏËÁÌØÎÙÈ ÏÐÅÒÁÃÉÑÈ, ÔÁËÉÈ ËÁË ÂÕÆÅÒÉÚÁÃÉÑ +É ÉÎÔÅÒÐÏÌÑÃÉÑ, ÂÅÚ ÓÏÈÒÁÎÅÎÉÑ ÐÒÏÍÅÖÕÔÏÞÎÙÈ ÒÅÚÕÌØÔÁÔÏ× × ×ÉÄÅ +ËÁÒÔ ×ÉÄÉÍÏ ÎÅ ÏÂÏÊÔÉÓØ. + + +÷ÉÚÕÁÌÉÚÁÃÉÑ ËÁÒÔ É ÍÅÔÁÄÁÎÎÙÅ. + +äÁÔØ ÓÔÒÏÇÏÅ ÍÁÔÅÍÁÔÉÞÅÓËÏÅ ÏÐÒÅÄÅÌÅÎÉÅ ËÁÒÔÙ ËÏÎÅÞÎÏ ÈÏÒÏÛÏ, ÎÏ +ÉÓÓÌÅÄÏ×ÁÔÅÌÉ ÐÒÉ×ÙËÌÉ ×ÉÄÅÔØ ËÁÒÔÕ ÐÅÒÅÄ ÇÌÁÚÁÍÉ. + +üÔÏ ËÁË ÒÁÚ ÔÏ, ÞÅÇÏ ÎÅ ÐÏÚ×ÏÌÑÀÔ ÓÕÝÅÓÔ×ÕÀÝÉÅ çéó. ÷ ÎÉÈ ÓÏÚÄÁÎÉÅ +ËÁÒÔÏÇÒÁÆÉÞÅÓËÏÊ ËÏÍÐÏÚÉÃÉÉ ÎÁ ÜËÒÁÎÅ ÉÌÉ ÎÁ ÂÕÍÁÇÅ - ÄÌÉÔÅÌØÎÙÊ +É ÓÌÏÖÎÙÊ ÐÒÏÃÅÓÓ, ÓÏ×ÅÒÛÅÎÎÏ ÎÅ Ó×ÑÚÁÎÎÙÊ Ó ÓÏÂÓÔ×ÅÎÎÏ ÐÒÏÓÔÒÁÎÓÔ×ÅÎÎÙÍ +ÁÎÁÌÉÚÏÍ É ÍÏÄÅÌÉÒÏ×ÁÎÉÅÍ. + +äÁ, ÓÔÁÄÉÑ ÄÉÚÁÊÎÁ ÎÅÏÂÈÏÄÉÍÁ, ËÏÇÄÁ ×Ù ÇÏÔÏ×ÉÔÅ ËÁÒÔÕ ÄÌÑ ÐÕÂÌÉËÁÃÉÉ, +ÎÏ ×ÏÚÍÏÖÎÏÓÔØ ÂÙÓÔÒÏ Õ×ÉÄÅÔØ ÒÅÚÕÌØÔÁÔ ËÁËÏÊ-ÔÏ ÏÐÅÒÁÃÉÉ × ÂÏÌÅÅ +ÍÅÎÅÅ ÁÄÅË×ÁÔÎÙÈ ËÁÒÔÏÇÒÁÆÉÞÅÓËÉÈ ÚÎÁËÁÈ ÍÏÖÅÔ ÉÚÂÁ×ÉÔØ ÏÔ ÍÎÏÖÅÓÔ×Á +ÏÛÉÂÏË. + +æÕÎËÃÉÏÎÁÌØÎÙÅ ËÁÒÔÙ ÍÏÇÕÔ ÐÏÍÏÞØ É ÚÄÅÓØ. +ðÏÓËÏÌØËÕ ËÁÖÄÁÑ ËÁÒÔÁ Õ ÎÁÓ ÏÔÏÂÒÁÖÁÅÔ ÒÏ×ÎÏ ÏÄÉÎ ÐÏËÁÚÁÔÅÌØ, +ÍÙ ÍÏÖÅÍ Ó×ÑÚÁÔØ ÓÐÏÓÏ ËÁÒÔÏÇÒÁÆÉÞÅÓËÏÇÏ ÉÚÏÂÒÁÖÅÎÉÑ ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÏ +Ó ÍÎÏÖÅÓÔ×ÏÍ ÚÎÁÞÅÎÉÊ ËÁÒÔÙ. (×Ï ÍÎÏÇÉÈ ÏÂÌÁÓÔÑÈ ÎÁÕË Ï ÚÅÍÌÅ ÜÔÏ +ÕÖÅ É ÔÁË ÓÄÅÌÁÎÏ - ÓÕÝÅÓÔ×ÕÀÔ ÓÔÁÎÄÁÒÔÎÙÅ Ã×ÅÔÁ ÄÌÑ ÔÉÐÏ× ÐÏÞ× ÉÌÉ +ÇÅÏÈÒÏÎÏÌÏÇÉÞÅÓËÉÈ ÜÐÏÈ). + +ðÏÓÌÅ ÜÔÏÇÏ, ÐÏÓÔÒÏÉ× ËÁÒÔÕ ÍÙ ÍÏÖÅÍ ÎÅÍÅÄÌÅÎÎÏ ÅÅ ÉÚÏÂÒÁÚÉÔØ × +ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÈ ÕÓÌÏ×ÎÙÈ ÚÎÁËÁÈ, Á ÚÁÄÁÞÁ ÄÉÚÁÊÎÁ ËÁÒÔÏÇÒÁÆÉÞÅÓËÏÊ +ËÏÍÐÏÚÉÃÉÉ ÒÁÓÐÁÄÁÅÔÓÑ ÎÁ ÓÏÚÄÁÎÉÅ ÎÁÂÏÒÁ ÚÎÁËÏ× ÄÌÑ ËÁÖÄÏÇÏ +ÐÏËÁÚÁÔÅÌÑ É ÉÚÏÂÒÁÖÅÎÉÅ ÎÁ ÏÄÎÏÍ ÌÉÓÔÅ ÔÅÈ ÓÌÏÅ×, ËÏÔÏÒÙÅ ÔÅÍÁÔÉÞÅÓËÉ +ÉÎÔÅÒÅÓÎÏ ÒÁÓÓÍÁÔÒÉ×ÁÔØ ×ÍÅÓÔÅ, ÔÁË , ÞÔÏÂÙ ÏÎÉ ÎÅ ÍÅÛÁÌÉ ÄÒÕÇ ÄÒÕÇÕ. + +íÁÓÛÔÁÂÎÙÊ ÒÑÄ ÉÌÉ ÉÅÒÁÒÈÉÑ ÒÅÇÉÏÎÏ×. + +äÁÌÅËÏ ÎÅ ×ÓÅÇÄÁ ÒÁÂÏÔÁ Ó ËÁÒÔÁÍÉ Ó×ÏÄÉÔÓÑ Ë ÒÁÂÏÔÅ Ó ÏÄÎÏÊ É ÔÏÊ ÖÅ +ÔÅÒÒÉÔÏÒÉÅÊ. äÏÓÔÁÔÏÞÎÏ ÞÁÓÔÏ ÐÒÉÈÏÄÉÔÓÑ ÉÍÅÔØ ÄÅÌÏ Ó ÉÅÒÁÒÈÉÅÊ +ÍÁÓÛÔÁÂÏ× É ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÊ ÅÊ ÉÅÒÁÒÈÉÅÊ ÔÅÒÒÉÔÏÒÉÊ. + +ðÒÉ ÜÔÏÍ ÉÓÐÏÌØÚÕÅÍÙÅ ËÁÒÔÏÇÒÁÆÉÞÅÓËÉÅ ÐÒÏÅËÃÉÉ É ËÌÁÓÓÉÆÉËÁÃÉÉ +ËÁÞÅÓÔ×ÅÎÎÙÈ ÐÏËÁÚÁÔÅÌÅÊ (ÐÏÞ×, ÒÁÓÔÉÔÅÌØÎÏÓÔÉ É Ô.Ä.) ÚÁËÏÎÏÍÅÒÎÏ +ÍÅÎÑÀÔÓÑ Ó ÉÚÍÅÎÅÎÅÍ ÍÁÓÛÔÁÂÁ. + +äÁÌÅËÏ ÎÅ ×ÓÅÇÄÁ ÎÁ ÎÕÖÎÏÍ ÍÁÓÛÔÁÂÎÏÍ ÕÒÏ×ÎÅ ÅÓÔØ ×ÓÑ ÎÅÏÂÈÏÄÉÍÁÑ +ÉÎÆÏÒÍÁÃÉÑ. ðÏÜÔÏÍÕ ÞÁÓÔÏ ×ÏÚÎÉËÁÅÔ ÚÁÄÁÞÁ ÌÉÂÏ ÓÏÂÒÁÔØ ËÁÒÔÕ +ÉÚ ÂÏÌÅÅ ËÒÕÐÎÏÍÁÓÛÔÁÂÎÙÈ ËÕÓËÏ×, Ó ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÊ ÇÅÎÅÒÁÌÉÚÁÃÉÅÊ, +ÌÉÂÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÆÒÁÇÍÅÎÔ ÂÏÌÅÅ ÍÅÌËÏÍÁÓÛÔÁÂÎÏÊ ËÁÒÔÙ. ðÏÔÅÒÑ ÔÏÞÎÏÓÔÉ +ÔÕÔ ÎÅÉÚÂÅÖÎÁ, ÎÏ ÞÁÓÔÏ ÌÕÞÛÅ ÎÅÔÏÞÎÙÅ ÄÁÎÎÙÅ, ÞÅÍ ÎÉËÁËÉÈ. + +ðÏÜÔÏÍÕ ÍÙ ××ÏÄÉÍ ËÏÎÃÅÐÃÉÀ ÒÅÇÉÏÎÁ. òÅÇÉÏÎ ÜÔÏ ÇÒÕÐÐÁ ËÁÒÔ ÎÁ ÏÄÎÕ +É ÔÕ ÖÅ ÔÅÒÒÉÔÏÒÉÀ. ÷ÓÅ ËÁÒÔÙ ÒÅÇÉÏÎÁ ÉÍÅÀÔ ÏÄÎÕ É ÔÕ ÖÅ ËÏÏÒÄÉÎÁÔÎÕÀ +ÓÉÓÔÅÍÕ (ËÁÒÔÏÇÒÁÆÉÞÅÓËÕÀ ÐÒÏÅËÃÉÀ) ÎÏ ÍÏÇÕÔ ÒÁÚÌÉÞÁÔØÓÑ ÐÏ ÒÁÚÒÅÛÅÎÉÀ. +ðÏÓÌÅÄÎÅÅ ÎÅ ÍÅÛÁÅÔ ÓÏ×ÍÅÓÔÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÉÈ × ÁÎÁÌÉÚÅ. +äÌÑ ÔÏÇÏ ÞÔÏÂÙ ÉÓÐÏÌØÚÏ×ÁÔØ ËÁÒÔÕ ÉÚ ÄÒÕÇÏÇÏ ÒÅÇÉÏÎÁ ×ÍÅÓÔÅ Ó ËÁÒÔÁÍÉ +ÔÅËÕÝÅÇÏ, ÅÅ ÎÁÄÏ ÓËÏÐÉÒÏ×ÁÔØ × ÜÔÏÔ ÒÅÇÉÏÎ. ðÒÉ ÜÔÏÍ ÏÎÁ ÂÕÄÅÔ +Á×ÔÏÍÁÔÉÞÅÓËÉ ÐÒÅÏÂÒÁÚÏ×ÁÎÁ × ÎÕÖÎÕÀ ÐÒÏÅËÃÉÀ, ÎÏ ÓÏÈÒÁÎÉÔ Ó×ÏÅ ÏÒÉÇÉÎÁÌØÎÏÅ +ÒÁÚÒÅÛÅÎÉÅ É ÌÅÇÅÎÄÕ. åÅ ÇÅÎÅÒÁÌÉÚÁÃÉÑ (ÕÍÅÎØÛÅÎÉÅ ÒÁÚÒÅÛÅÎÉÑ) É +ÐÅÒÅËÌÁÓÓÉÆÉËÁÃÉÑ ÌÅÇÅÎÄÙ - ÄÅÌÏ ÐÏÌØÚÏ×ÁÔÅÌÑ. + +òÅÇÉÏÎÙ ÉÍÅÀÔ ÉÅÒÁÒÈÉÞÅÓËÕÀ ÓÉÓÔÅÍÕ ÓÏÐÏÄÞÉÎÅÎÉÑ. ðÏËÁÖÅÍ, ÞÔÏ ÜÔÏ +ÔÁËÏÅ ÎÁ ÐÒÉÍÅÒÅ ÁÄÍÉÎÉÓÔÒÁÔÉ×ÎÏÇÏ ÄÅÌÅÎÉÑ òÏÓÓÉÉ. + +òÅÇÉÏÎ ×ÅÒÈÎÅÇÏ ÕÒÏ×ÎÑ - òÏÓÓÉÑ × ÃÅÌÏÍ. èÁÒÁËÔÅÒÎÏÅ ÒÁÚÒÅÛÅÎÉÅ 1-2ËÍ, + ÐÒÏÅËÃÉÑ ÓËÏÒÅÅ ×ÓÅÇÏ ËÏÎÉÞÅÓËÁÑ. +÷ ÜÔÏÔ ÒÅÇÉÏÎ ×ÈÏÄÑÔ 86 ÐÏÄÒÅÇÉÏÎÏ× - ÁÄÍÉÎÉÓÔÒÁÔÉ×ÎÙÈ ÏÂÌÁÓÔÅÊ. +òÁÚÒÅÛÅÎÉÅ × ÎÉÈ ÏÔ 500 ÄÏ 100 Í, Á ÐÒÏÅËÃÉÑ ÍÏÖÅÔ ÂÙÔØ ËÏÎÉÞÅÓËÏÊ, +ËÏÓÏÊ ÁÚÉÍÕÔÁÌØÎÏÊ ÉÌÉ UTM(çÁÕÓÓÁ), × ÚÁ×ÉÓÉÍÏÓÔÉ ÏÔ ÒÁÚÍÅÒÏ× ÏÂÌÁÓÔÉ. + +åÓÌÉ ÄÅÌÅÎÉÅ ÏÄÎÏÇÏ ÒÅÇÉÏÎÁ ÓÒÁÚÕ ÎÁ 86 ÞÁÓÔÅÊ ËÁÖÅÔÓÑ ÓÌÉÛËÏÍ ÍÅÌËÉÍ, +ÍÏÖÎÏ ××ÅÓÔÉ ÐÒÏÍÅÖÕÔÏÞÎÙÊ ÕÒÏ×ÅÎØ ÜËÏÎÏÍÉÞÅÓËÉÈ ÒÁÊÏÎÏ×. + +ëÁÖÄÁÑ ÏÂÌÁÓÔØ ÓÏÓÔÏÉÔ ÉÚ ÒÁÊÏÎÏ×. ðÒÉ ÎÁÌÉÞÉÉ ÉÓÈÏÄÎÙÈ ÄÁÎÎÙÈ +ÍÏÖÎÏ ××ÅÓÔÉ ÅÝÅ É ÐÏÄÒÅÇÉÏÎÙ ÄÌÑ ÒÁÊÏÎÏ× - ÏÔÄÅÌØÎÙÅ ÈÏÚÑÊÓÔ×Á Ó +ÒÁÚÒÅÛÅÎÉÅÍ ÐÏÒÑÄËÁ ÍÅÔÒÏ× (ÍÁÓÛÔÁ 1:5000 - 1:10000) + +óÉÓÔÅÍÁ ÐÏÚ×ÏÌÑÅÔ ÐÅÒÅÊÔÉ ÎÁ ÓÏÓÅÄÎÉÊ ÕÒÏ×ÅÎØ × ÜÔÏÊ ÉÅÒÁÒÈÉÉ - ÌÉÂÏ +ÐÏÄÎÑÔØÓÑ ××ÅÒÈ × ÏÂßÅÍÌÀÝÉÊ ÒÅÇÉÏÎ, ÌÉÂÏ, ×ÙÂÒÁ× ÎÕÖÎÙÊ ÐÏÄÒÅÇÉÏÎ +ÎÁ ÓÐÅÃÉÁÌØÎÏÊ ËÁÒÔÅ (× ÄÁÎÎÏÍ ÓÌÕÞÁÅ ÁÄÍÉÎÉÓÔÒÁÔÉ×ÎÏÊ) ÐÅÒÅÊÔÉ +× ÎÅÇÏ. + +ðÒÉ ËÏÐÉÒÏ×ÁÎÉÉ ËÁÒÔÙ Ó ÎÉÖÎÅÇÏ ÕÒÏ×ÎÑ ÎÁ ×ÅÒÈÎÉÊ, ÏÎÁ ËÏÐÉÒÕÅÔÓÑ +ÃÅÌÉËÏÍ, Á ×ÏÔ ÐÒÉ ÏÂÒÁÔÎÏÍ ËÏÐÉÒÏ×ÁÎÉÉ ×ÏÚÎÉËÁÅÔ ÚÁÄÁÞÁ ×ÙÒÅÚÁÎÉÑ +ÎÕÖÎÏÇÏ ËÕÓËÁ. ïÄÉÎ ÉÚ ×ÏÚÍÏÖÎÙÈ ÐÕÔÅÊ ÅÅ ÒÅÛÅÎÉÑ - ÉÍÅÔØ × ËÁÖÄÏÍ +ÒÅÇÉÏÎÅ ÓÐÅÃÉÁÌØÎÕÀ ËÁÒÔÕ (×ÉÄÉÍÏ, ÔÕ ÖÅ, ËÏÔÏÒÁÑ ÉÓÐÏÌØÚÕÅÔÓÑ ÄÌÑ +ÐÏÉÓËÁ ÓÕÂÒÅÇÉÏÎÏ×), ÏÂÌÁÓÔØ ÏÐÒÅÄÅÌÅÎÉÑ ËÏÔÏÒÏÊ ÓÏ×ÐÁÄÁÅÔ ÓÏ ×ÓÅÊ +ÔÅÒÒÉÔÏÒÉÅÊ ÒÅÇÉÏÎÁ, É ÐÏÌØÚÏ×ÁÔØÓÑ ÅÊ ËÁË ÍÁÓËÏÊ. + +ðÒÉÎÃÉÐÙ ÐÏÓÔÒÏÅÎÉÑ ÓÉÓÔÅÍÙ + +óÉÓÔÅÍÁ ÓÔÒÏÉÔÓÑ ×ÏËÒÕÇ ×ØÀÅÒÁ/ÒÅÄÁËÔÏÒÁ ËÁÒÔ. +üÔÏÔ ×ØÀÅÒ/ÒÅÄÁËÔÏÒ ÕÍÅÅÔ ×Ù×ÏÄÉÔØ ËÁÒÔÙ ÂÏÌÅÅ-ÍÅÎÅÅ ×ÓÅÍÉ +ÓÕÝÅÓÔ×ÕÀÝÉÍÉ ÓÐÏÓÏÂÁÍÉ ËÁÒÔÏÇÒÁÆÉÞÅÓËÏÇÏ ÉÚÏÂÒÁÖÅÎÉÑ, × ÔÏÍ ÞÉÓÌÅ +ÎÁÐÒÉÍÅÒ ÓÌÏÊ ÛÔÒÉÈÏ×ËÁÍÉ ÐÏ×ÅÒÈ ÓÌÏÑ Ã×ÅÔÏ×. + +ïÔËÒÙÔØ ÄÌÑ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ × ËÁÖÄÙÊ ËÏÎËÒÅÔÎÙÊ ÍÏÍÅÎÔ ÍÏÖÎÏ ÔÏÌØËÏ ÏÄÉÎ +ÓÌÏÊ. + +ðÒÉ ÔÙËÁÎØÅ ÍÙÛØÀ × ÏËÏÎ ËÁÒÔÙ ÏÂÙÞÎÏ × ËÁËÏÍ-ÔÏ ÄÒÕÇÏÍ ÏËÎÅ +ÐÏËÁÚÙ×ÁÅÔÓÑ ÚÎÁÞÅÎÉÅ ÐÏ ÎÅËÏÔÏÒÙÍ ×ÙÂÒÁÎÎÙÍ ËÁÒÔÁÍ (×ÓÅ ×ÉÄÉÍÙÅ + +ÔÅ ËÏÔÏÒÙÅ ÐÏÌØÚÏ×ÁÔÅÌØ ÕËÁÚÁÌ Ñ×ÎÏ) × ÜÔÏÊ ÔÏÞËÅ. + +íÅÎÀ ÓÉÓÔÅÍÙ ÐÏÚ×ÏÌÑÅÔ ×ÙÐÏÌÎÉÔØ ÌÀÂÙÅ ÏÐÅÒÁÃÉÉ ÁÎÁÌÉÚÁ, ÐÅÒÅÈÏÄ +ÍÅÖÄÕ ÒÅÇÉÏÎÁÍÉ É Ô.Ð. åÓÌÉ × ÒÅÚÕÌØÔÁÔÅ ÏÐÅÒÁÃÉÉ ÏÂÒÁÂÏÔËÉ ËÁÒÔ +ÓÏÚÄÁÎÁ ÒÏ×ÎÏ ÏÄÎÁ ÎÏ×ÁÑ ËÁÒÔÁ, ÔÏ ÏÎÁ ÚÁÍÅÝÁÅÔ × ÏËÎÅ ×ØÀÅÒÁ ÔÕ, +ËÏÔÏÒÁÑ ÂÙÌÁ ×Ù×ÅÄÅÎÁ Ã×ÅÔÏÍ (ÓÌÕÞÁÊ ÓÉÎÈÒÏÎÎÏÇÏ ×ÙÐÏÌÎÅÎÉÑ). + +÷ÓÅ ÏÐÅÒÁÃÉÉ, ËÏÔÏÒÙÅ ÐÏÌØÚÏ×ÁÔÅÌØ ÍÏÖÅÔ ÐÒÏÉÚ×ÅÓÔÉ ÉÚ ÍÅÎÀ ÓÉÓÔÅÍÙ +ÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÉÚ ÐÒÏÇÒÁÍÍÙ ÎÁ Tcl, ×ËÌÀÞÁÑ ÔÁËÉÅ ËÁË ÒÉÓÏ×ÁÎÉÅ +ÔÏÞËÉ ÉÌÉ ÌÉÎÉÉ × ÒÅÄÁËÔÏÒÅ + +á×ÔÏÍÁÔÉÞÅÓËÁÑ ÁËÔÕÁÌÉÚÁÃÉÑ ËÁÒÔ. + +äÌÑ ËÁÒÔ ÓÏÚÄÁÎÎÙÈ × ÒÅÚÕÌØÔÁÔÅ ÏÐÅÒÁÃÉÊ ÏÂÒÁÂÏÔËÉ ÈÒÁÎÉÔÓÑ +ËÏÍÁÎÄÁ, ÓÏÚÄÁ×ÛÁÑ ËÁÒÔÕ, É ÓÐÉÓÏË ÉÓÈÏÄÎÙÈ ËÁÒÔ. ðÒÉ ×ÉÚÕÁÌÉÚÁÃÉÉ +ÜÔÏÊ ËÁÒÔÙ ÐÒÏ×ÅÒÑÅÔÓÑ, ÎÅ ÂÙÌÉ ÌÉ ÉÚÍÅÎÅÎÙ ËÁËÉÅ-ÔÏ ÉÚ ÉÓÈÏÄÎÙÈ +ËÁÒÔ, É ÅÓÌÉ ÄÁ, ÐÒÅÄÌÁÇÁÅÔÓÑ ÐÏ×ÔÏÒÉÔØ ÇÅÎÅÒÁÃÉÀ ËÁÒÔÙ. + diff --git a/doc/concepts.html b/doc/concepts.html new file mode 100644 index 0000000..08dc673 --- /dev/null +++ b/doc/concepts.html @@ -0,0 +1,360 @@ + + + +f(GIS) concepts + + + +

f(GIS) + concepts

+ +
    +
  1. Data model +
      +
    1. Functional model +
    2. Layer classification +
    3. Implementation of data model +
    4. Regions and chartographic projection +
    +
  2. Program design +
      +
    1. Layer as Tcl object +
    2. Planchet - object for displaying maps +
    3. Low level objects +
    4. GIS operation +
    5. Utilities +
    6. Data access library +
    +
+ + + + +

Data model

+ +GIS is a software system for processing spatial data. So, adequate model +of spatial phenomena is most important thing for GIS. +

+It should provide way to represent spatial phenomena in computer memory, +allow to perform desired operation on this representation and let user +see the results in form, he used to. Ideally, GIS system should hide +complicated issues of internal data storage from user as well as text +processor hides questions of font rendering or kerning or SQL database +hides actual file layout and search technologies, providing simple, +but powerful relational operations instead. +

+Many modern +GIS systems, especially vector based, like ARC/Info, try to +represent map of spatial phenomena rather than spatial phenomena +itself. It leads to overcomplication of storage format and processing +algorithms, and makes user worry about such technical things as polygon +topology, which are completely irrelevant to his problem (say geology +or soil science), as font rendering hints and kerning is irrelevant to +contents of article, typesetted with some partcular font. Maps are +tool for analyse spatial data, widely used, but no more than tool. +GIS system should deal with them, becouse it is neccesary to use +existing data, which are represented on maps, and present results to +user in understandable form of maps, but while processing data we should +take into account properties of actual phenomena, rather then properties +of chartographic representation like polygons. +

+

Functional model

+ +In f(GIS) we use term layer to denote computer representation of +spatial phenomena. We define layer as function which maps geographical +coordinates to value of some property. Closest analogue of our +layer is spatial variable in geostatistics. +

+Layer values can be either real numbers or elements of some finite sets. +If you want to study more complicated spatial phenomena, it is better +to describe it as set of layers rather then individual layer with +structured value. Obvoisly you'll not need values of all attributes in +question for all desired calculations, and separating them makes your +actions more clear. +

+Becouse layers are defined as functions it is theoretically possible to +apply well develped mathematical apparatus of functional analysis to +them. + + +

Layer classification

+Layers can be classified by their area of definition and their set of +values. By area of definition we can distinguish between: + +
+
Two-dimensional layers +
which are defined on some contineous area. + It is most frequently used type of layers for physical geography. + Relief and soil type are perfect examples of such layers. Area of + definition of two-dimensional layers is usially finite, limited by + boundaries of study area or by availability of data. Areas which are + outside of area of definition are called offsite areas. +
One-dimensional layers +
are defined on set of lines within study area. Examples of such + layers are hydrography or railroad network. +
Zero-dimensional layers +
are defined on set of separate points. This layers can be used + for store information about sampling points or weather station +networks. +
+ +By the set of values layers can be classified to: +
+
Numeric layers +
whose values belong to some contineous interval on numeric axis, +for example relief layers, which have any value between lowest and +highest altitude in the study area. +
Classification layers +
which have finite set of values. f(GIS) allows to use arbitrary +strings as elements of such set. Soil map which has names of soil series +as values can be used as an example. +
+ +This simple classification covers all theoretically important types of +layers. Dealing with implementation we'll have to classify layers +further, for example, according to source of thematic data. But for +data analysis it is not significant whether data are stored in disk +file or come from some data asquition system on the fly. It is only +important to know type of values and whether they are defined for +any point of study area or not. + +

Implementation of data model

+ +Spatial phenomena seldom can be expressed by some mathematical equation. +Even if they can, finding of this equation is usially aim of analysis, +not a starting point. So, we need to store values of layers in any +point they are defined. Raster is natural way to store data for +two-dimensional layers.

+ (Raster is just big matrix of numeric values, stored +in special format to reduce storage space. If raster is used in GIS +processing, it should be known, how to find row and column numbers given +real word coordinates and vice versa) +

+f(GIS) uses raster data format developed for EPPL7 GIS system. This +format have several advantages - it is compressed and allows random +access at the same time and it is able to deal with very fine +resolution. For example Landscape map of exUSSR with spatial resolution +(raster cell size) 500m and more than 3000 distinct kinds of landscapes +occupies about 9MB of disk space. Due to such properties of data +format, it is advisable to work with raster cell size significantly less +then known accuracy of data. Resolution of maps can be compatible with +resolution of your scanner and printer - modern processors are powerful +enough to bear it, so raster doesn't mean loss of precession. +

+This data format is able to hold values in range 0..65535. While it is +always sufficient for classification layers, it can look that for +numeric layers it is better to use real numbers. But data always have +finite accuracy, which is usially less than 1/65535 of total range, +and even if we can take measurements with larger precession, we should +take into account spatial variability within one raster cell. +

+For example, if we have map of relief of Russia with 500 meter cell, +we need to represent range from -28 (Caspian coast) to 5642 (Elbrus) +meters above sea level. Thus smallest usable unit is about 10 cm. +Some points' altitude may be measured with more accuracy (for example, +triangualtion points), but each raster cell represents 500x500 meters +square which always would have more than 10cm of variability. +Even if value of our layer should have more precession in some part +of its range, we could use non-linear (for instance logarithmic) mapping +of raster cell values to layer values. +

+But even with compression, raster files occupy significant storage +space. So, we should avoid duplication of them if possible. Thus we +introduce concept of reclass tables. Reclass table maps values +of raster cell to another set of integer in arbitrary order. Don't mix +reclass table with mapping function which is used for convert raster +cell values to real units of numeric layer. For example if we have +statistical data of populations by county and want to create population +them as map, we can use reclass table over county map. Several counties +with different names, which have distinct values in county map raster, +can be mapped to same class in population density map if their population +density is same. +

+Point layer is just list of triplets < X, Y, Value >. Typically +point layer doesn't contain more than few thousands of points, so there +is no need to optimize performance or storage space. +

+Natural storage form of one-dimensional layer is vector format. +It is most questionable area in current fGIS design. There are a lot of +advantages of EPPL7 vector format (compactness, speed of processing), +but it have only one drawback, which overcomes them all - it can +associate only one value with whole vector object (polyline). But +if we are talking about the function, defined on set of lines, whe +should be prepared that this function (stream depth for instance) would +vary from one end of line to other. +

+It is also a question how intersections and joints of lines should +be stored/interpreted, becouse most interesting network analysis +algorithmes require ability to cross joints and intersections. +

+ +

Regions and chartographic projection

+ +Study area usially have hierarchical structure. For example Russia +can be subdivided to administrative regions, which consists of +districts. United States consists of states, which are divided into +counties. Often study is concerned only with one of such hierarchy +levels, but there are opposite examples. +

+Each hierarchy level have its typical data accuracy (which is rough +representation of map scale in GIS world, becouse GIS maps can be +arbitrarily scaled, but only certain scale range make sense for +particular data accuracy), chartographic projection (especially +significant for large areas like whole country or continent). +On thematic maps like soils or vegetation, different classifications +can be used in different scales. +

+So, f(GIS) uses concept of regions. Region is set of layers, +which cover almost same territory, have exactly same projection and +simular spatial resolution. Regions can be nested, i.e. region of +Russia can have several subregions of administrative regions, which +have subregions of districts etc. In this case there should be base +layer +which have subregion names as values. When copiing data between regions +f(GIS) authomatically performs neccessary projection and resolution + conversion using base layer as reference. Classification conversion, +if neccessary, should be performed by user, becouse it requires +knowledge in problem area. + +

Program design

+ +f(GIS) is designed as set of extensions to Tcl programming language +and set of independent utilities, which perform most time consuming +raster and vector processing tasks. Thus long operations can be launched +in background as separate while user continues to view/analyze data in +main program. +

+From users point of view, fGIS is Tcl application which allows him +to operate with set of layers from GUI as well as from Tcl command line. +It is essential design constraing that there should be no operation, +which can be performed from GUI, but couldn't be from Tcl script. There +should be way to automate everything. Other way around is enusred by +very nature of Tcl. Nothing prevent user, which have direct access to +Tcl interpreter from creating new button or menu item and binding any +Tcl command to it. +

+From programmers point of view, fGIS consists of several abstraction +levels, all available for extension and modification. And I think that +every fGIS user can eventually become programmer, if he discoveres need +to implement some, just invented, data analysis algorithm, or customize +graphical user interface to his needs. Relationship between fGIS +abstraction levels is shown on this figure. +

+ +

+

Layer as Tcl object

+Layers in fGIS behave like objects in object-oriented programming +language. Once created with layer command they become tcl +commands itself (i.e. name of layer can be used as Tcl command), +just like Tk widget. Options of layer command allow to manipulate +properties of layer and store layer definition to file. This file +is just Tcl script which creates neccessary subobjects and invokes +appropriate command to create layer. +

Layer have following properties +

+
It can return value by coordinates +
It is why whole thing is about +
It can one or more ways to draw itself +
Raster layer can be drawn in opaque colors, so only offsite area is +transparent or using transparent monochrome patterns, thus allowing to +overlay one raster over another. In most existing raster GIS, like +Idrisi only vector or point layers can be overlayed over raster. +In f(GIS) any +layer can be drawn as overlay +
It has underlying data source +
Data source for layers typically consist of some object which can + return integer value given coordinate (raster file, combined with +reclass table, for example) and legend table or map +function which maps values of underlying raster object to +thematically meaningful values. +
It has visualization parameters +
visualization fo layer is controlled by several parameters such as +color palette, pattern set, flag, indicating if boundaries between +classes are drawn or not. All these parameters can be changed +interactively. +
It has metadata +
Metadata for layer typically include layer title, units in which +its values are managed, spatial resolution and value precession. +Chartographic projection is property of region rather than layer. +
+ +Besides layer types described above fGIS have +object layer type. This layer type can consist of any objects +allowed in Tcl canvas - lines, arcs, polygons, images with only one +thematic value for each object. This type is primarily for annotation +purposes, but also can be used as substitute for vector layers, while +later are not developed +

+

Planchet - object for displaying maps

+Another type of object which is essential for fGIS user is +planchet. It is Tk widget like canvas (and actially derived from +canvas) which has chartographic projection and real-world coordinates. +It is used for displaying layers and picking points on them. Becouse +it has real-world coordinates and physical size on the screen, it always +knows its scale. When scale is changed (via zoom or window resize operation), +all layers currently displayed on planchet are redrawn appropriately. +

+Planchet also have look feature. If right mouse button is pressed +on some point in planchet, it displays values of several layers in this +point in pop-up window. +

+There can be also "friend widgets" like status line which +display current coordinates if mouse is over planchet or zoom/unzoom +buttons which change its state depending of current state of planchet. +

+

Low level objects

+ +There are additional objects like rasters, palettes and pattern sets. +But user seldom need to operate on them directly. They are primarily +for developers of new layer types. + +

GIS operation

+GIS operation like calculationg buffer zones or computing new layer +from several existing are performed by separate utilities running in background. For user convinience +there are tcl procedures which take one or more layer names as arguments +and call appropriate utility. +

+Example of such procedure is interregion copy command, which tooks +layer name and name of target region, determines projections and calls +projection conversion program. +

+In some cases such procedures need to perform sufficient preprocessing +of user-supplied arguments +

Utilities

+ +GIS processing utilities are more general than fGIS. They use just +data files and user-supplied arguments. So they can be used separately +from fGIS, for example by users of EPPL7 GIS. Utilities are designed +for batch environment, so they use exit codes to report status and +stdin/stdout to recieve and return values which are not fit in command +line. Important concept of these utilities is that user shouldn't worry +about raster cell size. All utilites which operate on several raster +files are able to deal with files with different cell sizes as long +as there is non-empty intersection in terms of real-world coordinates. + +

Data access library

+ +Both low-level Tcl objects (rasters, vectors) and utilites use common +C library to access data files. This library provides appropriately +high-level framework for those who want implement own data analysis + algorithmes. For example it includes iterator routines, which recieve +user-written function and open raster file and perform this function +on every cell of given file. While library operates primarily in terms +of raster cells (which can be important for cellular automata +algorithmes, which need to distinguish between ``this cell'' and +``neighbouring cell'') it provides ways to process files with different +cell sizes simulateously. + + + + + + + + + + + + + diff --git a/doc/doc.formats b/doc/doc.formats new file mode 100644 index 0000000..5f62da2 --- /dev/null +++ b/doc/doc.formats @@ -0,0 +1,37 @@ + æÁÊÌ ÏÐÉÓÁÎÉÑ ÒÅÇÉÏÎÁ +îÁÚÙ×ÁÅÔÓÑ .region +ÉÌÉ REGION × Windows ×ÅÒÓÉÉ + +óÏÄÅÒÖÉÔ ÓÌÅÄÕÀÝÕÀ ÉÎÆÏÒÍÁÃÉÀ + +1. NAME "îÁÚ×ÁÎÉÅ ÒÅÇÉÏÎÁ" + CYRILLIC ÉÍÑ ËÏÄÉÒÏ×ËÉ +2. PROJECTION ÎÁÚ×ÁÎÉÅ + .... + END +ïÐÉÓÁÎÉÅ ÐÒÏÅËÃÉÉ × ÆÏÒÍÁÔÅ, ÓÏ×ÐÁÄÁÀÝÅÍ Ó ARC/Info. +3. SHOW ÓÐÉÓÏË ËÁÒÔ + éÍÅÎÁ ËÁÒÔ, ËÏÔÏÒÙÅ ×Ù×ÏÄÑÔÓÑ ÐÒÉ ×ÈÏÄÅ × ÄÁÎÎÙÊ ÒÅÇÉÏÎ. +4 DATABASE ÉÍÑ ÂÁÚÙ ÄÁÎÎÙÈ +5. MAP ÉÍÑ ÆÁÊÌÁ +éÍÑ ÒÁÓÔÒÁ, ÉÓÐÏÌØÚÕÅÍÏÇÏ ÄÌÑ ÐÅÒÅÈÏÄÁ Ë ÒÅÇÉÏÎÁÍ ÓÌÅÄÕÀÝÅÇÏ ÕÒÏ×ÎÑ +6. SUBREGIONS +ËÌÁÓÓ ÉÍÑ ËÁÔÁÌÏÇÁ +... +ÉÌÉ SUBREGIONS QUERY sql-ÚÁÐÏÒÏÓ +æÁÊÌ ÏÐÉÓÁÎÉÑ ËÁÒÔÙ + +NAME ÉÍÑ +[GROUP ÉÍÑ ÇÒÕÐÐÙ ËÁÒÔ] +[CYRILLIC ÉÍÑ ËÏÄÉÒÏ×ËÉ] +INFO +ÎÅÓÔÒÕËÔÕÒÉÒÏ×ÁÎÎÑÊ ÔÅËÓÔ +ENDINFO +RASTER ÉÍÑ ÆÁÊÌÁ +RECLASS [QUERY sql- ÚÁÐÒÏÓ|FILE ÉÍÑ|\nÓÐÉÓÏË ÏÐÅÒÁÔÏÒÏ×] +[RECALC ×ÙÒÁÖÅÎÉÅ \n[CCT\nÔÁÂÌÉÃÁ ÉÎÔÅÒ×ÁÌÏ×|INTERVAL ÞÉÓÌÏ] +|LEGEND [FILE ÉÍÑ|QUERY sql-ÚÁÐÒÏÓ|\nÔÅËÓÔ ÌÅÇÅÄÙ] +PALETTE [ÉÍÑ ÆÁÊÌÁ|\n ÓÐÉÓÏË ÏÐÉÓÁÎÉÊ Ã×ÅÔÏ×] +[SYMBOLS/PATTERNS [BORDER]] ÓÐÉÓÏË ÏÐÉÓÁÎÉÊ ÛÔÒÉÈÏ×ÏË +COMPANIONS ÓÐÉÓÏË ÉÍÅÎ ËÁÒÔ - ÉÍÅÎÁ ËÁÒÔ, ËÏÔÏÒÙÅ ÎÁÄÏ ×Ù×ÏÄÉÔØ, ÅÓÌÉ +ÕËÁÚÁÎÎÁÑ ×Ù×ÏÄÉÔÓÑ ËÁË ÏÓÎÏ×ÎÁÑ diff --git a/doc/epu_doc.tex b/doc/epu_doc.tex new file mode 100644 index 0000000..7f4f896 --- /dev/null +++ b/doc/epu_doc.tex @@ -0,0 +1,181 @@ +\documentclass{article} +\usepackage{russian,academy} +\title{Environmental planning utilities\\òÕËÏ×ÏÄÓÔ×Ï ÐÏÌØÚÏ×ÁÔÅÌÑ} +\author{÷.â.~÷ÁÇÎÅÒ} +\newcommand{\obsoletes}[1]{\par úÁÍÅÎÑÅÔ ËÏÍÁÎÄÙ EPPL7: {\bf #1}\par} +\begin{document} +\maketitle +\section*{÷×ÅÄÅÎÉÅ} + +Environmental planning utilities (ÄÁÌÅÅ EPU)~--- ÎÁÂÏÒ ÐÒÏÇÒÁÍÍ, ×ÙÐÏÌÎÑÀÝÉÈ +ÐÒÉÍÅÒÎÏ ÔÅ ÖÅ ÏÐÅÒÁÃÉÉ, ÞÔÏ É ËÏÍÁÎÄÙ çéó EPPL7. ïÓÎÏ×ÎÙÍ ÍÏÔÉ×ÏÍ ÉÈ +ÒÁÚÒÁÂÏÔËÉ ÂÙÌÏ ÐÒÅÏÄÏÌÅÎÉÅ ÎÅËÏÔÏÒÙÈ ÏÇÒÁÎÉÞÅÎÉÊ EPPL7 ×ÅÒÓÉÉ 3.0, +Ó×ÑÚÁÎÎÙÈ Ó 16-ÂÉÔÎÏÊ ÁÒÈÉÔÅËÔÏÒÏÊ ÜÔÏÊ ÐÒÏÇÒÁÍÍÙ, É ÏÂÅÓÐÅÞÅÎÉÅ ×ÏÚÍÏÖÎÏÓÔÉ +ÒÁÂÏÔÙ Ó ÆÁÊÌÁÍÉ EPPL7 × ÓÒÅÄÅ UNIX. + +EPPL7 ÒÁÓÛÉÆÒÏ×Ù×ÁÅÔÓÑ ËÁË +Environmental Planning Programming Language. ë ÓÏÖÁÌÅÎÉÀ × ÑÚÙËÅ EPPL7 +ÎÅ È×ÁÔÁÅÔ ÓÔÒÕËÔÕÒ ÕÐÒÁ×ÌÅÎÉÑ, ÐÅÒÅÍÅÎÎÙÈ É ÄÒÕÇÉÈ ÐÏÌÅÚÎÙÈ ËÏÎÓÔÒÕÔÃÉÊ, +× ÓÉÌÕ ÞÅÇÏ ÏÎ ÎÅ ÐÒÉÇÏÄÅÎ ÄÌÑ ÓÅÒØÅÚÎÏÇÏ ÐÒÏÇÒÁÍÍÉÒÏ×ÁÎÉÑ. + +ðÏÜÔÏÍÕ, ÐÒÉ ÒÁÚÒÁÂÏÔËÅ EPU ÂÙÌÏ ÒÅÛÅÎÏ ÎÅ ÐÙÔÁÔØÓÑ ×ÏÓÐÒÏÉÚ×ÅÓÔÉ ËÏÎÃÅÐÃÉÀ +ÏÒÉÇÉÎÁÌÁ, Á ÒÁÚÒÁÂÏÔÁÔØ ÎÁÂÏÒ ÏÔÄÅÌØÎÙÈ ËÏÍÁÎÄÎÏ-ÓÔÒÏÞÎÙÈ ÕÔÉÌÉÔ, +×ÙÐÏÌÎÑÀÝÉÈ ÏÓÎÏ×ÎÙÅ çéó ÏÐÅÒÁÃÉÉ, ÞÔÏ ÐÏÚ×ÏÌÉÔ ÉÓÐÏÌØÚÏ×ÁÔØ ÄÌÑ ÒÅÛÅÎÉÑ +ËÏÎËÒÅÔÎÙÈ ÚÁÄÁÞ ÕÖÅ ÓÕÝÅÓÔ×ÕÀÝÉÅ ÒÁÚ×ÉÔÙÅ ÓËÒÉÐÔÏ×ÙÅ ÑÚÙËÉ (shell, tcl, perl). + +÷ÙÄÅÌÅÎÉÅ ÜÔÉÈ ÏÐÅÒÁÃÉÊ × ÏÔÄÅÌØÎÙÅ ÐÒÏÇÒÁÍÍÙ ÉÍÅÅÔ ÅÝÅ É ÔÏ ÐÒÅÉÍÕÝÅÓÔ×Ï, +ÞÔÏ ÜÔÉ ÏÐÅÒÁÃÉÉ, ÏÂÙÞÎÏ ÚÁÎÉÍÁÀÝÉÅ ÍÎÏÇÏ ×ÒÅÍÅÎÉ, ÍÏÇÕÔ ÂÙÔØ ÚÁÐÕÝÅÎÙ +ËÁË ÐÁÒÁÌÌÅÌØÎÙÅ ÐÒÏÃÅÓÓÙ, ÎÅÚÁ×ÉÓÉÍÏ ÏÔ ÔÏÇÏ, ÐÏÄÄÅÒÖÉ×ÁÀÔÓÑ ÌÉ ÏÐÅÒÁÃÉÏÎÎÏÊ +ÓÉÓÔÅÍÏÊ ÍÎÏÇÏÎÉÔÅ×ÙÅ ÐÒÏÇÒÁÍÍÙ. + +õÔÉÌÉÔÙ ÒÁÚÒÁÂÁÔÙ×ÁÌÉÓØ Ó ÕÞÅÔÏÍ ÔÒÅÂÏ×ÁÎÉÑ ÍÁËÓÉÍÁÌØÎÏÊ ÐÅÒÅÎÏÓÉÍÏÓÔÉ, +É ÔÅÏÒÅÔÉÞÅÓËÉ ÄÏÌÖÎÙ ËÏÍÐÉÌÉÒÏ×ÁÔØÓÑ É ×ÙÐÏÌÎÑÔØÓÑ ÎÁ ÌÀÂÏÊ 32 É ÂÏÌÅÅ +ÒÁÚÒÑÄÎÏÊ ÐÌÁÔÆÏÒÍÅ (DOS DPMI, Windows NT, Unix, VMS). ÷ ÎÁÓÔÏÑÝÅÅ ×ÒÅÍÑ +ÏÎÉ ÂÙÌÉ ÐÒÏÔÅÓÔÉÔÏ×ÁÎÙ ÎÁ ÐÌÁÔÆÏÒÍÁÈ DOS/DOS4GW, Linux i386 É Solaris Sparc, +ÞÔÏ ÐÏÚ×ÏÌÑÅÔ ÕÔ×ÅÒÖÄÁÔØ ÞÔÏ ÏÎÉ ÎÅÚÁ×ÉÓÉÍÙ ÏÔ ÐÏÒÑÄËÁ ÂÁÊÔÏ× × ÐÒÏÃÅÓÓÏÒÅ. +÷ÅÒÏÑÔÎÅÅ ×ÓÅÇÏ, × ÕÔÉÌÉÔÁÈ É ÉÓÐÏÌØÚÕÅÍÙÈ ÂÉÂÌÉÏÔÅËÁÈ ÓÕÝÅÓÔ×ÕÀÔ ÍÅÓÔÁ, +ËÏÔÏÒÙÅ ÐÏÔÏÒÅÂÕÀÔ ÐÒÁ×ËÉ ÐÒÉ ÐÅÒÅÈÏÄÅ Ë 64-ÒÁÚÒÑÄÎÏÊ ÁÒÈÉÔÅËÔÕÒÅ. + +÷ Ó×ÑÚÉ Ó ÔÅÍ, ÞÔÏ EPU ÉÎÔÅÎÓÉ×ÎÏ ÉÓÐÏÌØÚÕÀÔ ÏÐÅÒÁÃÉÉ Ó ÐÌÁ×ÁÀÝÅÊ ÚÁÐÑÔÏÊ, +ÍÙ ÎÅ ÒÅËÏÍÅÎÄÕÅÍ ËÏÍÐÉÌÉÒÏ×ÁÔØ ÉÈ ÐÒÉ ÐÏÍÏÝÉ DJGPP ×ÅÒÓÉÊ 1.x É 2.0x, +ÐÏÓËÏÌØËÕ ÜÔÏÔ ËÏÍÐÉÌÑÔÏÒ ÉÍÅÅÔ ÛÉÒÏËÏ ÉÚ×ÅÓÔÎÙÅ ÐÒÏÂÌÅÍÙ Ó ÉÓÐÏÌØÚÏ×ÁÎÉÅÍ +ÓÏÐÒÏÃÅÓÓÏÒÁ. + +\section{ëÏÎÃÅÐÃÉÑ EPU} + +EPU ÒÁÂÏÔÁÀÔ ÐÒÅÉÍÕÝÅÓÔ×ÅÎÎÏ Ó ÒÁÓÔÒÏ×ÙÍÉ ËÁÒÔÁÍÉ. ÷ ÏÔÌÉÞÉÅ ÏÔ ÂÏÌØÛÉÎÓÔ×Á +ÄÒÕÇÉÈ ÒÁÓÔÒÏ×ÙÈ çéó, ÓÞÉÔÁÅÔÓÑ ÞÔÏ ÒÁÓÔÒÏ×ÁÑ ËÁÒÔÁ Ñ×ÌÑÅÔÓÑ ÍÏÄÅÌØÀ ÎÅËÏÊ +ÃÅÌÏÞÉÓÌÅÎÎÏÊ ÉÌÉ ×ÅÝÅÓÔ×ÅÎÎÏÊ ÆÕÎËÃÉÉ ÏÔ ËÏÏÒÄÉÎÁÔ, É ÒÁÚÍÅÒ ÑÞÅÊËÉ ÒÁÓÔÒÁ +ÎÅ Ñ×ÌÑÅÔÓÑ ÓÕÝÅÓÔ×ÅÎÎÙÍ ÄÌÑ ÂÏÌØÛÉÎÓÔ×Á ÏÐÅÒÁÃÉÊ, ÈÏÔÑ ÉÍÅÎÎÏ ÏÎ ÓÌÕÖÉÔ +ÏÓÎÏ×ÎÏÊ ÍÅÒÏÊ ÔÏÞÎÏÓÔÉ. + +ðÏÜÔÏÍÕ, ×ÓÅ ÐÒÏÇÒÁÍÍÙ EPU, ÏÂÒÁÂÁÂÙ×ÁÀÝÉÅ ÎÅÓËÏÌØËÏ ×ÈÏÄÎÙÈ ÆÁÊÌÏ×, ÐÏÚ×ÏÌÑÀÔ +ÉÓÐÏÌØÚÏ×ÁÔØ ÆÁÊÌÙ, ËÏÏÒÄÉÎÁÔÙ ÒÁÍËÉ É ÒÁÚÍÅÒ ÑÞÅÊËÉ ËÏÔÏÒÙÈ ÎÅ ÓÏ×ÐÁÄÁÀÔ% +\footnote{åÓÌÉ ËÁËÁÑ-ÌÉÂÏ ÉÚ ÕÔÉÌÉÔ ÏÔËÁÚÙ×ÁÅÔÓÑ ×ÏÓÐÒÉÎÉÍÁÔØ ÔÁËÉÅ ÆÁÊÌÙ, +ÛÌÉÔÅ bug-report.}. +ðÒÏÓÔÒÁÎÓÔ×ÅÎÎÏÅ ÓÏÏÔ×ÅÔÓÔ×ÉÅ ÍÅÖÄÕ ÆÁÊÌÁÍÉ ÐÒÉ ÜÔÏÍ ÕÓÔÁÎÁ×ÌÉ×ÁÅÔÓÑ ÐÏ +ÍÉÒÏ×ÙÍ ËÏÏÒÄÉÎÁÔÁÍ (ÁÌØÔÅÒÎÁÔÉ×ÎÙÅ ËÏÏÒÄÉÎÁÔÙ × ÔÅÒÍÉÎÏÌÏÇÉÉ EPPL7). + +áÎÁÌÏÇÉÞÎÏ, ÚÎÁÞÅÎÉÅ offsite (ÎÅÔ ÄÁÎÎÙÈ) ÐÒÁËÔÉÞÅÓËÉ ×ÓÅÇÄÁ ÐÒÉÎÉÍÁÅÔÓÑ +×Ï ×ÎÉÍÁÎÉÅ, ÈÏÔÑ ÏÔÄÅÌØÎÙÅ ÕÔÉÌÉÔÙ ÍÏÇÕÔ ÉÍÅÔØ ÓÐÅÃÉÁÌØÎÙÊ ËÌÀÞ, +ÐÏÚ×ÏÌÑÀÝÉÊ ÎÅ ÕÞÉÔÙ×ÁÔØ offsite. + +ëÁÒÔÙ EPPL7 ÍÏÖÎÏ ÒÁÚÄÅÌÉÔØ ÎÁ Ä×Á ËÌÁÓÓÁ~--- ËÁÒÔÙ ËÏÌÉÞÅÓÔ×ÅÎÎÙÈ ×ÅÌÉÞÉÎ +(ÃÉÆÒÏ×ÙÅ ÍÏÄÅÌÉ) É ËÁÒÔÙ ËÌÁÓÓÉÆÉËÁÃÉÊ, ÞÉÓÌÏ×ÙÅ ÚÎÁÞÅÎÉÑ ËÌÁÓÓÏ× ËÏÔÏÒÙÈ +ÎÅ ÉÍÅÀÔ ÄÒÕÇÏÇÏ ÓÍÙÓÌÁ, ËÒÏÍÅ ËÁË ÉÎÄÅËÓÙ ÔÅËÓÔÏ×ÙÈ ÚÎÁÞÅÎÉÊ × ÌÅÇÅÎÄÅ. + +æÏÒÍÁÔ ÆÁÊÌÏ× EPPL7 ÎÅ ÐÏÚ×ÏÌÑÅÔ ×Ï ×ÓÅÈ ÓÌÕÞÁÑÈ ÈÒÁÎÉÔØ ÓÅÍÁÎÔÉÞÅÓËÏÅ +ÚÎÁÞÅÎÉÅ Ó ÔÒÅÂÕÅÍÏÊ ÔÏÞÎÏÓÔØÀ ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÏ × ÆÁÊÌÅ ÄÁÎÎÙÈ, ÐÏÓËÏÌØËÕ +ÄÉÁÐÁÚÏÎ ×ÏÚÍÏÖÎÙÈ ÚÎÁÞÅÎÉÊ ÆÁÊÌÏ× ÏÇÒÁÎÉÞÅÎ ËÏÒÏÔËÉÍ ÂÅÚÚÎÁËÏ×ÙÍ ÃÅÌÙÍ +(0--65535). ðÏÜÔÏÍÕ ÔÅ ÐÒÏÇÒÁÍÍÙ EPU, ËÏÔÏÒÙÅ ×ÙÐÏÌÎÑÀÔ ÍÁÔÅÍÁÔÉÞÅÓËÉÅ ÏÐÅÒÁÃÉÉ +ÎÁÄ ÚÎÁÞÅÎÉÑÍÉ ËÁÒÔÙ, ÐÏÚ×ÏÌÑÀÔ ÚÁÄÁÔØ ÍÁÓÛÔÁÂÎÙÊ ËÏÜÆÆÉÃÉÅÎÔ É ÓÍÅÝÅÎÉÅ +ÎÕÌÅ×ÏÇÏ ËÌÁÓÓÁ. + +÷ÏÚÍÏÖÎÏÓÔÉ EPU ÐÏ ÒÁÂÏÔÅ Ó ×ÅËÔÏÒÎÙÍÉ ÆÁÊÌÁÍÉ EPPL7 ÓÕÝÅÓÔ×ÅÎÎÏ ÏÇÒÁÎÉÞÅÎÙ. +üÔÏ Ó×ÑÚÁÎÏ × ÏÓÎÏ×ÎÏÍ Ó ÔÅÍ, ÞÔÏ ÐÒÅÄÐÏÌÁÇÁÅÔÓÑ × ÄÁÌØÎÅÊÛÅÍ ÐÅÒÅÊÔÉ +ÏÔ ÆÏÒÍÁÔÁ DGT Ë ÂÏÌÅÅ ÇÉÂËÏÍÕ ×ÅËÔÏÒÎÏÍÕ ÆÏÒÍÁÔÕ fGIS. + +ðÏ ×ÏÚÍÏÖÎÏÓÔÉ, ÍÙ ÓÔÁÒÁÌÉÓØ ÏÂßÅÄÉÎÉÔØ ÆÕÎËÃÉÉ ÎÅÓËÏÌØËÉÈ ËÏÍÁÎÄ EPPL7 +× ÅÄÉÎÕÀ ÕÔÉÌÉÔÕ, ÔÁË ËÁË ÜÔÏ ÉÎÏÇÄÁ ÐÏÚ×ÏÌÑÅÔ ÄÏÂÉÔØÓÑ ÎÏ×ÏÇÏ ËÁÞÅÓÔ×Á. + +éÚ ÕÔÉÌÉÔ EPU ÎÁÍÅÒÅÎÎÏ ÉÓËÌÀÞÅÎÁ ×ÓÑËÁÑ ÉÎÔÅÒÁËÔÉ×ÎÏÓÔØ, ÐÏÓËÏÌØËÕ +ÏÎÉ ÏÒÉÅÎÔÉÒÏ×ÁÎÙ ÎÁ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÉÚ ÓËÒÉÐÔÏ×. +\section{õÔÉÌÉÔÙ EPU} +\subsection{border}\label{border} +\obsoletes{BORDER (×ÁÒÉÁÎÔ Ó ÓÏÚÄÁÎÉÅÍ {\tt dgt}-ÆÁÊÌÁ)} +ðÏ ÚÁÄÁÎÎÏÍÕ ÒÁÓÔÒÏ×ÏÍÕ ÆÁÊÌÕ ÓÏÚÄÁÅÔ ×ÅËÔÏÒÎÙÊ ÆÁÊÌ, × ËÏÔÏÒÏÍ ÏÔÒÉÓÏ×Ù×ÁÅÔ +ÇÒÁÎÉÃÙ ÍÅÖÄÕ ËÌÁÓÓÁÍÉ ÉÓÈÏÄÎÏÇÏ ÒÁÓÔÒÁ. ðÏ ÕÍÏÌÞÁÎÉÀ, ÇÒÁÎÉÃÁ ÏÔÒÉÓÏ×Ù×ÁÅÔÓÑ +ÔÏÞÎÏ, × ÒÅÚÕÌØÔÁÔÅ ÞÅÇÏ ÌÉÎÉÑ ÐÒÉ ÂÏÌØÛÏÍ Õ×ÅÌÉÞÅÎÉÉ ×ÙÇÌÑÄÉÔ ËÁË ÓÔÕÐÅÎÞÁÔÁÑ. + +ðÁÒÁÍÅÔÒ tolerance ÐÏÚ×ÏÌÑÅÔ ÕÐÒÁ×ÌÑÔØ ÓÇÌÁÖÉ×ÁÎÉÅÍ ÌÉÎÉÊ. + +ëÁË É ×Ï ×ÓÅÈ ÏÓÔÁÌØÎÙÈ ÕÔÉÌÉÔÁÈ EPU, ÏÂÌÁÓÔØ ÌÅÖÁÛÁÑ ÚÁ ÐÒÅÄÅÌÁÍÉ ÒÁÍËÉ +ËÁÒÔÙ ÓÞÉÔÁÅÔÓÑ offsite. ðÏÜÔÏÍÕ × ÔÅÈ ÍÅÓÔÁÈ ÇÄÅ onsite-ËÌÁÓÓÙ ×ÐÏÌÔÎÕÀ +ÐÒÉÌÅÇÁÀÔ Ë ÒÁÍËÅ, ÏÔÒÉÓÏ×Ù×ÁÅÔÓÑ ÇÒÁÎÉÃÁ. ôÁËÏÅ ÐÏ×ÅÄÅÎÉÅ ÎÅ ×ÓÅÇÄÁ ÖÅÌÁÔÅÌØÎÏ, +ÐÏÜÔÏÍÕ ÅÇÏ ÍÏÖÎÏ ÏÔËÌÀÞÉÔØ. + +{\bf æÏÒÍÁÔ ×ÙÚÏ×Á:} + +{\tt + \bf border \rm\it ËÌÀÞÉ ÉÍÑ ÆÁÊÌÁ\rm +} + +{\bf ëÌÀÞÉ:} +\begin{description} +\item[-\%] ÷ ÐÒÏÃÅÓÓÅ ÒÁÂÏÔÙ ×Ù×ÏÄÉÔØ ÎÁ stdout ÐÒÏÃÅÎÔ ÏÂÒÁÂÏÔÁÎÎÏÊ ËÁÒÔÙ. +\item[-l] óÏÚÄÁÔØ ÍÅÔËÉ ÐÏÌÉÇÏÎÏ×. (ÐÏËÁ ÎÅ ÎÁÐÉÓÁÎÏ) +\item[-m] ðÏÄÁ×ÉÔØ ÒÉÓÏ×ÁÎÉÅ ÇÒÁÎÉà ×ÄÏÌØ ÒÁÍËÉ ËÁÒÔÙ +\item[-o ÉÍÑ ÆÁÊÌÁ] úÁÄÁÔØ ÉÍÑ ×ÙÈÏÄÎÏÇÏ ÆÁÊÌÁ. åÓÌÉ ÎÅ ÚÁÄÁÎÏ, ÉÍÑ ×ÙÈÏÄÎÏÇÏ + ÆÁÊÌÁ ÄÅÌÁÅÔÓÑ ÉÚ ÉÍÅÎÉ ×ÈÏÄÎÏÇÏ ÚÁÍÅÎÏÊ ÒÁÓÛÉÒÅÎÉÑ {\tt .epp} ÎÁ {\tt .dgt} +\item[-t ÞÉÓÌÏ] úÁÄÁÔØ ÚÎÁÞÅÎÉÅ tolerance. üÔÏ ÚÎÁÞÅÎÉÅ ÚÁÄÁÅÔÓÑ × ÑÞÅÊËÁÈ + ÉÓÈÏÄÎÏÇÏ ÒÁÓÔÒÁ É ÉÍÅÅÔ ÓÍÙÓÌ ÍÁËÓÉÍÁÌØÎÏÊ ÄÌÉÎÙ ÏÔÒÅÚËÁ, ÏÂÒÁÂÁÔÙ×ÁÅÍÏÊ +ÁÌÇÏÒÉÔÍÏÍ ÓÇÌÁÖÉ×ÁÎÉÑ. ÷ ÂÏÌØÛÉÎÓÔ×Å ÓÌÕÞÁÅ× ÚÎÁÞÅÎÉÅ 3 ÄÁÅÔ ÕÄÏ×ÌÅÔ×ÏÒÉÔÅÌØÎÙÅ +ÒÅÚÕÌØÔÁÔÙ. +\end{description} + +\subsection{classify}\label{classify} +\obsoletes{RECLASS} +óÏÚÄÁÅÔ ÎÏ×ÕÀ ÒÁÓÔÒÏ×ÕÀ ËÁÒÔÕ ÐÏ ÏÄÎÏÊ ÉÌÉ ÎÅÓËÏÌØËÉÍ ÓÔÁÒÙÍ, ÉÓÐÏÌØÚÕÑ +ÚÁÄÁÎÎÙÊ ÎÁÂÏÒ ÐÒÁ×ÉÌ. ÷ ÏÔÌÉÞÉÅ ÏÔ ËÏÍÁÎÄÙ RECLASS EPPL7 ÏÐÅÒÉÒÕÅÔ ÎÅ +Ó ÞÉÓÌÏ×ÙÍÉ ÚÎÁÞÅÎÉÑÍÉ ËÌÁÓÓÏ×, Á Ó ÔÅËÓÔÁÍÉ ÌÅÇÅÎÄÙ. ðÒÅÄÎÁÚÎÁÞÅÎÁ +× ÏÓÎÏ×ÎÏÍ ÄÌÑ ËÁÒÔ ËÌÁÓÓÉÆÉËÁÃÉÊ, × ÏÔÌÉÞÉÉ ÏÔ evaluate (ÒÁÚÄÅÌ~% +\ref{evaluate}), ÐÒÅÄÎÁÚÎÁÞÅÎÎÏÊ × ÏÓÎÏ×ÎÏÍ ÄÌÑ ÃÉÆÒÏ×ÙÈ ÍÏÄÅÌÅÊ. + +\subsection{cluster}\label{cluster} +\obsoletes{CLUSTER, RASTERIZE} +óÏÚÄÁÅÔ ÎÏ×ÕÀ ËÁÒÔÕ, ÚÎÁÞÅÎÉÑ ËÌÁÓÓÏ× ËÏÔÏÒÏÊ ÐÒÅÄÓÔÁ×ÌÑÀÔ ÓÏÂÏÊ +ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÙÅ ÎÏÍÅÒÁ ÒÅÇÉÏÎÏ× ÉÓÈÏÄÎÏÊ ËÁÒÔÙ. ÷ ÏÔÌÉÞÉÅ ÏÔ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÊ +ËÏÍÁÎÄÙ EPPL7, ÇÒÁÎÉÃÁÍÉ ÒÅÇÉÏÎÏ× ÍÏÇÕÔ ÂÙÔØ ÎÅ ÔÏÌØËÏ ÌÉÎÉÉ ÏÐÒÅÄÅÌÅÎÎÏÇÏ +ËÌÁÓÓÁ, ÎÏ É ÐÅÒÅÈÏÄÙ ÍÅÖÄÕ ËÌÁÓÓÁÍÉ. üÔÁ ÖÅ ÕÔÉÌÉÔÁ ×ÙÐÏÌÎÑÅÔ ÒÁÓÔÅÒÉÚÁÃÉÀ +×ÅËÔÏÒÎÏÇÏ ÆÁÊÌÁ. + + +\subsection{dgt2gen}\label{dgt2gen} +\obsoletes{EXPORT DGT$\bigarrowleft$ARC Generate} +ëÏÎ×ÅÒÔÉÒÕÅÔ ×ÅËÔÏÒÎÙÊ ÆÁÊÌ EPPL7 × ÆÁÊÌ × ÆÏÒÍÁÔÅ, ÐÒÉÇÏÄÎÏÍ ÄÌÑ +ËÏÍÁÎÄÙ GENERATE ARC/Info. óÏÚÄÁÅÔ Ä×Á ÆÁÊÌÁ Ó ÒÁÓÛÉÒÅÎÉÑÍÉ {\tt .gen} É +{\tt gpn} ÓÏÏÔ×ÅÔÓ×ÅÎÎÏ, ÓÏÄÅÒÖÁÝÉÅ ÌÉÎÉÉ É ÔÏÞËÉ ÉÓÈÏÄÎÏÇÏ ÆÁÊÌÁ. +ðÏ ÕÍÏÌÞÁÎÉÀ ÜÔÉ ÆÁÊÌÙ ÉÍÅÀÔ ÉÍÑ ÓÏ×ÐÁÄÁÀÝÅÅ Ó ÉÍÅÎÅÍ ÉÓÈÏÄÎÏÇÏ ÆÁÊÌÁ É +ËÏÎÃÙ ÓÔÒÏË × ÓÔÉÌÅ UNIX. ëÌÀÞ {\bf -r} ÐÏÚ×ÏÌÑÅÔ ÇÅÎÅÒÉÒÏ×ÁÔØ ËÏÎÃÙ ÓÔÒÏË +× ÓÔÉÌÅ MS-DOS, ÞÔÏ ÎÅÏÂÈÏÄÉÍÏ ÄÌÑ PC ARC/Info ×ÅÒÓÉÊ ÄÏ 3.5. +{\bf ëÌÀÞÉ} +\begin{description} +\item[-v] ÷ ÐÒÏÃÅÓÓÅ ÒÁÂÏÔÙ ÐÏËÁÚÙ×ÁÔØ, ÓËÏÌØËÏ ÌÉÎÉÊ É ÔÏÞÅË ËÏÎ×ÅÒÔÉÒÏ×ÁÎÏ. +\item[-o ÉÍÑ ÆÁÊÌÁ] ÚÁÄÁÔØ ÉÍÑ ÄÌÑ ×ÙÈÏÄÎÙÈ ÆÁÊÌÏ× +\item[-r] çÅÎÅÒÉÒÏ×ÁÔØ ËÏÎÃÙ ÓÔÒÏË × ÓÔÉÌÅ MS-DOS +\end{description} +\subsection{eheader}\label{eheader} + +\obsoletes{HEADER, MAPLIST, ALIGN} +íÏÄÉÆÉÃÉÒÕÅÔ É/ÉÌÉ ÐÏËÁÚÙ×ÁÅÔ ÉÎÆÏÒÍÁÃÉÀ ÉÚ ÚÁÇÏÌÏ×ËÁ ÒÁÓÔÒÏ×ÙÈ É ×ÅËÔÏÒÎÙÈ +ÆÁÊÌÏ× EPPL7. + +\subsection{evaluate}\label{evaluate} +\obsoletes{EVALUATE, MOVING, JUMPING, BORDER, EDGE, NEIGHBOR} +\subsection{extents}\label{extents} +çÅÎÅÒÉÒÕÅÔ ÔÁÂÌÉÃÕ ÐÒÅÄÅÌÏ× ËÏÏÒÄÉÎÁÔ ÄÌÑ ËÁÖÄÏÇÏ ÉÚ ËÌÁÓÓÏ×, ×ÓÔÒÅÞÁÀÝÉÈÓÑ +× ÆÁÊÌÅ. +\subsection{fill}\label{fill} +\obsoletes{FILL} +\subsection{intable}\label{intable} +\obsoletes{INTABLE} +çÅÎÅÒÉÒÕÅÔ ÎÏ×ÙÊ ÆÁÊÌ ÎÁ ÏÓÎÏ×ÁÎÉÉ ÎÅÓËÏÌØËÉÈ ÓÔÁÒÙÈ É ÔÁÂÌÉÃÙ ÓÏÏÔ×ÅÔÓÔ×ÉÑ. +\subsection{mosaic}\label{mosaic} +\obsoletes{MOSAIC}ÍÛÍ +ïÂßÅÄÉÎÑÅÔ ÎÅÓËÏÌØËÏ ËÁÒÔ × ÏÄÎÕ. +\subsection{neighbours}\label{neighbours} +çÅÎÅÒÉÒÕÅÔ ÔÁÂÌÉÃÕ ÓÏÓÅÄÓÔ× ËÌÁÓÓÏ× × ÕËÁÚÁÎÎÏÊ ËÁÒÔÅ. +\subsection{outtable}\label{outtable} +\obsoletes{OUTTABLE} +\subsection{reclass1}\label{reclass1} +\obsoletes{RECLASS (ÏÄÎÏÆÁÊÌÏ×ÙÊ)} +óÏÚÄÁÅÔ ÎÏ×ÕÀ ËÁÒÔÕ ÎÁ ÂÁÚÅ ÎÁÂÏÒÁ ÐÒÁ×ÉÌ Ó ÓÉÎÔÁËÓÉÓÏÍ ÜË×É×ÁÌÅÎÔÙÍ +ËÏÍÁÎÄÅ RECLASS EPPL7. +\subsection{transform}\label{transform} +\obsoletes{RESAMPLE, RESCALE, FILL} +ðÒÅÏÂÒÁÚÕÅÔ ËÁÒÔÕ ÉÚ ÏÄÎÏÊ ËÏÏÒÄÉÎÁÔÎÏÊ ÓÉÓÔÅÍÙ × ÄÒÕÇÕÀ É/ÉÌÉ ÍÅÎÑÅÔ +ÒÁÚÍÅÒ ÑÞÅÊËÉ. +\subsection{window}\label{window} +\obsoletes{window} +÷ÙÒÅÚÁÅÔ ÆÒÁÇÍÅÎÔ ÉÚ ËÁÒÔÙ. +\end{document} diff --git a/doc/layers.doc b/doc/layers.doc new file mode 100644 index 0000000..babf47f --- /dev/null +++ b/doc/layers.doc @@ -0,0 +1,91 @@ +Guidelines to impliment layers + +New types of layer can be defined in fgis using + +layer typedef command + +They should implement following commands + +1. info option + Obligatory + Returns boolean value indicating that certain operation + are supported by this layer. + Required options are + + opaque - layer could be displayed as base layer in planchet + lookable - layer could be inserted in planchet look list + legend - legend of this layer can be drawn by drawlegend command + limits - layer have working limits command + numeric - values of layer are subject of arithmetic operations + dimension - returns 0 if layer defined on the set of point, + 1 on set of lines (i.e. vector file) + 2 on continuous area (i.e. raster) + reclass - if it is raster layer, returns true if counting operation + should use reclass table otherwise can return anything +2. dump + Obligatory + Returns TCL script which can be used to reimplement this layer + using layer load command. + This script would be executed at global level with value of + variable fgisLayerName set to desired name of this layer. + All objects which could be neccessary for existance of layer + (i.e. legends, palettes, pattern sets) should be recreated + by this script. (it is assumed that all neccessary files exist + in same locations) + +3. value x y ?flag? + If lookable is true + Returns value of layer at given point +k + Flag can be one of following + -raw - return value + -list - return two-element list consisting of layer title and value + -titled -return string as you like to appear in look window + presumable results of + [join [$layer value $x $y -list] ": "] + If layer is not defined in given point, this command should return + empty string. + +4.show planchet mode + obligatory + should record information that layer is visible in specified planchet + and optionally create certain items in this planchet which are persistent. + These items should have same tag as layer name (may be among other tags) + mode is either -base or -overlay +5.hide planchet + obligatory + removes information that layer is visible in planchet. It is up to + planchet to remove all related items +6.redraw planchet + obligatory + Do all neccessary things to redraw itself in planchet, including + deletion of items which are no more applicable. + +7.configure option arg ?option arg? + obligatory + changes properties of layer and issues redraw command for all planchets, + where layer is currently visible, if this changes can affect view + +8. legclasses + if [$layer info legend] is true + returns list of classes, which should be drawn by drawlegend +9 sample canvas index x y ?mode? + if [$layer info legend] is true + given index from list returned from legclasses, canvas and coordinates + should draw sample of itself. All items constituting this sample should + have tag $layername$index + mode is either -base or -overlay +10 legtext index + if [$layer info legend] is true + returns text to draw near the sample +11 title +12 subtitle + Returns string to draw as title or subtitle of legend +13 expand list + given list of two-element lists + rasterclass area + return list of two-element lists + value area. +14 delete + Obligatory - destroys itself + diff --git a/doc/levels.eps b/doc/levels.eps new file mode 100644 index 0000000..7840c8e --- /dev/null +++ b/doc/levels.eps @@ -0,0 +1,147 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: levels.fig +%%Creator: fig2dev Version 3.1 Patchlevel 2 +%%CreationDate: Thu Jul 9 23:48:13 1998 +%%For: vitus@wagner (Victor Wagner,,,135-46-61,) +%Magnification: 1.00 +%%Orientation: Landscape +%%BoundingBox: 0 0 277 263 +%%Pages: 0 +%%BeginSetup +%%IncludeFeature: *PageSize Letter +%%EndSetup +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +-57.0 -161.0 translate + 90 rotate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def +%%EndProlog + +$F2psBegin +10 setmiterlimit +n 0 612 m 0 0 l 792 0 l 792 612 l cp clip + 0.06000 0.06000 sc +7.500 slw +% Polyline +n 3900 975 m 5700 975 l 5700 1575 l 3900 1575 l cp gs col-1 s gr +% Polyline +n 5250 2175 m 7050 2175 l 7050 2850 l 5250 2850 l cp gs col-1 s gr +% Polyline +n 2700 2100 m 4500 2100 l 4500 2775 l 2700 2775 l cp gs col-1 s gr +% Polyline +n 2700 3000 m 4500 3000 l 4500 3525 l 2700 3525 l cp gs col-1 s gr +% Polyline +n 3525 3900 m 6300 3900 l 6300 4500 l 3525 4500 l cp gs col-1 s gr +% Polyline +n 3525 4950 m 6300 4950 l 6300 5550 l 3525 5550 l cp gs col-1 s gr +30.000 slw +% Polyline +n 4800 4500 m 4800 4950 l gs col-1 s gr +% Polyline +n 3900 3525 m 3900 3900 l gs col-1 s gr +% Polyline +n 5925 2850 m 5925 3900 l gs col-1 s gr +% Polyline +n 3900 2775 m 3900 3000 l gs col-1 s gr +% Polyline +n 4350 1575 m 4350 2100 l gs col-1 s gr +% Polyline +n 5550 1575 m 5550 2175 l gs col-1 s gr +% Polyline +n 3600 4950 m 3600 4725 l 3375 4725 l 3375 3525 l gs col-1 s gr +7.500 slw +% Polyline + [66.7] 0 sd +n 4500 3375 m 5625 2850 l gs col-1 s gr [] 0 sd +/Times-Roman ff 180.00 scf sf +4725 1350 m +gs 1 -1 sc (Data files) dup sw pop 2 div neg 0 rm col-1 sh gr +/Times-Roman ff 180.00 scf sf +6075 2625 m +gs 1 -1 sc (Utilities) dup sw pop 2 div neg 0 rm col-1 sh gr +/Times-Roman ff 180.00 scf sf +3600 2550 m +gs 1 -1 sc (Low-level Tcl objects) dup sw pop 2 div neg 0 rm col-1 sh gr +/Times-Roman ff 180.00 scf sf +3600 3375 m +gs 1 -1 sc (Layers) dup sw pop 2 div neg 0 rm col-1 sh gr +/Times-Roman ff 180.00 scf sf +4800 4350 m +gs 1 -1 sc (User-level Tcl commands) dup sw pop 2 div neg 0 rm col-1 sh gr +/Times-Roman ff 180.00 scf sf +4725 5400 m +gs 1 -1 sc (Graphic user interface) dup sw pop 2 div neg 0 rm col-1 sh gr +$F2psEnd +rs diff --git a/doc/levels.fig b/doc/levels.fig new file mode 100644 index 0000000..c16b10a --- /dev/null +++ b/doc/levels.fig @@ -0,0 +1,56 @@ +#FIG 3.1 +Portrait +Center +Inches +1200 2 +6 2700 2100 4500 2775 +2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 + 2700 2100 4500 2100 4500 2775 2700 2775 2700 2100 +4 1 -1 0 0 0 12 0.0000 4 180 1680 3600 2550 Low-level Tcl objects\001 +-6 +6 5250 2175 7050 2850 +2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 + 5250 2175 7050 2175 7050 2850 5250 2850 5250 2175 +4 1 -1 0 0 0 12 0.0000 4 135 615 6075 2625 Utilities\001 +-6 +6 2700 3000 4500 3525 +2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 + 2700 3000 4500 3000 4500 3525 2700 3525 2700 3000 +4 1 -1 0 0 0 12 0.0000 4 180 525 3600 3375 Layers\001 +-6 +6 3525 3900 6300 4500 +2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 + 3525 3900 6300 3900 6300 4500 3525 4500 3525 3900 +4 1 -1 0 0 0 12 0.0000 4 135 1980 4800 4350 User-level Tcl commands\001 +-6 +6 3525 4950 6300 5550 +2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 + 3525 4950 6300 4950 6300 5550 3525 5550 3525 4950 +4 1 -1 0 0 0 12 0.0000 4 180 1695 4725 5400 Graphic user interface\001 +-6 +6 3900 300 5700 900 +2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 + 3900 300 5700 300 5700 900 3900 900 3900 300 +4 1 -1 0 0 0 12 0.0000 4 135 750 4725 675 Data files\001 +-6 +2 1 0 3 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 4800 4500 4800 4950 +2 1 0 3 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 3900 3525 3900 3900 +2 1 0 3 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 5925 2850 5925 3900 +2 1 0 3 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 3900 2775 3900 3000 +2 1 0 3 -1 7 0 0 -1 0.000 0 0 -1 0 0 4 + 3600 4950 3600 4725 3375 4725 3375 3525 +2 1 1 1 -1 7 0 0 -1 4.000 0 0 -1 0 0 2 + 4500 3375 5625 2850 +2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 + 3900 1200 6225 1200 6225 1800 3900 1800 3900 1200 +2 1 0 3 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 4200 1800 4200 2100 +2 1 0 3 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 5775 1800 5775 2175 +2 1 0 3 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 4875 900 4875 1200 +4 1 -1 0 0 0 12 0.0000 4 180 1485 5025 1575 Data access library\001 diff --git a/doc/levels.gif b/doc/levels.gif new file mode 100644 index 0000000000000000000000000000000000000000..c4b1bb78f07f0ff8cf9dd32d78d9809d167d6389 GIT binary patch literal 2540 zcmVJz&S&%EQJIsG27<2(AjKhgJx5h&kh3s;L;rUU2NZBh5G-jDzG`aRb7 zuV4>(2OIts_^{#%g%>-P(D*Ql z>-x3c*s{IGy^TA!?%h~SX9nea^l#vxhifuU33+ni!HYNVtXviI>Cm5Rj_wFMBJJC$ zS9k9HGIv_x#S>O}t6kz5;|0M&7X6!!_PIVpt8_!YvGUFS_Hi4S*gpbBLm+(e{imKl z?sQ`j2=p0ZA3O9Yq|HVTSva9a87_2TKNWpvlz;t{v&@JYF*x8k8#V;sJL@UMpEWCL zR1bw3-e^aP{>_Ntf+Re+$9w+pSmTTxs>h>|7;WUukJf46%a95Z^o>b6lDLvTRdxd) zIl?e_qk~Vr#0-#lm}x^bXfmSHiy?vsVw~p1_}H3p*x3f2dD2-YpQQP@n4bBJIhmk? z!YQX`gofrDZ;n0+X{6}Y_5f{+xJl`cn7X%VrfYO+2&kT(XDF$oiX`fpsh$eus+X3E zm8EyO%BobfK67iWiR3B?ue#>pt4zWE>VT}c!dm{7v3U+lY$eQ6^lY<$L<n~%2Af-9`Ibcs6(xm~OEL_4T6gx@7#R*xUaUC^uyhg)hek^fVZIXO4!YQ*? za-}Vc^fF~J-@7tnGw)k-A~*k=^8_G^neomQ3XC$*DjUsm&k>M>%2^{E*~v(&`RfVb=2T|DUI7xdZ}VbVmFDUmjsr>64x>O z93k4&DA{#~Ns7HS;f6C=B-RsKjdmV(|v6(&Qjy>)%~@meaB zIKsW9-C0_HJ&k(X-PprCFQ`&5;)6M$P!_uvc<5dm-(!!B--Gs<=~w+d`&)O8_unG3 zIlun(*SI+7MGYbG3yJq?GB+Cm5N}rUAIBiKF$9*cH!DF9(;ipAi5$>j`_mxuMwY>Y zY!HMGTpL~>n7ee0(10Bj;Rjh5LVT>ygE3U$3u#zFusM)}HN3_QU1%$V2~mhQ1Y&a3 zH6Ij~D@aNl1G%zd!dxJ6KRSHH{uFUA#4HxB6J%IL%}7J*q$ zER-5)@y5Bd(G#KrBO0^!sXIdJj%tddTIRSJKjue^gp?E(K>|ptMDYwUN#q)vxUMnk zu|EYNiX)*|MKTCdORs=r3-PkaBFb<(p;TKY>yVjC4q=j??B5_I=}Ftba*<90f-1QZ zOHRt7lar)GIdvh{?Q^b01iWZ6ktrVW|h0i~V*cT47-Fei{9rm31aO*$TPkIBrY z_5Q=alh_2B*0dc4mB+cn!K`cD>L&cAl_0)3#C#B$6)@kaKpM?%oTR+xI@`Csc`zh} z$%CUmHA%h(V&;0$ELKDQc~MRR@?w_;bte{aSy5~r5~IJgs4t~>P#l8PqaqDeNR2pB zjgl~>)qydm$cAz zE_uIeUeuNsSkfB=Cnngvfi*I`)D7EieYU&zS(j%2ge`iPc3%M7_qGI<=)BG=UbeZU zF5+k{I8VY|+Id7r;^PRF_9oB*O?Q2?U9W-_m%r43IC$uc-H2u9z6=#qz5o620E)c^TXoO*hWE3k|#m|dihgrC_o9j15?%DKy! z%qb06nvV>5)^L7WQ&w4#BX6Oc@t3#Hac|7w+}_b2JidU2*qS%z^UxXE<->JZKle+? zl2F`BNKQ?|TsGbBwDi6Jq6l$A&bHM@38N*Iy?rJI-fh)Bw1EyUKPu08{`7w0|u9l$Xe6)`fWAzcC9*oeU5R| zYn<_`XZg!rPjc0p94MyO-M0dc``mk>-@Na=?|%>c;0u5F#4o<_kB|K1EB`SC002A5 C1OS!* literal 0 HcmV?d00001 diff --git a/doc/levels.pbm b/doc/levels.pbm new file mode 100644 index 0000000..bc95db4 --- /dev/null +++ b/doc/levels.pbm @@ -0,0 +1,3300 @@ +P1 +# CREATOR: XV Version 3.10a Rev: 12/29/94 +311 371 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 0 0 0 +1 1 1 0 1 1 0 0 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 +0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0 0 1 0 0 +1 0 0 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 +0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 +0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 1 0 0 1 +0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 +0 1 0 0 1 1 0 0 1 1 0 1 0 0 0 0 1 0 0 1 1 1 1 1 1 0 0 1 1 1 0 0 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 0 0 +0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 1 1 +1 0 0 0 0 0 1 0 1 1 0 0 1 1 1 0 0 1 0 1 1 0 0 1 1 0 0 1 0 1 1 1 1 0 0 +1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 +0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 +0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0 0 +1 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 +0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 1 1 0 0 1 0 0 0 1 0 1 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 +0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 1 0 0 1 0 0 +1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 +0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 +0 1 0 0 1 1 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 +0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 +1 0 1 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 0 1 1 0 0 0 +0 1 1 1 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 1 1 0 0 1 1 1 +0 0 0 1 1 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 1 1 1 1 +1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 +0 0 0 0 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 +1 0 0 1 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 +0 0 0 1 1 0 0 0 1 1 1 0 0 1 1 0 0 0 1 1 0 0 0 0 1 1 0 0 1 1 1 1 0 0 1 +1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 +1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 +0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 +0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 +0 0 1 1 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 1 1 1 1 0 0 1 0 1 1 0 0 1 1 +1 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 +1 0 0 1 0 0 1 0 0 1 1 1 1 0 0 1 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 1 0 1 1 0 0 1 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 1 +0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 +1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 +0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 1 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 1 1 0 0 0 1 1 0 0 1 0 1 0 0 0 +0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 +0 1 1 0 0 1 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 0 +0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 1 0 0 0 0 0 1 1 1 0 1 1 1 0 0 0 0 0 1 +1 1 0 0 0 0 1 1 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 0 0 1 0 0 0 1 1 +1 0 0 0 1 1 0 0 0 0 1 1 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 1 0 1 1 1 1 1 1 0 0 1 0 1 1 0 1 1 1 1 1 1 0 0 0 1 1 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 1 1 1 0 0 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 +1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 1 0 0 0 +1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 +1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 +1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 +1 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 1 0 1 1 +0 0 1 1 1 1 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 1 0 0 0 1 0 +0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 1 1 0 0 1 0 +1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1 0 1 1 1 0 0 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 1 1 0 0 0 0 +0 0 0 0 1 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 1 0 +0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 1 0 1 1 0 1 1 0 0 +1 0 1 1 0 1 1 0 0 0 0 1 1 0 0 1 0 1 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 +1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 +0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 +1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 1 0 0 1 1 0 0 0 0 1 1 1 1 0 0 1 0 0 0 1 1 1 1 1 0 0 1 0 0 1 +1 1 1 0 0 1 0 1 1 0 0 1 1 1 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 +0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 +0 0 0 1 1 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 1 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 +0 1 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 +0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 +0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 +1 0 0 1 0 0 1 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 1 1 +0 0 0 1 1 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 +0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 +1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1 1 1 0 +0 0 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 1 0 0 0 0 0 +1 1 1 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 1 0 0 0 0 0 1 1 0 0 +0 0 1 1 0 0 1 1 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 1 1 1 0 1 +1 0 0 1 1 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 +0 0 1 1 1 0 0 1 1 0 0 0 1 1 0 0 0 0 0 1 1 0 1 1 0 0 0 1 1 1 0 0 0 1 1 +0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 1 0 1 1 1 1 1 +0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 +0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 +1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 1 0 0 1 0 0 0 1 0 +0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 +1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 1 0 0 0 0 1 1 1 1 0 0 1 0 0 0 0 +0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 1 1 1 0 0 1 0 0 0 1 0 0 0 0 1 1 1 0 0 +1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 +0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 +0 1 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 +1 1 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 +0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 1 0 0 +1 0 0 1 0 0 0 1 1 0 0 1 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 1 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 +1 1 1 0 0 0 1 1 0 1 0 1 1 1 0 0 1 1 1 0 1 1 1 1 1 0 0 1 1 0 0 0 0 0 0 +0 1 1 0 1 0 1 1 1 0 0 0 0 1 1 1 0 1 1 1 0 0 0 0 1 1 1 1 1 1 0 1 1 0 0 +1 1 0 0 1 1 1 0 1 1 1 0 0 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 0 1 1 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/doc/levels.xbm b/doc/levels.xbm new file mode 100644 index 0000000..c0ce86a --- /dev/null +++ b/doc/levels.xbm @@ -0,0 +1,1209 @@ +#define levels.xbm_width 311 +#define levels.xbm_height 371 +static unsigned char levels.xbm_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x20, 0x0d, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, + 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x42, 0x80, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x82, 0xcc, 0x33, 0xb8, 0x89, 0xe1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x82, 0x92, 0x48, 0x10, 0x49, 0x92, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x82, 0x9c, 0x70, + 0x10, 0xc9, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x42, 0x92, 0x48, 0x10, 0x49, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x62, 0x92, 0x48, 0x10, 0xc9, 0x94, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3f, 0x2c, 0xb3, 0x90, 0x9f, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, + 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x20, 0xc8, 0x3c, 0x03, 0x86, 0x61, 0x18, 0x8e, 0x83, 0xe6, + 0x34, 0xd3, 0x33, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, 0x28, 0x89, 0x04, 0x49, 0x92, 0x24, + 0x49, 0x82, 0x24, 0x99, 0x64, 0x12, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, 0xc8, 0x09, 0x07, + 0x4e, 0x10, 0x3c, 0xc3, 0x80, 0x24, 0x09, 0x27, 0x1a, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, + 0x24, 0x89, 0x04, 0x49, 0x10, 0x04, 0x0c, 0x83, 0x24, 0x89, 0x24, 0x0a, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x20, 0x26, 0x89, 0x04, 0x49, 0x92, 0x4c, 0x49, 0x82, 0x24, + 0x89, 0x24, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0xf0, 0xc3, 0x32, 0x0b, 0x96, 0x61, 0x38, + 0xc7, 0xc1, 0xef, 0x1c, 0x7b, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x80, 0xe1, 0x0f, 0x0c, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x42, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x21, 0x09, 0x08, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x01, 0x08, 0x80, + 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x42, 0xc0, 0xdc, 0x06, 0x88, 0x99, 0x19, 0x01, + 0xc1, 0x08, 0x8c, 0x33, 0x86, 0x79, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x42, 0x20, 0x49, 0x02, 0x48, + 0x92, 0x24, 0x01, 0x21, 0x09, 0x92, 0x24, 0x49, 0x12, 0x09, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x42, 0x20, + 0x59, 0xf3, 0xc9, 0xd3, 0x3c, 0x01, 0x21, 0x08, 0x92, 0x24, 0x4f, 0x10, + 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, + 0x73, 0xd0, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x42, 0x20, 0x51, 0x01, 0x48, 0x50, 0x04, 0x01, 0x21, 0x08, 0x92, + 0x24, 0x41, 0x10, 0x0c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x42, 0x24, 0xb1, 0x00, 0xc8, 0x64, 0x4c, 0x01, + 0x21, 0x09, 0x92, 0x24, 0x53, 0x12, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xe2, 0xc7, 0x90, 0x00, 0x9c, + 0x23, 0xb8, 0x83, 0xc3, 0x1c, 0x8c, 0x23, 0x8e, 0x61, 0x07, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x9f, 0xf6, + 0x63, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x21, 0x91, 0x24, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x91, 0x24, 0xf2, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x91, 0x24, 0x12, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x33, 0x91, 0x24, + 0x32, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0xfe, 0xcf, 0xe7, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x66, 0xa6, 0x39, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x90, 0x24, + 0xc9, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xe0, 0x34, 0x4f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x90, 0x14, 0x41, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x92, 0x18, 0x53, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x63, 0x09, + 0xee, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x01, 0x00, 0x70, 0x0e, 0x00, 0x00, 0x18, 0x00, 0x00, 0xc3, + 0x1f, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x20, 0x04, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x42, 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x20, 0x04, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, + 0x00, 0x20, 0xc4, 0x31, 0x0d, 0x10, 0x33, 0x33, 0x02, 0x82, 0x11, 0x18, + 0xa6, 0x4d, 0x1b, 0xa6, 0xe1, 0x38, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x01, 0x00, 0x20, 0x24, 0x49, 0x06, 0x90, 0x24, 0x49, 0x02, + 0x42, 0x12, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x20, 0x64, 0x78, 0xe2, 0x93, + 0xa7, 0x79, 0x02, 0x42, 0x10, 0x04, 0x49, 0x92, 0x24, 0x4e, 0x92, 0x0c, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x20, 0x84, + 0x09, 0x02, 0x90, 0xa0, 0x08, 0x02, 0x42, 0x10, 0x04, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x30, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, + 0x00, 0x60, 0x26, 0x99, 0x02, 0x90, 0xc9, 0x98, 0x02, 0x42, 0x12, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x01, 0x00, 0xc0, 0xe3, 0x70, 0x07, 0x38, 0x47, 0x70, 0x07, + 0x87, 0x39, 0x18, 0xe6, 0xf6, 0x6d, 0xf6, 0x66, 0x1d, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x5c, + 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x66, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x42, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x9a, 0x79, 0x9c, + 0x31, 0xd8, 0x38, 0xa6, 0xb1, 0xe6, 0x99, 0x3e, 0x86, 0x61, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xe1, + 0x4c, 0x92, 0x24, 0x49, 0x90, 0x24, 0xc9, 0x20, 0x49, 0x24, 0x13, 0x49, + 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x41, 0x84, 0x93, 0x24, 0x09, 0x90, 0x0c, 0x4f, 0x20, 0x49, + 0x3c, 0x11, 0x4e, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x42, 0x44, 0x92, 0x24, 0x09, 0x90, 0x30, + 0x41, 0x20, 0x49, 0x04, 0x11, 0x49, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x66, 0x44, 0x92, 0x24, + 0x49, 0x90, 0x24, 0x53, 0x20, 0x49, 0x4c, 0x11, 0x49, 0x32, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x3c, + 0x8e, 0x75, 0xee, 0x33, 0x60, 0x1d, 0xee, 0xf0, 0x9b, 0xb9, 0x13, 0x96, + 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/doc/lib_doc.tex b/doc/lib_doc.tex new file mode 100644 index 0000000..fb4a8b3 --- /dev/null +++ b/doc/lib_doc.tex @@ -0,0 +1,1196 @@ +\documentclass{report} +\usepackage[koi8-r]{inputenc} +\usepackage[russian]{babel} +\newcommand{\function}[1]{\par\smallskip{\raggedright\setlength{\hangindent}{2cm}\noindent\tt #1\par} \smallskip} +\newcommand{\var}[2]{\par\smallskip{\setlength{\hangindent}{1cm}\noindent\tt#1\rm~--- #2\par} \smallskip} +\textwidth=6.3in +\oddsidemargin=0.5in +\title{âÉÂÌÉÏÔÅËÁ ÄÌÑ ÒÁÂÏÔÙ\\ Ó ÆÁÊÌÁÍÉ EPPL7.\\òÕËÏ×ÏÄÓÔ×Ï ÐÒÏÇÒÁÍÍÉÓÔÁ} +\author{÷.â.~÷ÁÇÎÅÒ} +\makeindex +\begin{document} +\maketitle +\tableofcontents +\chapter*{÷×ÅÄÅÎÉÅ}\addcontentsline{toc}{chapter}{÷×ÅÄÅÎÉÅ} + +âÉÂÌÉÏÔÅËÁ ÐÒÅÄÎÁÚÎÁÞÅÎÁ ÄÌÑ ÒÁÂÏÔÙ Ó ×ÅËÔÏÒÎÙÍÉ É ÒÁÓÔÒÏ×ÙÍÉ +ÆÁÊÌÁÍÉ EPPL7 ÉÚ ÐÒÏÇÒÁÍÍ ÎÁ ÑÚÙËÅ C. âÉÂÌÉÏÔÅËÁ ÒÁÓÞÉÔÁÎÁ ÎÁ +ÒÁÂÏÔÕ × 32-ÒÁÚÒÑÄÎÏÊ ÓÒÅÄÅ. ÷ ÐÒÉÎÃÉÐÅ ÎÅÂÏÌØÛÉÅ ÐÒÏÇÒÁÍÍÙ +ÓÐÏÓÏÂÎÙ ÒÁÂÏÔÁÔØ É × 16-ÒÁÚÒÑÄÎÏÊ ÓÒÅÄÅ, ÎÏ ÐÏÓËÏÌØËÕ ÓÐÅÃÉÁÌØÎÙÈ +ÍÅÒ ÄÌÑ ÜÔÏÇÏ ÎÅ ÐÒÉÎÉÍÁÌÏÓØ, ÒÁÂÏÔÁ × ÍÏÄÅÌÑÈ ÐÁÍÑÔÉ Compact, Large +É Huge ÎÅ ÇÁÒÁÎÔÉÒÕÅÔÓÑ. + +÷ ÂÉÂÌÉÏÔÅËÁÈ ÐÒÅÄÕÓÍÏÔÒÅÎ ËÏÄ ÄÌÑ ÒÁÂÏÔÙ ÎÁ ÐÒÏÃÅÓÓÏÒÁÈ Ó +ÐÒÑÍÙÍ ÐÏÒÑÄËÏÍ ÂÁÊÔ (MSB First), ÈÏÔÑ ÏÎ ÐÏËÁ ÎÅ ÏÔÔÅÓÔÉÒÏ×ÁÎ. + +ôÅÍ ÎÅ ÍÅÎÅÅ ÎÅ ÒÅËÏÍÅÎÄÕÅÔÓÑ ÉÓÐÏÌØÚÏ×ÁÔØ ÞÉÔÁÔØ ÆÁÊÌÙ EPPL7 ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÏ, +ÔÁË ËÁË ÐÒÉ ÜÔÏÍ ÐÒÉÄÅÔÓÑ ÏÂÒÁÝÁÔØ ×ÎÉÍÁÎÉÅ ÎÁ ÐÏÒÑÄÏË ÂÁÊÔÏ× × ÓÌÏ×Å. + +ðÏÓËÏÌØËÕ ÏÒÉÇÉÎÁÌØÎÙÊ ÐÁËÅÔ EPPL7 ÒÁÂÏÔÁÌ ÐÏÄ DOS, ×ÓÅ ÅÇÏ ÆÁÊÌÙ, +ÈÒÁÎÑÝÉÅÓÑ × Ä×ÏÉÞÎÏÍ ÆÏÒÍÁÔÅ ÉÓÐÏÌØÚÕÀÔ ÐÏÒÑÄÏË ÂÁÊÔÏ× ÐÒÏÃÅÓÓÏÒÁ Intel~--- +ÍÌÁÄÛÉÊ ÂÁÊÔ ÐÅÒ×ÙÍ. + + +âÉÂÌÉÏÔÅËÉ ÎÅ ÉÓÐÏÌØÚÕÀÔ ÓÉÓÔÅÍÎÙÈ ×ÙÚÏ×Ï× É ÂÉÂÌÉÏÔÅÞÎÙÈ ÆÕÎËÃÉÊ, +ÓÐÅÃÉÆÉÞÎÙÈ ÄÌÑ UNIX\footnote{úÁ ÉÓËÌÀÞÅÎÉÅÍ ÕÔÉÌÉÔ ÄÌÑ ÒÁÂÏÔÙ Ó ÆÁÊÌÏ×ÏÊ +ÓÉÓÔÅÍÏÊ É ÏÂÒÁÂÏËÉ ÐÒÅÒÙ×ÁÎÉÑ ÐÒÏÇÒÁÍÍÙ. üÔÉ ÆÕÎËÃÉÉ ÌÏËÁÌÉÚÏ×ÁÎÙ +× ÍÏÄÕÌÅ {\tt file\_utils.c} É ÏÐÉÓÁÎÙ × ÇÌÁ×Å \ref{utils}}. + +ðÒÉ ÒÁÚÒÁÂÏÔËÅ ÂÉÂÌÉÏÔÅË ÐÒÅÄÐÏÌÁÇÁÌÏÓØ, ÞÔÏ ÔÉÐ {\tt long int} ÉÍÅÅÔ +ÒÁÚÍÅÒ 32 ÂÉÔÁ, {\tt short int}~--- 16 ÂÉÔ É {\tt double}~--- 64 ÂÉÔÁ, +× ÆÏÒÍÁÔÅ, ÕÄÏ×ÌÅÔ×ÏÒÑÀÝÅÍ ÓÔÁÎÄÁÒÔÕ IEEE. + +\chapter{ìÏÇÉÞÅÓËÁÑ ÍÏÄÅÌØ ÆÁÊÌÏ× ÄÁÎÎÙÈ} +\section{òÁÓÔÒ} + +ôÅÏÒÅÔÉÞÅÓËÉ, ÒÁÓÔÒÏ×ÁÑ ËÁÒÔÁ Ñ×ÌÑÅÔÓÑ ÆÕÎËÃÉÅÊ ÏÔ ËÏÏÒÄÉÎÁÔ, +ÚÎÁÞÅÎÉÑ ËÏÔÏÒÏÊ Ñ×ÌÑÀÔÓÑ ÞÉÓÌÁÍÉ ÉÌÉ ÜÌÅÍÅÎÔÁÍÉ ÎÅËÏÔÏÒÏÇÏ +ËÏÎÅÞÎÏÇÏ ÍÎÏÖÅÓÔ×Á, ÏÐÒÅÄÅÌÅÎÎÏÊ ×ÎÕÔÒÉ ÎÅËÏÔÏÒÏÊ ÇÅÏÍÅÔÒÉÞÅÓËÏÊ +ÆÉÇÕÒÙ ÎÁ ÄÅËÁÒÔÏ×ÏÊ ËÏÏÒÄÉÎÁÔÎÏÊ ÐÌÏÝÁÄÉ. + +ðÒÁËÔÉÞÅÓËÉ ËÁË ÏÂÌÁÓÔØ ÏÐÒÅÄÅÌÅÎÉÑ, ÔÁË É ÏÂÌÁÓÔØ ÚÎÁÞÅÎÉÊ +Ë×ÁÎÔÕÀÔÓÑ, Á ÃÅÌØÀ ÂÉÂÌÉÏÔÅËÉ Ñ×ÌÑÅÔÓÑ ×ÏÚÍÏÖÎÏÓÔØ +ÐÒÏÉÚ×ÏÌØÎÙÍ ÏÂÒÁÚÏÍ ÚÁÄÁ×ÁÔØ ÚÎÁÞÅÎÉÑ ÒÁÓÔÒÁ × ÌÀÂÏÊ ÎÕÖÎÏÊ ÔÏÞËÅ. + + +ðÏÜÔÏÍÕ, ÒÁÓÔÒÏ×ÙÅ ÆÁÊÌÙ EPPL7 (epp) ÒÁÓÓÍÁÔÒÉ×ÁÀÔÓÑ ËÁË ÂÏÌØÛÁÑ ÍÁÔÒÉÃÁ +ËÏÒÏÔËÉÈ (16-ÂÉÔ) ÃÅÌÙÈ. òÁÚÍÅÒÙ ÍÁÔÒÉÃÙ ÍÏÇÕÔ ÄÏÓÔÉÇÁÔØ $30000\times30000$ +Á ÚÎÁÞÅÎÉÑ - ÐÒÉÎÉÍÁÔØ ÌÀÂÏÅ ÚÎÁÞÅÎÉÅ, ÄÏÐÕÓÔÉÍÏÅ ÄÌÑ ÔÉÐÁ +{\tt unsigned short} Ô.Å. 0--65535. + +óÏÏÔ×ÅÔÓÔ×ÉÅ ÍÅÖÄÕ ×ÅÝÅÓÔ×ÅÎÎÙÍÉ ËÁÒÔÏÇÒÁÆÉÞÅÓËÉÍÉ +ËÏÏÒÄÉÎÁÔÁÍÉ É ÃÅÌÏÞÉÓÌÅÎÙÍÉ ÉÎÄÅËÓÁÍÉ × ÍÁÔÒÉÃÅ (ÒÑÄÁÍÉ É ËÏÌÏÎËÁÍÉ) +ÈÒÁÎÉÔÓÑ × ÚÁÇÏÌÏ×ËÅ epp-ÆÁÊÌÁ, É × ÂÉÂÌÉÏÔÅËÅ ÐÒÅÄÕÓÍÏÔÒÅÎÙ ÆÕÎËÃÉÉ +ÄÌÑ ÐÅÒÅÓÞÅÔÁ ÏÄÎÉÈ × ÄÒÕÇÉÅ. + +îÏÍÅÒÁ ÒÑÄÏ×/ËÏÌÏÎÏË × ÆÁÊÌÅ ÎÅ ÏÂÑÚÁÔÅÌØÎÏ ÎÁÞÉÎÁÀÔÓÑ Ó ÅÄÉÎÉÃÙ. +äÌÑ ÎÉÈ ÄÏÐÕÓÔÉÍÙ ÌÀÂÙÅ ÚÎÁÞÅÎÉÑ × ÄÉÁÐÁÚÏÎÅ -32767--+32767. + +üÔÏ ÐÏÚ×ÏÌÑÅÔ × ÆÁÊÌÅ, ÐÏËÒÙ×ÁÀÝÅÍ ÎÅÂÏÌØÛÎÏÊ ÕÞÁÓÔÏË ÔÅÒÒÉÔÏÒÉÉ ÉÍÅÔØ +ÓÏ×ÍÅÓÔÉÍÏÓÔØ Ó Â\`ÏÌØÛÉÍ ÆÁÊÌÏÍ ÎÅ ÔÏÌØËÏ ÐÏ ÁÌØÔÅÒÎÁÔÉ×ÎÙÍ ËÏÏÒÄÉÎÁÔÁÍ, +ÎÏ É ÐÏ ÎÏÍÅÒÁÍ ÒÑÄÏ×/ËÏÌÏÎÏË. + +ïÂÙÞÎÏ ÑÞÅÊËÉ × ÆÁÊÌÅ Ë×ÁÄÒÁÔÎÙÅ, ÈÏÔÑ ×ÓÅ ÐÒÏÃÅÄÕÒÙ ÂÉÂÌÉÏÔÅËÉ +ÂÕÄÕÔ ËÏÒÒÅËÔÎÏ ÒÁÂÏÔÁÔØ Ó ÆÁÊÌÁÍÉ, × ËÏÔÏÒÙÈ ÒÁÚÍÅÒÙ ÑÞÅÊËÉ ÐÏ ×ÅÒÔÉËÁÌÉ +É ÐÏ ÇÏÒÉÚÏÎÔÁÌÉ ÒÁÚÌÉÞÎÙ. + +úÎÁÞÅÎÉÅ ÐÌÏÝÁÄÉ ÑÞÅÊËÉ ×ÍÅÓÔÅ Ó ÒÁÚÍÅÒÎÏÓÔØÀ (Ë×ÁÄÒÁÔÎÙÅ ÍÅÔÒÙ, ÆÕÔÙ, +ÇÅËÔÁÒÙ É ÄÒ.) ÈÒÁÎÉÔÓÑ × ÚÁÇÏÌÏ×ËÅ ÆÁÊÌÁ. ìÉÎÅÊÎÙÅ ÅÄÉÎÉÃÙ ÁÌØÔÅÒÎÔÁÔÉ×ÎÙÈ +ËÏÏÒÄÉÎÁÔ ÎÉÇÄÅ ÎÅ ÏÐÉÓÙ×ÁÀÔÓÑ, ÎÏ ÄÌÑ ÓÏ×ÍÅÓÔÉÍÏÓÔÉ ÎÅ ÒÅËÏÍÅÎÄÕÅÔÓÑ +ÉÓÐÏÌØÚÏ×ÁÔØ ÎÉËÁËÉÈ ÅÄÉÎÉà ËÒÏÍÅ ÍÅÔÒÏ× ÉÌÉ ÇÒÁÄÕÓÏ× (ÅÓÌÉ ÆÁÊÌ ÈÒÁÎÉÔÓÑ +× ÇÅÏÇÒÁÆÉÞÅÓËÉÈ ËÏÏÒÄÉÎÁÔÁÈ). + +ðÒÉ ÜÔÏÍ ÐÌÏÝÁÄØ ÑÞÅÊËÉ ÍÏÖÎÏ ÐÅÒÅ×ÅÓÔÉ × ÄÒÕÇÉÅ ÅÄÉÎÉÃÙ, ÓÏÏÔ×ÅÔÓÔ×ÅÎÎÏ +ÉÚÍÅÎÉ× ËÏÄ ÒÁÚÍÅÒÎÏÓÔÉ, ÄÌÑ ÔÏÇÏ ÞÔÏÂÙ ÐÏÌÕÞÉÔØ ÂÏÌÅÅ ÕÄÏÂÏÞÉÔÁÅÍÙÅ ÞÉÓÌÁ +ÐÒÉ ÒÁÓÓÞÅÔÅ ÐÌÏÝÁÄÅÊ. + +ðÒÅÏÂÒÁÚÏ×ÁÎÉÅ ÍÎÏÖÅÓÔ×Á ÚÎÁÞÅÎÉÊ ËÁÒÔÙ × ÍÎÏÖÅÓÔ×Ï ÚÎÁÞÅÎÉÊ (ËÌÁÓÓÏ×) +epp-ÆÁÊÌÁ ÔÒÁÄÉÃÉÏÎÎÏ ÓÞÉÔÁÅÔÓÑ ÆÕÎËÃÉÅÊ ÌÅÇÅÎÄÙ, É ÎÁÈÏÄÉÔÓÑ ÚÁ +ÐÒÅÄÅÌÁÍÉ ÆÏÒÍÁÔÁ epp, Á, ÓÌÅÄÏ×ÁÔÅÌØÎÏ É ÄÁÎÎÏÊ ÂÉÂÌÉÏÔÅËÉ. + +ðÏÓËÏÌØËÕ ÍÁÔÒÉÃÁ ×ÓÅÇÄÁ ÐÒÑÍÏÕÇÏÌØÎÁ, Á ÏÂÌÁÓÔØ ÏÐÒÅÄÅÌÅÎÉÑ ËÁÒÔÙ~--- +ÎÅ ×ÓÅÇÄÁ, ÐÒÅÄÕÓÍÏÔÒÅÎÏ ÓÐÅÃÉÁÌØÎÏÅ ÚÎÁÞÅÎÉÅ, ÎÁÚÙ×ÁÅÍÏÅ offsite. + +ðÒÉ ÞÔÅÎÉÉ epp-ÆÁÊÌÁ ÐÒÅÄÐÏÌÁÇÁÅÔÓÑ, ÞÔÏ ÒÁÚÍÅÒÙ ÅÇÏ ÂÅÓËÏÎÅÞÎÙ, ÎÏ +ÐÏÐÙÔËÁ ÐÒÏÞÉÔÁÔØ ÅÇÏ ÜÌÅÍÅÎÔ ÚÁ ÐÒÅÌÁÍÉ ÒÅÁÌØÎÏÇÏ ÆÁÊÌÁ ÐÒÉ×ÏÄÉÔ +Ë ×ÏÚ×ÒÁÔÕ ÚÎÁÞÅÎÉÑ offsite, ËÏÔÏÒÏÅ ÏÚÎÁÞÁÅÔ, ÞÔÏ × ÄÁÎÎÏÊ ÔÏÞËÅ +ÚÎÁÞÅÎÉÅ ÎÅ ÏÐÒÅÄÅÌÅÎÏ. úÎÁÞÅÎÉÅ offsite Ó×ÏÅ ÄÌÑ ËÁÖÄÏÊ ËÁÒÔÙ. ïÎÏ +ÈÒÁÎÉÔÓÑ × ÚÁÇÏÌÏ×ËÅ ÆÁÊÌÁ É × ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÍ ÐÏÌÅ ÓÔÒÕËÔÕÒÙ ÄÁÎÎÙÈ, +ÉÓÐÏÌØÚÕÅÍÏÊ ÄÌÑ ÄÏÓÔÕÐÁ Ë ÆÁÊÌÕ. + +âÏÌØÛÁÑ ÞÁÓÔØ ÁÌÇÏÒÉÔÍÏ×, ÉÓÐÏÌØÚÕÅÍÙÈ ÄÌÑ ÇÅÎÅÒÁÃÉÉ ÒÁÓÔÒÏ×ÙÈ ËÁÒÔ ÉÌÉ +ÄÌÑ ÉÈ ÁÎÁÌÉÚÁ, ÎÅ ÚÁ×ÉÓÉÔ ÏÔ ÐÏÒÑÄËÁ ÏÂÈÏÄÁ ÑÞÅÅË ËÁÒÔÙ, ÈÏÔÑ É ÔÒÅÂÕÅÔ +ÐÏÌÎÏÇÏ ÉÈ ÐÅÒÅÂÏÒÁ. ÷ ÜÔÉÈ ÓÌÕÞÁÑÈ ÒÅËÏÍÅÎÄÕÅÔÓÑ ÉÓÐÏÌØÚÏ×ÁÔØ +{\it ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÙÊ} +ÐÅÒÅÂÏÒ ÐÏ ÓÔÒÏËÁÍ, ËÁË ÓÁÍÙÊ ÜËÏÎÏÍÉÞÎÙÊ ÐÏ ÐÁÍÑÔÉ. + +äÒÕÇÏÊ ÒÁÓÐÒÏÓÔÒÁÎÅÎÎÙÊ ×ÁÒÉÁÎÔ ÄÏÓÔÕÐÁ, ÜÔÏ ËÏÇÄÁ ÐÒÉ ÏÂÒÁÂÏÔËÉ ËÏÎËÒÅÔÎÏÊ +ÑÞÅÊËÉ ÒÁÓÔÒÁ ÔÒÅÂÕÅÔÓÑ ÉÎÆÏÒÍÁÃÉÑ Ï ÚÎÁÞÅÎÉÑÈ, ÓÏÄÅÒÖÁÝÉÈÓÑ × ÓÏÓÅÄÎÉÈ ÑÞÅÊËÁÈ. + +÷ ÜÔÏÍ ÒÅÖÉÍÅ ÄÏÓÔÕÐ Ë ËÁÖÄÏÊ ÓÔÒÏËÅ ÒÁÓÔÒÁ ÔÒÅÂÕÅÔÓÑ ÎÅÓËÏÌØËÏ ÒÁÚ~--- +ÓÎÁÞÁÌÁ ÐÒÉ ÏÂÒÁÂÏÔËÅ ÏÄÎÏÊ ÉÌÉ ÎÅÓËÏÌØËÉÈ ÐÒÅÄÙÄÕÝÉÈ ÓÔÒÏË, ÐÏÔÏÍ ÐÒÉ ÏÂÒÁÂÏÔËÅ +ÓÁÍÏÊ ÜÔÏÊ ÓÔÒÏËÉ, É ÎÁËÏÎÅÃ, ÐÒÉ ÏÂÒÁÂÏÔËÅ ÓÌÅÄÕÀÝÉÈ ÓÔÒÏË. äÌÑ ÔÁËÉÈ ÓÉÔÕÁÃÉÊ +ÒÅÁÌÉÚÏ×ÁÎ {\it ËÜÛÉÒÏ×ÁÎÎÙÊ} ÄÏÓÔÕÐ, ÐÒÉ ËÏÔÏÒÏÍ ÎÅÓËÏÌØËÏ ÓÔÒÏË × +ÒÁÓÐÁËÏ×ÁÎÎÏÍ ×ÉÄÅ ÈÒÁÎÑÔÓÑ × ÐÁÍÑÔÉ. + +é, ÎÁËÏÎÅÃ, ÄÌÑ ÔÁËÉÈ ÐÒÉÌÏÖÅÎÉÊ ËÁË ÉÎÔÅÒÁËÔÉ×ÎÙÅ ÒÅÄÁËÔÏÒÙ, ÒÅÁÌÉÚÏ×ÁÎ +{\it ÐÒÑÍÏÊ ÄÏÓÔÕÐ ÎÁ ÞÔÅÎÉÅ/ÚÁÐÉÓØ}. üÔÏÔ ÓÐÏÓÏ ÄÏÓÔÕÐÁ ÓÕÝÅÓÔ×ÅÎÎÏ ÍÅÄÌÅÎÎÅÅ, +ÞÅÍ ËÜÛÉÒÏ×ÁÎÎÙÊ, ÐÏÓËÏÌØËÕ ÓÔÒÏËÉ epp-ÆÁÊÌÁ ÈÒÁÎÑÔÓÑ × ÐÁÍÑÔÉ × +ÕÐÁËÏ×ÁÎÎÏÍ ×ÉÄÅ. + +äÌÑ ÕÐÒÏÝÅÎÉÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÇÏ ÐÅÒÅÂÏÒÁ ÑÞÅÅË ÓÕÝÅÓÔ×ÕÀÔ ÆÕÎËÃÉÉ-% +{\it ÉÔÅÒÁÔÏÒÙ}, ËÏÔÏÒÙÅ ÐÏÌÕÞÁÀÔ × ËÁÞÅÓÔ×Å ÐÁÒÁÍÅÔÒÁ ÆÕÎËÃÉÀ É +ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏ ÐÒÉÍÅÎÑÀÔ ÅÅ ËÏ ×ÓÅÍ ÑÞÅÊËÁÍ ÆÁÊÌÁ. + + +\section{÷ÅËÔÏÒ} + +÷ÅËÔÏÒÎÙÅ ÆÁÊÌÙ EPPL7 (dgt) ÐÒÅÄÓÔÁ×ÌÑÀÔ ÓÏÂÏÊ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÓÔØ +ÏÂßÅËÔÏ×~--- ÌÉÎÉÊ É ÔÏÞÅË. + +õÓÔÁÎÏ×ÌÅÎÉÅ ÓÏÏÔ×ÅÓÔ×ÉÑ ÍÅÖÄÕ ÏÂßÅËÔÏÍ É ËÏÏÒÄÉÎÁÔÁÍÉ ÐÒÅÄÓÔÁ×ÌÑÅÔ +ÄÌÑ ÎÉÈ ÓÕÝÅÓÔ×ÅÎÎÏ ÂÏÌÅÅ ÓÌÏÖÎÕÀ ÚÁÄÁÞÕ, ÞÅÍ ÕÓÔÁÎÏ×ÌÅÎÉÅ +ÓÏÏÔ×ÅÔÓÔ×ÉÑ ÍÅÖÄÕ ËÏÏÒÄÉÎÁÔÁÍÉ É ËÌÁÓÓÁÍÉ ÒÁÓÔÒÁ. + +äÌÑ ÂÏÌØÛÉÎÓÔ×Á ÓÐÏÓÏÂÏ× ÏÂÒÁÂÏËÉ ×ÅËÔÏÒÎÙÈ ÆÁÊÌÏ× ÔÏÖÅ ÄÏÓÔÁÔÏÞÎÏ +ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÇÏ ÐÅÒÅÂÏÒÁ ÏÂßÅËÔÏ×. + +÷ ÔÅÈ ÓÌÕÞÁÑÈ, ËÏÇÄÁ ÔÒÅÂÕÅÔÓÑ, ÎÁÐÒÉÍÅÒ, ÐÅÒÅÂÏÒ ×ÓÅÈ ÐÁÒ ÏÂßÅËÔÏ×, +ÍÏÖÎÏ ÚÁÇÒÕÚÉÔØ ×ÅËÔÏÒÎÙÊ ÆÁÊÌ × ÐÁÍÑÔØ. + +äÌÑ ×ÅËÔÏÒÎÙÈ ÆÁÊÌÏ× ÔÏÖÅ ÓÕÝÅÓÔ×ÕÀÔ ÉÔÅÒÁÔÏÒÙ, ÐÏÚ×ÏÌÑÀÝÉÅ ÐÒÉÍÅÎÉÔØ +ÐÅÒÅÄÁÎÎÕÀ ÆÕÎËÃÉÀ ËÏ ×ÓÅÍ ÌÉÎÉÑÍ, ËÏ ×ÓÅÍ ÔÏÞËÁÍ ÉÌÉ ×ÏÏÂÝÅ ËÏ +×ÓÅÍ ÏÂßÅËÔÁÍ × ÆÁÊÌÅ. + +ìÏÇÉÞÅÓËÁÑ ÓÔÒÕËÔÕÒÁ ×ÅËÔÏÒÎÏÇÏ ÆÁÊÌÁ EPPL7 ÔÁËÏ×Á: + +÷ ÅÇÏ ÚÁÇÏÌÏ×ËÅ ÏÐÒÅÄÅÌÑÅÔÓÑ ÐÒÑÍÏÕÇÏÌØÎÁÑ ÏÂÌÁÓÔØ × ËÁÒÔÏÇÒÁÆÉÞÅÓËÉÈ +(ÁÌØÔÅÒÎÁÔÉ×ÎÙÈ) ËÏÏÒÄÉÎÁÔÁÈ, ËÏÔÏÒÕÀ ÐÏËÒÙ×ÁÅÔ ÆÁÊÌ. + +÷ÎÕÔÒÉ ÆÁÊÌÁ ×ÓÅ ËÏÏÒÄÉÎÁÔÙ ÈÒÁÎÑÔÓÑ ×Ï ×ÎÕÔÒÅÎÎÉÈ ÅÄÉÎÉÃÁÈ, ÄÌÑ ËÏÔÏÒÙÈ +×ÓÅÇÄÁ ÎÉÖÎÑÑ É ÌÅ×ÁÑ ÇÒÁÎÉÃÙ ÆÁÊÌÁ ÉÍÅÀÔ ÚÎÁÞÅÎÉÅ $-32767$, Á ×ÅÒÈÎÑÑ +É ÐÒÁ×ÁÑ~--- $+32767$. üÔÏ ÏÂÅÓÐÅÞÉ×ÁÅÔ ÍÁËÓÉÍÁÌØÎÏ ×ÏÚÍÏÖÎÕÀ ÔÏÞÎÏÓÔØ +É ËÏÍÐÁËÔÎÏÓÔØ, ÎÏ ÐÒÉ×ÏÄÉÔ Ë ÐÒÏÂÌÅÍÁÍ ÐÒÉ ÒÁÓÞÅÔÅ ÒÁÓÓÔÏÑÎÉÊ É ÕÇÌÏ×, +É ÐÒÉÍÅÎÅÎÉÉ ÄÒÕÇÉÈ ÆÕÎËÃÉÊ ÁÎÁÌÉÔÉÞÅÓËÏÊ ÇÅÏÍÅÔÒÉÉ, ÐÏÓËÏÌØËÕ ×ÅÌÉÞÉÎÁ +ÅÄÉÎÉÞÎÏÇÏ ÏÔÒÅÚËÁ ÐÏ ÏÓÉ $X$ É ÐÏ ÏÓÉ $Y$ ÎÅ ÓÏ×ÐÁÄÁÀÔ. + +÷ÓÅ ÏÂßÅËÔÙ × ×ÅËÔÏÒÎÏÍ ÆÁÊÌÅ ÉÍÅÀÔ ÃÅÌÏÞÉÓÌÅÎÎÙÊ (32-ÂÉÔÎÙÊ) ÉÄÅÎÔÉÆÉËÁÔÏÒ. +îÅÄÏÐÕÓÔÉÍÙÍ ÚÎÁÞÅÎÉÅÍ ÄÌÑ ÉÄÅÎÔÉÆÉËÁÔÏÒÁ ÏÂßÅËÔÁ Ñ×ÌÑÅÔÓÑ 0, ÐÏÓËÏÌØËÕ +ÔÏÞËÁ Ó ÎÕÌÅ×ÙÍÉ ËÏÏÒÄÉÎÁÔÁÍÉ É ÎÕÌÅ×ÙÍ ÉÄÅÎÔÉÆÉËÁÔÏÒÏÍ ÉÓÐÏÌØÚÕÅÔÓÑ ËÁË +ÐÒÉÚÎÁË ËÏÎÃÁ ÆÁÊÌÁ. + +÷ÅËÔÏÒÎÙÊ ÆÁÊÌ EPPL7 ÍÏÖÅÔ ÈÒÁÎÉÔØ Ä×Á ÔÉÐÁ ÏÂßÅËÔÏ×: ÌÉÎÉÉ É ÔÏÞËÉ. + +ôÏÞËÁ ÉÍÅÅÔ Ä×Å ËÏÏÒÄÉÎÁÔÙ É ÉÄÅÎÔÉÆÉËÁÔÏÒ. + +äÌÑ ÌÉÎÉÉ ÈÒÁÎÉÔÓÑ ÉÄÅÎÔÉÆÉËÁÔÏÒ, ËÏÏÒÄÉÎÁÔÙ ÍÉÎÉÍÁÌØÎÏÇÏ ÐÒÑÍÏÕÇÏÌØÎÉËÁ, +ÚÁËÌÀÞÁÀÝÅÇÏ × ÓÅÂÅ ÌÉÎÉÀ, ÞÉÓÌÏ ÔÏÞÅË É ÎÁÂÏÒ ÐÁÒ ËÏÏÒÄÉÎÁÔ. + +ëÏÌÉÞÅÓÔ×Ï ÔÏÞÅË × ÌÉÎÉÉ ÎÅ ÍÏÖÅÔ ÐÒÅ×ÙÛÁÔØ 500. + +æÕÎËÃÉÉ ÂÉÂÌÉÏÔÅËÉ ÚÁÂÏÔÑÔÓÑ Ï ÔÏÍ, ÞÔÏÂÙ ËÏÏÒÄÉÎÁÔÙ ÏÂßÅÍÌÀÝÅÇÏ +ÐÒÑÍÏÕÇÏÌØÎÉËÁ (ÍÁÓËÉ ÌÉÎÉÉ) ÂÙÌÉ ËÏÒÒÅËÔÎÙÍÉ. + +\chapter{æÕÎËÃÉÉ ÄÏÓÔÕÐÁ Ë epp ÆÁÊÌÁÍ} + +æÕÎËÃÉÉ ÐÅÒÅÍÅÎÎÙÅ, ÎÅÏÂÈÏÄÉÍÙÅ ÄÌÑ ÄÏÓÔÕÐÁ Ë epp-ÆÁÊÌÁÍ +ÏÐÉÓÁÎÙ × ÆÁÊÌÅ {\tt epp.h}. ÷ ÎÅÍ ÏÐÉÓÁÎÁ ÓÔÒÕËÔÕÒÁ ÄÁÎÎÙÈ +{\tt EPP}, ÈÒÁÎÑÝÁÑ ÉÎÆÏÒÍÁÃÉÀ Ï ÏÔËÒÙÔÏÍ epp-ÆÁÊÌÅ. + +÷ÎÕÔÒÅÎÎÅÅ ÕÓÔÒÏÊÓÔ×Ï ÜÔÏÊ ÓÔÒÕËÔÕÒÙ ÏÐÉÓÁÎÏ × ÒÁÚÄÅÌÅ \ref{EPP-internals}. + +ðÒÁËÔÉÞÅÓËÉ ÌÅÚÔØ ×ÎÕÔÒØ ÜÔÏÊ ÓÔÒÕËÔÕÒÙ ÐÒÉ ÐÒÏÇÒÁÍÍÉÒÏ×ÁÎÉÉ +ÐÒÉËÌÁÄÎÙÈ ÚÁÄÁÞ ÎÅÔ ÎÅÏÂÈÏÄÉÍÏÓÔÉ. ÷ÓÑ ÒÁÂÏÔÁ Ó ÎÅÊ ÐÒÏÉÚ×ÏÄÉÔÓÑ +Ó ÐÏÍÏÝØÀ ÆÕÎËÃÉÊ ÂÉÂÌÉÏÔÅËÉ. + +üÔÁ ÓÔÒÕËÔÕÒÁ ÄÁÎÎÙÈ ÈÒÁÎÉÔ ÎÁÉÂÏÌÅÅ ÓÕÝÅÓÔ×ÅÎÎÕÀ ÉÎÆÏÒÍÁÃÉÀ ÉÚ +ÚÁÇÏÌÏ×ËÁ EPP-ÆÁÊÌÁ. úÎÁÞÅÎÉÑ ÔÅÈ ÐÏÌÅÊ ËÏÔÏÒÙÅ ÎÅ ÈÒÁÎÑÔÓÑ × ÜÔÏÊ +ÓÔÒÕËÔÕÒÅ, ÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ÉÌÉ ÉÚÍÅÎÉÔØ Ó ÐÏÍÏÝØÀ ÆÕÎËÃÉÊ, ÏÐÉÓÁÎÎÙÈ +× ÒÁÚÄÅÌÅ \ref{EPPHEADER}. + +\section{ðÏÌÑ ÓÔÒÕËÔÕÒÙ EPP}\index{EPP} +÷ ÜÔÏÍ ÒÁÚÄÅÌÅ ÏÐÉÓÁÎÙ ÔÏÌØËÏ ÔÅ ÐÏÌÑ, ÚÎÁÞÅÎÉÑ ËÏÔÏÒÙÈ ÄÏÓÔÁÔÏÞÎÏ +ÞÁÓÔÏ ÉÓÐÏÌØÚÕÀÔÓÑ ÐÒÉ ÒÅÁÌÉÚÁÃÉÉ ÐÒÉËÌÁÄÎÙÈ ÁÌÇÏÒÉÔÍÏ×. ïÓÔÁÌØÎÙÅ +ÐÏÌÑ É ÐÒÉÎÃÉÐÙ ÒÁÂÏÔÙ Ó ÎÉÍÉ ÏÐÉÓÁÎÙ × ÒÁÚÄÅÌÅ \ref{EPP-internals}. +÷ÓÅ ÐÏÌÑ, ÐÒÏ ËÏÔÏÒÙÅ ÎÅ ÓËÁÚÁÎÏ ÏÂÒÁÔÎÏÇÏ, ÍÏÖÎÏ ÔÏÌØËÏ ÞÉÔÁÔØ. +äÌÑ ÉÈ ÉÚÍÅÎÅÎÉÑ ÉÓÐÏÌØÚÕÊÔÅ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÅ ÆÕÎËÃÉÉ, ÐÏÓËÏÌØËÕ +ÉÚÍÅÎÅÎÉÅ ÚÎÁÞÅÎÉÊ ÎÅËÏÔÏÒÙÈ ÐÏÌÅÊ ÍÏÖÅÔ ÐÏÔÒÅÂÏ×ÁÔØ ÓÏÇÌÁÓÏ×ÁÎÎÏÇÏ +ÉÚÍÅÎÅÎÉÑ ËÁËÉÈ-ÔÏ ÄÒÕÇÉÈ. + +\index{EPP!fc}\index{EPP!lc}\index{EPP!fr}\index{EPP!lr}% +\index{fr}\index{lr}\index{fc}\index{lc}\index{shift_epp}% +\var{int fr,lr,fc,lc}{ îÏÍÅÒÁ ÐÅÒ×ÏÊ ÓÔÒÏËÉ É ËÏÌÏÎËÉ, Á ÔÁËÖÅ ÚÎÁÞÅÎÉÑ +ÎÁ ÅÄÉÎÉÃÕ ÂÏÌØÛÅ ÐÏÓÌÅÄÎÅÊ ÓÔÒÏËÉ É ËÏÌÏÎËÉ. îÁ ÅÄÉÎÉÃÕ ÂÏÌØÛÅ ÏÎÉ +ÐÏÔÏÍÕ, ÞÔÏ × ÜÔÏÍ ÓÌÕÞÁÅ ËÏÎÓÔÒÕËÃÉÉ {\tt lc $-$ fc} É {\tt lr $-$ fr} +ÄÁÀÔ ËÏÌÉÞÅÓÔ×Ï ÓÔÒÏË É ËÏÌÏÎÏË × ÆÁÊÌÅ. äÌÑ ÉÚÍÅÎÅÎÉÑ ÉÓÐÏÌØÚÕÅÔÓÑ ÆÕÎËÃÉÑ +{\tt shift\_epp} } + +\index{EPP!Xleft}\index{EPP!YBottom}\index{EPP!XRight}\index{EPP!YTop} +\index{XLeft!EPP}\index{YBottom!EPP}\index{XRight!EPP}\index{YTop!EPP} +\var{double Xleft,YBottom,XRight,YTop}{ ÁÌØÔÅÒÎÁÔÉ×ÎÙÅ (ËÁÒÏÇÒÁÆÉÞÅÓËÉÅ) +ËÏÏÒÄÉÎÁÔÙ ÇÒÁÎÉà ËÁÒÔÙ.} + +\index{EPP!offsite}\index{offsite}% +\var{int offsite}{ ÚÎÁÞÅÎÉÅ offsite. åÓÌÉ ÆÁÊÌ ÏÔËÒÙÔ ÎÁ ÚÁÐÉÓØ, ÜÔÏ + ÚÎÁÞÅÎÉÅ ÍÏÖÎÏ ÍÅÎÑÔØ.} + +\index{EPP!cell_area}\index{cell_area}% +\var{double cell\_area}{ ÐÌÏÝÁÄØ ÑÞÅÊËÉ × ÅÄÉÎÉÃÁÈ, ÕËÁÚÁÎÎÙÈ × ÚÁÇÏÌÏ×ËÅ +ÆÁÊÌÁ. óÍ. ÒÁÚÄÅÌ \ref{EPPHEADER}.} + +\index{EPP!kind}\index{kind}% +\var{int kind}{ ËÏÌÉÞÅÓÔ×Ï ÂÉÔ ÎÁ ÑÞÅÊËÕ. íÏÖÅÔ ÐÒÉÎÉÍÁÔØ ÚÎÁÞÅÎÉÑ 8 ÉÌÉ 16.} + + +éÎÆÏÒÍÁÃÉÑ ÉÚ ÚÁÇÏÌÏ×ËÁ ÆÁÊÌÁ epp, ËÏÔÏÒÁÑ ÎÅ ÐÏÐÁÌÁ × ×ÙÛÅÐÅÒÅÞÉÓÌÅÎÎÙÊ +ÓÐÉÓÏË ÐÏÌÅÊ, × ÓÔÒÕËÔÕÒÅ EPP ÎÅ ÈÒÁÎÉÔÓÑ. äÌÑ ÒÁÂÏÔÙ Ó ÎÅÊ ÎÕÖÎÏ +ÐÏÌÕÞÉÔØ ÐÏÌÎÕÀ ËÏÐÉÀ ÚÁÇÏÌÏ×ËÁ ÆÁÊÌÁ Ó ÐÏÍÏÝØÀ ÆÕÎËÃÉÉ {\tt get\_epp\_header}% +\index{get_epp_header}. + +\index{mode}\index{EPP!mode}\index{MAP_INPUT}\index{MAP_OUTPUT} +\var{int mode}{ ÒÅÖÉÍ, × ËÏÔÏÒÏÍ ÏÔËÒÙÔ ÆÁÊÌ. ëÏÍÂÉÎÁÃÉÑ ËÏÎÓÔÁÎÔ +{\tt MAP\_INPUT} É {\tt MAP\_OUTPUT}.} + + +\section{ïÔËÒÙÔÉÅ ÆÁÊÌÁ É ÒÅÖÉÍÙ ÄÏÓÔÕÐÁ} + +\index{open_epp}% +\function{EPP* open\_epp( char *filename );} + +ïÔËÒÙ×ÁÅÔ ÆÁÊÌ Ó ÉÍÅÎÅÍ {\tt filename} É ×ÏÚ×ÒÁÝÁÅÔ ÕËÁÚÁÔÅÌØ ÎÁ +ÓÔÒÕËÔÕÒÕ EPP. æÁÊÌ ÄÏÌÖÅÎ ÓÕÝÅÓÔ×Ï×ÁÔØ. òÅÖÉÍ ÏÔËÒÙÔÉÑ ÕÓÔÁÎÁ×ÌÉ×ÁÅÔÓÑ +× {\tt MAP\_INPUT}. + +\index{fopen_epp}% +\function{EPP* fopen\_epp(FILE *f);} +ïÔËÒÙ×ÁÅÔ ÆÁÊÌ ÁÎÁÌÏÇÉÞÎÏ {\tt open\_epp}, ÎÏ ÐÏÌÕÞÁÅÔ × ËÁÞÅÓÔ×Å +ÐÁÒÁÍÅÒÁ ÎÅ ÉÍÑ, Á ÕËÁÚÁÔÅÌØ ÎÁ ÓÔÒÕËÔÕÒÕ FILE. üÔÏ ÐÏÚ×ÏÌÑÅÔ +ÉÓÐÏÌØÚÏ×ÁÔØ ÄÌÑ ÐÅÒÅÄÁÞÉ ÒÁÓÔÒÏ×ÏÊ ÉÎÆÏÒÍÁÃÉÉ ÎÅ ÔÏÌØËÏ ÉÍÅÎÏ×ÁÎÎÙÅ +ÆÁÊÌÙ ÎÁ ÄÉÓËÅ. äÅÓËÒÉÐÔÏÒ ÆÁÊÌÁ f ÄÏÌÖÅÎ ÄÏÐÕÓËÁÔØ ÐÏÚÉÃÉÏÎÉÒÏ×ÁÎÉÅ. + +\index{creat_epp} +\function{% +EPP *creat\_epp(char *pathname, int first\_col, int first\_row, int last\_col, + int last\_row, double AXLeft,double AYTop, double AXRight, + double AYBottom, int scale, int base, int offsite);} + + +óÏÚÄÁÅÔ ÎÏ×ÙÊ epp-ÆÁÊÌ É ÏÔËÒÙ×ÁÅÔ ÅÇÏ × ÒÅÖÉÍÅ {\tt MAP\_OUTPUT}. + +ðÒÉ ÓÏÚÄÁÎÉÉ ÆÁÊÌÁ ÕËÁÚÙ×ÁÀÔÓÑ ÅÇÏ ÒÁÚÍÅÒÙ, ÁÌØÔÅÒÎÁÔÉ×ÎÙÅ ËÏÏÒÄÉÎÁÔÙ, +ÚÎÁÞÅÎÉÅ offsite É ÚÎÁÞÅÎÉÑ ÐÏÌÅÊ ÚÁÇÏÌÏ×ËÁ {\tt base} É {\tt scale}. + +äÌÑ ÓÏÚÄÁÎÉÑ Åpp ÆÁÊÌÅ × ÕÖÅ ÏÔËÒÙÔÏÍ ÆÁÊÌÅ UNIX ÓÕÝÅÓÔ×ÕÅÔ ÆÕÎËÃÉÑ +{\tt fcreat\_epp}\index{fcreat_epp}, ËÏÔÏÒÏÊ ×ÍÅÓÔÏ ÉÍÅÎÉ ÆÁÊÌÁ ÐÅÒÅÄÁÅÔÓÑ ÕËÁÚÁÔÅÌØ +ÎÁ ÓÔÒÕËÔÕÒÕ {\tt FILE}. + +÷Ï ÍÎÏÇÉÈ ÓÌÕÞÁÑÈ ÎÕÖÎÏ ÓÏÚÄÁÔØ ×ÙÈÏÄÎÏÊ ÆÁÊÌ ÔÏÇÏ ÖÅ ÒÁÚÍÅÒÁ É Ó ÔÏÊ +ÖÅ ËÏÏÒÄÉÎÁÔÎÏÊ ÓÉÓÔÅÍÏÊ, ÞÔÏ É ×ÈÏÄÎÏÊ. äÌÑ ÕÐÒÏÝÅÎÉÑ ÜÔÏÇÏ ÐÒÏÃÅÓÓÁ +ÓÕÝÅÓÔ×ÕÅÔ ÆÕÎËÃÉÑ +\index{creat_epp_as}% +\function{EPP *creat\_epp\_as(char *filename,EPP *pattern);} + +ËÏÔÏÒÁÑ ÓÏÚÄÁÅÔ ÆÁÊÌ, ËÏÐÉÒÕÑ ÂÏÌØÛÕÀ ÞÁÓÔØ ÉÎÆÏÒÍÁÃÉÉ ÚÁÇÏÌÏ×ËÁ ÉÚ +ÕÖÅ ÓÕÝÅÓÔ×ÕÀÝÅÇÏ ÆÁÊÌÁ, ÕËÁÚÁÔÅÌØ ÎÁ ËÏÔÏÒÙÊ ÐÅÒÅÄÁÅÔÓÑ × +ÐÁÒÁÍÅÔÒÅ {\tt pattern}. äÌÑ ÎÅÅ ÔÁËÖÅ ÓÕÝÅÓÔ×ÕÅÔ ÁÎÁÌÏÇ, ÐÏÌÕÞÁÀÝÉÊ +ÎÅ ÉÍÑ, Á ÏÔËÒÙÔÙÊ ÆÁÊÌ. + +÷ÓÅ ÜÔÉ ÆÕÎËÃÉÉ ÐÏ ÕÍÏÌÞÁÎÉÀ ÓÏÚÄÁÀÔ 8-ÂÉÔÎÙÊ epp-ÆÁÊÌ. ôÏÞÎÅÅ, +ËÏÌÉÞÅÓÔ×Ï ÂÉÔ ÏÐÒÅÄÅÌÑÅÔÓÑ ÚÎÁÞÅÎÉÅÍ ÇÌÏÂÁÌØÎÏÊ ÐÅÒÅÍÅÎÎÏÊ +{\tt Create16bit}, ËÏÔÏÒÏÊ ÎÕÖÎÏ ÐÒÉÓ×ÏÉÔØ ÎÅÎÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ ÄÌÑ +ÔÏÇÏ, ÞÔÏÂÙ ÓÏÚÄÁ×ÁÌÉÓØ 16-ÂÉÔÎÙÅ ÆÁÊÌÙ + +\section{éÚÍÅÎÅÎÉÅ ÒÅÖÉÍÏ× ÄÏÓÔÕÐÁ} + +ðÒÉ ÉÓÐÏÌØÚÏ×ÁÎÉÉ ÄÁÎÎÏÊ ÂÉÂÌÉÏÔÅËÉ ÓÕÝÅÓÔ×ÕÀÝÉÊ ÆÁÊÌ ×ÓÅÇÄÁ ÏÔËÒÙ×ÁÅÔÓÑ +× ÒÅÖÉÍÅ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÇÏ ÞÔÅÎÉÑ, Á ÎÏ×ÙÊ~--- × ÒÅÖÉÍÅ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÊ +ÚÁÐÉÓÉ. äÌÑ ÔÏÇÏ, ÞÔÏÂÙ ÐÏÌÕÞÉÔØ ÄÒÕÇÏÊ ÒÅÖÉÍ ÄÏÓÔÕÐÁ ÎÕÖÎÏ ÍÅÎÑÔØ ÒÅÖÉÍ +ÄÏÓÔÕÐÁ Ñ×ÎÙÍ ÏÂÒÁÚÏÍ. + +\index{reset_epp}% +\function{void reset\_epp(EPP *epp)} + +ðÅÒÅÏËÒÙ×ÁÅÔ ÄÌÑ ÞÔÅÎÉÑ ÆÁÊÌ, ÏÔËÒÙÔÙÊ ÄÌÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÊ ÚÁÐÉÓÉ. +÷ÓÅ ÎÅÚÁÐÏÌÎÅÎÎÙÅ ÓÔÒÏËÉ ÚÁÐÏÌÎÑÀÔÓÑ offsite. + +\index{set_epp_cache}% +\function{int set\_epp\_cache(EPP* epp, int lines);} + +óÏÚÄÁÅÔ ËÜÛ ÎÁ {\tt lines} ÓÔÒÏË. åÓÌÉ ËÜÛ ÒÁÎÅÅ ÓÕÝÅÓÔ×Ï×ÁÌ, +ÉÚÍÅÎÑÅÔ ÅÇÏ ÒÁÚÍÅÒ. {\tt set\_epp\_cache(epp,0);} ÏÔÍÅÎÑÅÔ ËÜÛÉÒÏ×ÁÎÉÅ +ÓÏ×ÓÅÍ. + +\index{load_epp} +\function{int load\_epp(EPP* epp);} + +úÁÇÒÕÖÁÅÔ ÆÁÊÌ, ÏÔËÒÙÔÙÊ ÄÌÑ ÞÔÅÎÉÑ × ÐÁÍÑÔØ É ÍÅÎÑÅÔ ÅÇÏ ÒÅÖÉÍ +ÎÁ {\tt MAP\_INPUT\verb!|!MAP\_OUTPUT}\index{MAP_INPUT},\index{MAP_OUTPUT}, Ô.Å. ÐÒÑÍÏÅ ÞÔÅÎÉÅ-ÚÁÐÉÓØ. + +\index{save_epp} +\function{int save\_epp(EPP *epp);} + +ÓÏÈÒÁÎÑÅÔ ÉÚÍÅÎÅÎÉÑ × ÚÁÇÒÕÖÅÎÎÏÍ ÆÁÊÌÅ ÎÁ ÄÉÓË. óÔÁÒÏÅ ÓÏÄÅÒÖÉÍÏÅ +ÐÒÉ ÜÔÏÍ ÔÅÒÑÅÔÓÑ. + +\index{save_epp_as} +\function{int save\_epp\_as(EPP *epp,char *newname);} + +óÏÈÒÁÎÑÅÔ ÆÁÊÌ ÐÏÄ ÎÏ×ÙÍ ÉÍÅÎÅÍ. óÔÁÒÙÊ ÆÁÊÌ ÐÒÉ ÜÔÏÍ ÚÁËÒÙ×ÁÅÔÓÑ. + +\index{fsave_epp_as} +\function{int fsave\_epp\_as(EPP *epp,FILE *f);} +áÎÁÌÏÇÉÞÎÁ {\tt save\_epp\_as}, ÎÏ ÐÏÌÕÞÁÅÔ ÎÅ ÉÍÑ ÆÁÊÌÁ, Á ÕÖÅ ÏÔËÒÙÔÙÊ ÆÁÊÌ. + +æÕÎËÃÉÉ ÓÏÈÒÁÎÅÎÉÑ ÎÅ ÍÅÎÑÀÔ ÒÅÖÉÍÁ ÆÁÊÌÁ. ðÒÏÓÔÏ ÂÏÌØÛÅ ÎÅËÕÄÁ ÂÙÌÏ ÉÈ ÐÏÍÅÓÔÉÔØ. + +÷ÓÅ ÆÕÎËÃÉÉ ÓÏÈÒÁÎÅÎÉÑ É ÆÕÎËÃÉÑ {\tt load\_epp} ÐÏÓÌÅ ÏÂÒÁÂÏÔËÉ ËÁÖÄÏÊ +ÓÔÒÏËÉ ×ÙÚÙ×ÁÀÔ ÆÕÎËÃÉÀ, ÎÁ ËÏÔÏÒÕÀ ÕËÁÚÙ×ÁÅÔ ÇÌÏÂÁÌØÎÁÑ ÐÅÒÅÍÅÎÎÁÑ \index{EndLineProc}% +{\tt EndLineProc} (ÓÍ.~ÒÁÚÄÅÌ \ref{iterators}). åÅ ÒÅÚÕÌØÔÁÔ ÏÎÉ ÉÇÎÏÒÉÒÕÀÔ. + +\index{close_epp} +\function{void close\_epp(EPP *epp);} + +úÁËÒÙ×ÁÅÔ ÆÁÊÌ. åÓÌÉ ÆÁÊÌ ÂÙÌ ÏÔËÒÙÔ ÎÁ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÕÀ ÚÁÐÉÓØ, ×ÓÅ ÉÚÍÅÎÅÎÉÑ +ÓÏÈÒÁÎÑÀÔÓÑ, Á ÎÅÚÁÐÏÌÎÅÎÎÙÅ ÓÔÒÏËÉ ÚÁÐÏÌÎÑÀÔÓÑ offsite. + +åÓÌÉ ÆÁÊÌ ÂÙÌ ÚÁÇÒÕÖÅÎ × ÐÁÍÑÔØ, Á×ÔÏÍÁÔÉÞÅÓËÏÇÏ ÓÏÈÒÁÎÅÎÉÑ {\bf ÎÅ} ÐÒÏÉÚ×ÏÄÉÔÓÑ. +\section{äÏÓÔÕÐ Ë ÑÞÅÊËÁÍ ÆÁÊÌÁ} +ïÓÎÏ×ÎÙÍ ÓÐÏÓÏÂÏÍ ÄÏÓÔÕÐÁ Ë ÑÞÅÊËÁÍ ÆÁÊÌÁ Ñ×ÌÑÀÔÓÑ ÆÕÎËÃÉÉ + +\index{epp_get|textbf}% +\function{int epp\_get(EPP* epp,int x,int y);} + +É + +\index{epp_put|textbf}% +\function{void epp\_put(EPP*epp,int x,int y,int value);} + +æÕÎËÃÉÑ {\tt epp\_get} ×ÏÚ×ÒÁÝÁÅÔ ÚÎÁÞÅÎÉÅ ÑÞÅÊËÉ Ó ÕËÁÚÁÎÎÙÍÉ ËÏÏÒÄÉÎÁÔÁÍÉ +(×Ï ×ÎÕÔÒÅÎÎÉÈ ÅÄÉÎÉÃÁÈ ÆÁÊÌÁ) ÉÌÉ offsite, ÅÓÌÉ ÄÁÎÎÁÑ ÔÏÞËÁ ÎÁÈÏÄÉÔÓÑ +ÚÁ ÐÒÅÄÅÌÁÍÉ ËÁÒÔÙ. + +åÅ ÎÅÌØÚÑ ÐÒÉÍÅÎÉÔØ Ë ÆÁÊÌÕ, ÏÔËÒÙÔÏÍÕ ÄÌÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÊ ÚÁÐÉÓÉ, ÐÒÉ +ÜÔÏÍ ×ÏÚÎÉËÁÅÔ ÏÛÉÂËÁ {\tt ME\_INVALID\_MODE}. + +ðÒÉ ÒÁÂÏÔÅ Ó ÆÁÊÌÏÍ ÏÔËÒÙÔÙÍ ÄÌÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÇÏ ÞÔÅÎÉÑ, ÏÐÒÁÛÉ×ÁÔØ +ÑÞÅÊËÉ ÍÏÖÎÏ × ÌÀÂÏÍ ÐÏÒÑÄËÅ, ÎÏ ÏÂÒÁÝÅÎÉÅ Ë ÄÒÕÇÏÊ ÓÔÒÏËÅ +ÔÒÅÂÕÅÔ ÅÅ ÓÞÉÔÙ×ÁÎÉÑ Ó ÄÉÓËÁ É ÒÁÓÐÁËÏ×ËÉ. + +ðÒÉ ÒÁÂÏÔÅ Ó ËÜÛÉÒÏ×ÁÎÎÙÍ ÉÌÉ ÚÁÇÒÕÖÅÎÎÙÍ × ÐÁÍÑÔØ ÆÁÊÌÏÍ, ÔÅÍ ÂÏÌÅÅ +ÍÏÖÎÏ ÏÂÒÁÝÁÔØÓÑ Ë ÅÇÏ ÑÞÅÊËÁÍ × ÐÒÏÉÚ×ÏÌØÎÏÍ ÐÏÒÑÄËÅ. + +æÕÎËÃÉÑ {\tt epp\_put} ÐÒÉ ÐÏÐÙÔËÅ ÉÚÍÅÎÉÔØ ÑÞÅÊËÕ ÚÁ ÐÒÅÄÅÌÁÍÉ +ÆÁÊÌÁ ÇÅÎÅÒÉÒÕÅÔ ÏÛÉÂËÕ {\tt ME\_POINT\_OUTSIDE}. + +÷ ÒÅÖÉÍÅ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÊ ÚÁÐÉÓÉ ÍÏÖÎÏ ÚÁÐÉÓÙ×ÁÔØ ÔÏÞËÉ ×ÎÕÔÒÉ ÔÅËÕÝÅÊ +ÓÔÒÏËÉ × ÐÒÏÉÚ×ÏÌØÎÏÍ ÐÏÒÑÄËÅ, Á ÐÒÉ ÏÂÒÁÝÅÎÉÉ Ë ÓÔÒÏËÅ Ó ÎÏÍÅÒÏÍ, +ÂÏÌØÛÉÍ ÞÅÍ ÔÅËÕÝÁÑ, ÔÅËÕÝÁÑ ÓÔÒÏËÁ ÓÂÒÁÓÙ×ÁÅÔÓÑ ÎÁ ÄÉÓË, É ÄÁÌØÎÅÊÛÁÑ +ÚÁÐÉÓØ × ÎÅÅ ÎÅ×ÏÚÍÏÖÎÁ. åÓÌÉ ÐÒÏÉÚÏÛÌÁ ÚÁÐÉÓØ × ÓÔÒÏËÕ Ó ÎÏÍÅÒÏÍ $n$, +× ÔÏ ×ÒÅÍÑ ËÁË ÐÒÅÄÙÄÕÝÁÑ ÔÅËÕÝÁÑ ÓÔÒÏËÁ ÉÍÅÌÁ ÎÏÍÅÒ $m$, ÇÄÅ $m$fc} ÐÒÉ×ÏÄÉÔ Ë ÏÛÉÂËÅ +{\tt ME\_POINT\_OUTSIDE}, Á ÆÕÎËÃÉÑ ×ÏÚ×ÒÁÝÁÅÔ {\tt NULL}. + +\section{éÔÅÒÁÔÏÒÙ} +\label{iterators} + +\index{for_each_cell}% +\function{int for\_each\_cell(EPP *epp,EPP\_ITER\_PROC action);} + +÷ÙÐÏÌÎÑÅÔ ÆÕÎËÃÉÀ {\tt action} ÄÌÑ ×ÓÅÈ ÎÅ-offsite ÑÞÅÅË ÓÕÝÅÓÔ×ÕÀÝÅÇÏ +ÆÁÊÌÁ ÉÌÉ ÄÌÑ ×ÓÅÈ ÑÞÅÅË ÆÁÊÌÁ, ÏÔËÒÙÔÏÇÏ ÄÌÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÊ ÚÁÐÉÓÉ. +÷ÏÚ×ÒÁÝÁÅÔ 0, ÅÓÌÉ ×ÙÐÏÌÎÅÎÉÅ ÚÁ×ÅÒÛÅÎÏ ÕÓÐÅÛÎÏ, -1 ÅÓÌÉ ×ÙÐÏÌÎÅÎÉÅ +ÐÒÅÒ×ÁÎÏ × ÒÅÚÕÌØÔÁÔÅ ÎÅÎÕÌÅ×ÏÇÏ ÒÅÚÕÌØÔÁÔÁ {\tt EndLineProc}\index{EndLineProc} É -2, +ÅÓÌÉ ×ÙÐÏÌÎÅÎÉÅ ÐÒÅÒ×ÁÎÏ ÓÁÍÏÊ ÆÕÎËÃÉÅÊ {\tt action} + +ôÉÐ {\tt EPP\_ITER\_PROC} ÏÐÒÅÄÅÌÅÎ ËÁË + + +{\tt typedef int (*EPP\_ITER\_PROC)(int col, int row, int value);} + + +ðÁÒÁÍÅÔÒÙ {\tt col} É {\tt row} ÐÅÒÅÄÁÀÔ ËÏÏÒÄÉÎÁÔÙ ÔÅËÕÝÅÊ ÔÏÞËÉ, +ÐÁÒÁÍÅÔÒ {\tt value} ÓÏÄÅÒÖÉÔ ËÌÁÓÓ ÔÏÞËÉ ÄÌÑ ÓÕÝÅÓÔ×ÕÀÝÅÇÏ ÆÁÊÌÁ É +offsite ÄÌÑ ÓÏÚÄÁ×ÁÅÍÏÇÏ. + +÷ÏÚ×ÒÁÝÁÅÍÏÅ ÚÎÁÞÅÎÉÅ × ÓÌÕÞÁÅ ÓÏÚÄÁ×ÁÅÍÏÇÏ ÆÁÊÌÁ ÚÁÐÉÓÙ×ÁÅÔÓÑ × ÑÞÅÊËÕ. + +÷ ÓÌÕÞÁÅ ÓÕÝÅÓÔ×ÕÀÝÅÇÏ ÆÁÊÌÁ ÎÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ ÓÏÏÔ×ÅÔÓÔ×ÕÅÔ ÎÏÒÍÁÌØÎÏÍÕ +ÓÏÓÔÏÑÎÉÀ, Á ÎÅÎÕÌÅ×ÏÅ ÐÒÉ×ÏÄÉÔ Ë ÐÒÅËÒÁÝÅÎÉÀ ÒÁÂÏÔÙ. + +\function{long count\_cells(EPP *epp, EPP\_ITER\_PROC condition);} + +÷ÏÚ×ÒÁÝÁÅÔ ËÏÌÉÞÅÓÔ×Ï ÑÞÅÅË × ÓÕÝÅÓÔ×ÕÀÝÅÍ ÆÁÊÌÅ, ÕÄÏ×ÌÅÔ×ÏÒÑÀÝÉÈ +ÚÁÄÁÎÎÏÍÕ ÕÓÌÏ×ÉÀ. æÕÎËÃÉÑ {\tt condition} ÄÏÌÖÎÁ ×ÏÚ×ÒÁÝÁÔØ 0 ÄÌÑ +ÑÞÅÅË, ËÏÔÏÒÙÅ ÕÓÌÏ×ÉÀ ÎÅ ÕÄÏ×ÌÅÔ×ÏÒÑÀÔ É ÎÅÎÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ ÄÌÑ +ÔÅÈ, ËÏÔÏÒÙÅ ÕÄÏ×ÌÅÔ×ÏÒÑÀÔ. ÷ ÓÌÕÞÁÅ ÐÒÅÒÙ×ÁÎÉÑ ÒÁÂÏÔÙ, ×ÏÚ×ÒÁÝÁÅÔ ÔÅ ÖÅ +ËÏÄÙ, ÞÔÏ É {\tt for\_each\_cell} + +ðÁÒÁÍÅÔÒÙ, ÐÅÒÅÄÁ×ÁÅÍÙÅ ÆÕÎËÃÉÉ {\tt condition} ÔÁËÉÅ ÖÅ, ËÁË +Õ {\tt action} × ÓÌÕÞÁÅ ÓÕÝÅÓÔ×ÕÀÝÅÇÏ ÆÁÊÌÁ. + +éÔÅÒÁÔÏÒÙ ×ÙÐÏÌÎÑÀÔÓÑ ÄÏÓÔÁÔÏÞÎÏ ÄÏÌÇÏ, ÐÏÜÔÏÍÕ ÄÌÑ ÎÉÈ ÐÒÅÄÕÓÍÏÔÒÅÎ +ÓÐÏÓÏ ×ÙÄÁÞÉ ÐÒÏÇÒÅÓÓ-ÉÎÄÉËÁÔÏÒÁ. åÓÌÉ ÇÌÏÂÁÌØÎÏÊ ÐÅÒÅÍÅÎÎÏÊ {\tt EndLineProc}% +\index{EndLineProc|textbf} +ÐÒÉÓ×ÏÅÎÏ ÚÎÁÞÅÎÉÅ, ÏÔÌÉÞÎÏÅ ÏÔ {\tt NULL}, ÔÏ ÆÕÎËÃÉÑ, ÎÁ ËÏÔÏÒÕÀ ÏÎÁ +ÕËÁÚÙ×ÁÅÔ, ×ÙÚÙ×ÁÅÔÓÑ ÐÏÓÌÅ ÏËÏÎÞÁÎÉÑ ÏÂÒÁÂÏÔËÉ ËÁÖÄÏÊ ÓÔÒÏËÉ ÆÁÊÌÁ. + +æÕÎËÃÉÑ ÐÏÌÕÞÁÅÔ ÔÒÉ ÃÅÌÙÈ ÐÁÒÁÍÅÔÒÁ: +\var{row}{ ÎÏÍÅÒ ÓÔÒÏËÉ epp-ÆÁÊÌÁ, Ó ÕÞÅÔÏÍ ÚÎÁÞÅÎÉÑ ÐÏÌÑ {\tt fr}} +\var{seqno}{ ÐÏÒÑÄËÏ×ÙÊ ÎÏÍÅÒ ÓÔÒÏËÉ (ÏÔ 1 ÄÏ {\tt lr-fr})} +\var{total}{ ÏÂÝÅÅ ÞÉÓÌÏ ÓÔÒÏË × ÆÁÊÌÅ.} + +åÓÌÉ ÜÔÁ ÆÕÎËÃÉÑ ×ÏÚ×ÒÁÝÁÅÔ ÎÅÎÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ, ÏÂÒÁÂÏÔËÁ ÆÁÊÌÁ ÐÒÅÒÙ×ÁÅÔÓÑ. + +ôÁËÉÍ ÏÂÒÁÚÏÍ ÐÒÏÓÔÅÊÛÁÑ ÆÕÎËÃÉÑ ÉÎÄÉËÁÃÉÉ ÐÒÏÇÒÅÓÓÁ (ÄÁÀÝÁÑ ÒÅÚÕÌØÔÁÔ, +ÏÞÅÎØ ÐÏÈÏÖÉÊ ÎÁ ÐÏ×ÅÄÅÎÉÅ EPPL7 × ÁÎÁÌÏÇÉÞÎÏÊ ÓÉÔÕÁÃÉÉ), ×ÙÇÌÑÄÉÔ ÔÁË: + +\begin{verbatim} +int show_progress(int row,int seqno,int total) +{ + fprintf(stderr,"\rProcessing row %d of %d",seqno,total); + fflush(stderr); + return 0; +} +\end{verbatim} + +\section{òÁÂÏÔÁ Ó ÚÁÇÏÌÏ×ËÏÍ epp-ÆÁÊÌÁ} +\label{EPPHEADER}\index{EPPHEADER} +úÁÇÏÌÏ×ÏË epp-ÆÁÊÌÁ ÉÍÅÅÔ ÓÌÅÄÕÀÝÕÀ ÓÔÒÕËÔÕÒÕ: +\begin{verbatim} +typedef struct EPPHEADER + { short int fr,lr,fc,lc; + double fry,lry,fcx,lcx; + short int kind; + short int base,scale; + unsigned short int offsite; + double sfact; + long access_ptr; + unsigned short minclass, maxclass; + char area_unit; + char coord_sys; + char Reserved[6]; + char date[16], time[8]; + char comment[32]; + } EPPHEADER; +\end{verbatim} + +óÅÍÁÎÔÉËÁ ÜÔÉÈ ÐÏÌÅÊ ÓÌÅÄÕÀÝÁÑ: +\var{fr,lr,fc,lc}{ ÓÏ×ÐÁÄÁÀÔ Ó ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÍÉ ÐÏÌÑÍÉ ÓÔÒÕËÔÕÒÙ {\tt EPP}} +\var{fry,lry,fcx,lcx}{ ÁÌØÔÅÒÎÁÔÉ×ÎÙÅ ËÏÏÒÄÉÎÁÔÙ} +\var{kind}{ ËÏÌÉÞÅÓÔ×Ï ÂÉÔ ÎÁ ÑÞÅÊËÕ} +\var{base,scale}{ ÔÁÊÎÁ, ÐÏËÒÙÔÁÑ ÍÒÁËÏÍ. ñ ÔÁË É ÎÅ ÓÍÏÇ ÕÑÓÎÉÔØ ÉÚ + ÄÏËÕÍÅÎÔÁÃÉÉ Ë EPPL7, ÞÔÏ ÜÔÉ ÐÏÌÑ ÄÅÌÁÀÔ, É ÎÅ ÚÎÁÀ, ËÁËÉÅ ËÏÍÁÎÄÙ EPPL, + ÎÅ ÓÞÉÔÁÑ {\tt HEADER} Ó ÎÉÍÉ ÒÁÂÏÔÁÀÔ.} +\var{offsite}{ ÈÒÁÎÉÔ ÚÎÁÞÅÎÉÅ offsite.} +\var{sfact}{ ÐÌÏÝÁÄØ ÑÞÅÊËÉ. óÍ. ÔÁËÖÅ ÐÏÌÅ {\tt area\_unit}} +\var{access\_ptr}{ ÓÍÅÝÅÎÉÅ (× 128 ÂÁÊÔÏ×ÙÈ ÂÌÏËÁÈ) ÔÁÂÌÉÃÙ ÄÌÉÎ ÓÔÒÏË × ÆÁÊÌÅ} +\var{minclass,maxclass}{ ÍÉÎÉÍÁÌØÎÙÊ É ÍÁËÓÉÍÁÌØÎÙÊ ËÌÁÓÓ × ÆÁÊÌÅ (ÎÅ ÓÞÉÔÁÑ +offsite} +\var{area\_unit}{ åÄÉÎÉÃÁ ÉÚÍÅÒÅÎÉÑ ÐÌÏÝÁÄÉ.}\index{area_unit} +\var{coord\_sys}{ ÔÉÐ ÐÒÏÅËÃÉÉ}\index{coord_sys}\index{EPPHEADER!coord_sys} +\var{date,time}{ ÄÁÔÁ É ×ÒÅÍÑ ÓÏÚÄÁÎÉÑ ÆÁÊÌÁ × ÔÅËÓÔÏ×ÏÍ ÆÏÒÍÁÔÅ.} +\var{comment}{ ËÒÁÔËÉÊ ËÏÍÍÅÎÔÁÒÉÊ Ë ÆÁÊÌÕ (ÚÁÇÏÌÏ×ÏË ËÁÒÔÙ). úÎÁÞÅÎÉÅ +ÜÔÏÇÏ ÐÏÌÑ EPPL7 ÚÁÐÒÁÛÉ×ÁÅÔ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ ÐÒÉ ÓÏÚÄÁÎÉÉ ËÁÖÄÏÇÏ ÆÁÊÌÁ ËÁË +``Description''} + +÷ÏÚÍÏÖÎÙÅ ÚÎÁÞÅÎÉÑ ÅÄÉÎÉà ÐÌÏÝÁÄÉ É ÔÉÐÏ× ÐÒÏÅËÃÉÉ ÏÐÉÓÁÎÙ ËÁË ËÏÎÓÔÁÎÔÙ × ÆÁÊÌÅ {\tt eppl.h}, +ËÏÔÏÒÙÊ ×ËÌÀÞÁÅÔÓÑ É ÆÁÊÌÏÍ {\tt epp.h} É ÆÁÊÌÏÍ {\tt dgt.h} +\begin{description} +\item[AREA\_NO\_UNIT] ðÌÏÝÁÄØ ÑÞÅÊËÉ ÎÅ ÏÐÒÅÄÅÌÅÎÁ; +\item[AREA\_SQ\_FOOT] ë×ÁÄÒÁÔÎÙÅ ÆÕÔÙ; +\item[AREA\_SQ\_METER] ë×ÁÄÒÁÔÎÙÅ ÍÅÔÒÙ; +\item[AREA\_SQ\_KM] ë×ÁÄÒÁÔÎÙÅ ËÉÌÏÍÅÔÒÙ; +\item[AREA\_SQ\_MILE] ë×ÁÄÒÁÔÎÙÅ ÍÉÌÉ (×ÉÄÉÍÏ, ÉÍÅÀÔÓÑ × ×ÉÄÕ ÁÎÇÌÉÊÓËÉÅ, Á ÎÅ +ÍÏÒÓËÉÅ); +\item[AREA\_HECTARE] çÅËÔÁÒÙ; +\item[AREA\_ACRE] áËÒÙ. +\end{description} + +ëÁË ×ÉÄÉÔÅ, ÍÉÌÌÉÍÅÔÒÙ ÎÅ ÐÒÅÄÕÓÍÏÔÒÅÎÙ. + +ëÏÌÉÞÅÓÔ×Ï ÔÉÐÏ× ÐÒÏÅËÃÉÊ ÏÞÅÎØ ÎÅ×ÅÌÉËÏ É ÐÏËÁÚÙ×ÁÅÔ ÏÒÉÅÎÔÁÃÉÀ EPPL7 ÎÁ +ËÒÕÐÎÏÍÁÓÛÔÁÂÎÏÅ ËÁÒÔÏÇÒÁÆÉÒÏ×ÁÎÉÅ. +\begin{description} +\item[COORD\_NONE] ëÏÏÒÄÉÎÁÔÎÁÑ ÓÉÓÔÅÍÁ ÎÅ ÏÐÒÅÄÅÌÅÎÁ (Ó×ÅÖÅÅ ÓËÁÎÅÒÎÏÅ +ÉÚÏÂÒÁÖÅÎÉÅ); +\item[COORD\_UTM] áÍÅÒÉËÁÎÓËÁÑ ÔÏÐÏÇÒÁÆÉÞÅÓËÁÑ ËÁÒÔÁ. (ÏÔ çÁÕÓÓÁ-ëÒÀÇÅÒÁ +ÏÔÌÉÞÁÅÔÓÑ ÎÁ 0.2\%, ÎÏ ÏÔÌÉÞÁÅÔÓÑ. +\item[COORD\_STPLANE] ðÒÏÅËÃÉÑ State Plane. éÓÐÏÌØÚÕÅÔÓÑ, ÓÕÄÑ ÐÏ ÎÁÚ×ÁÎÉÀ, +ÄÌÑ ËÁÒÔ ÛÔÁÔÏ× óûá. +\item[COORD\_LL] çÅÏÇÒÁÆÉÞÅÓËÉÅ ËÏÏÒÄÉÎÁÔÙ. +\end{description} + +äÌÑ ÒÁÂÏÔÙ Ó ÜÔÏÊ ÉÎÆÏÒÍÁÃÉÅÊ ÐÒÅÄÕÓÍÏÔÒÅÎÙ ÓÌÅÄÕÀÝÉÅ ÆÕÎËÃÉÉ: +\function{void get\_epp\_header(EPP* epp, EPPHEADER *h);}\index{get_epp_header|textbf} +÷ÏÚ×ÒÁÝÁÅÔ ÚÁÇÏÌÏ×ÏË ÆÁÊÌÁ × ×ÉÄÅ ×ÙÛÅÏÐÉÓÁÎÎÏÊ ÓÔÒÕËÔÕÒÙ. éÓÐÏÌØÚÕÅÔÓÑ +ÄÌÑ ÞÔÅÎÉÑ ÐÏÌÅÊ, Ë ËÏÔÏÒÙÍ ÎÅÔ ÂÏÌÅÅ ÕÄÏÂÎÏÇÏ ÄÏÓÔÕÐÁ. + +\function{char *getcomment(EPP *epp);}\index{getcomment} + +÷ÏÚ×ÒÁÝÁÅÔ ËÏÍÍÅÎÔÁÒÉÊ, ÏÂÒÅÚÁÑ ËÏÎÃÅ×ÙÅ ÐÒÏÂÅÌÙ. ÷ÏÚ×ÒÁÝÁÅÔ +ÕËÁÚÁÔÅÌØ ÎÁ ÓÔÁÔÉÞÅÓËÉÊ ÂÕÆÅÒ, ËÏÔÏÒÙÊ ÂÕÄÅÔ ÐÅÒÅÚÁÐÉÓÁÎ ÐÒÉ +ÓÌÅÄÕÀÝÅÍ ÏÂÒÁÝÅÎÉÉ Ë ÜÔÏÊ ÆÕÎËÃÉÉ. + +\function{void change\_epp\_header(EPP* epp,EPPHEADER h);}\index{change_epp_header} + +ëÏÐÉÒÕÅÔ × ÚÁÇÏÌÏ×ÏË ÆÁÊÌÁ ÐÏÌÑ {\tt fcx, lcx, fry, lry, base, scale, offsite, +sfact, coord\_sys, area\_unit, comment} ÉÚ ÐÅÒÅÄÁÎÎÏÊ ÓÔÒÕËÔÕÒÙ. ïÓÔÁÌØÎÙÅ +ÐÏÌÑ ÏÓÔÁ×ÌÑÅÔ ËÁË ÂÙÌÉ. + +\function{void setcomment(EPP *epp,char *comment);}\index{set_comment} + +éÚÍÅÎÑÅÔ ÔÏÌØËÏ ËÏÍÍÅÎÔÁÒÉÊ. ÷ ÏÔÌÉÞÉÅ ÏÔ {\tt change\_epp\_header} ÎÅ +ÔÒÅÂÕÅÔ, ÞÔÏÂÙ ÓÔÒÏËÁ ÂÙÌÁ ÄÏÐÏÌÎÅÎÁ ÐÒÏÂÅÌÁÍÉ ÄÏ 32 ÓÉÍ×ÏÌÏ×. +åÅ ÁÒÕÇÕÍÅÎÔ~--- ÏÂÙÞÎÁÑ NULL-terminated ÓÔÒÏËÁ. + + + +\function{int shift\_epp(EPP* epp, int new\_fr, int new\_fc);}\index{shift_epp} + +éÚÍÅÎÑÅÔ ÚÎÁÞÅÎÉÑ ÐÏÌÅÊ {\tt fr} É {\tt fc}, É ÓÏÏÔ×ÅÔÓÔ×ÅÎÎÏ {\tt lr} É +{\tt lc}, ÐÏÓËÏÌØËÕ ÞÉÓÌÏ ÓÔÒÏË É ËÏÌÏÎÏË × ÆÁÊÌÅ ÐÏÍÅÎÑÔØ ÎÅÌØÚÑ. + +÷ÏÚ×ÒÁÝÁÅÔ ÎÅÎÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ × ÓÌÕÞÁÅ ÕÓÐÅÈÁ ÉÌÉ 0, ÅÓÌÉ ËÁËÉÅ-ÔÏ +ËÏÏÒÄÉÎÁÔÙ ÐÒÉ ÉÚÍÅÎÅÎÉÉ ×ÙÌÅÚÌÉ ÚÁ ÄÏÐÕÓÔÉÍÙÊ ÄÉÁÐÁÚÏÎ. + +\section{ðÅÒÅÓÞÅÔ ËÏÏÒÄÉÎÁÔ} +\function{int epp\_row(EPP *epp,double y);}\index{epp_row} +÷ÏÚ×ÒÁÝÁÅÔ ÎÏÍÅÒ ÓÔÒÏËÉ ÐÏ ÁÌØÔÅÒÎÁÔÉ×ÎÏÍÕ y. +\function{int epp\_col(EPP *epp,double x);}\index{epp_col} +CÏÏÔ×ÅÔÓÔ×ÅÎÎÏ, ÎÏÍÅÒ ËÏÌÏÎËÉ ÐÏ ÁÌØÔÅÒÎÁÔÉ×ÎÏÍÕ x. +\function{double alt\_x(EPP *epp,int col);}\index{alt_x} +÷ÏÚ×ÒÁÝÁÅÔ ÁÌØÔÅÒÔÁÎÔÉ×ÎÙÊ x ÕËÁÚÁÎÎÏÊ ËÏÌÏÎËÉ. +\function{double alt\_y(EPP *epp,int row);}\index{alt_y} +é ÁÌØÔÅÒÎÁÔÉ×ÎÙÊ y ÕËÁÚÁÎÎÏÊ ÓÔÒÏËÉ. + +üÔÉ Ä×Å ÆÕÎËÃÉÉ ×ÏÚ×ÒÁÝÁÀÔ ÁÌØÔÅÒÎÁÔÉ×ÎÙÅ ËÏÏÒÄÉÎÁÔÙ ÐÒÁ×ÏÇÏ ×ÅÒÈÎÅÇÏ +ÕÇÌÁ ÑÞÅÊËÉ. äÌÑ ÐÏÌÕÞÅÎÉÑ ËÏÏÒÄÉÎÁÔ ÃÅÎÔÒÁ ÑÞÅÊËÉ ÐÒÅÄÎÁÚÎÁÞÅÎÙ ÆÕÎËÃÉÉ: + +\function{double alt\_xc(EPP *epp,int col);}\index{alt_xc} +\function{double alt\_yc(EPP *epp,int row);}\index{alt_yc} + + + +\section{îÁÌÏÖÅÎÉÅ ÆÁÊÌÏ×} + +òÁÓÔÒÏ×ÙÅ ÆÁÊÌÙ ÌÅÇËÏ ÎÁËÌÁÄÙ×ÁÔØ ÄÒÕÇ ÎÁ ÄÒÕÇÁ, ÅÓÌÉ Õ ÎÉÈ +ÓÏ×ÐÁÄÁÅÔ ÒÁÚÍÅÒ ÑÞÅÊËÉ É ËÏÏÒÄÉÎÁÔÎÁÑ ÓÉÓÔÅÍÁ. + +äÌÑ ÐÒÏ×ÅÒËÉ ÜÔÉÈ ÕÓÌÏ×ÉÊ × ÂÉÂÌÉÏÔÅËÕ ×ËÌÀÞÅÎÁ ÆÕÎËÃÉÑ + +\function{int compare\_cell\_size(EPP *f1,EPP *f2);}\index{compare_cell_size} + +ÏÎÁ ×ÏÚ×ÒÁÝÁÅÔ 0 ÅÓÌÉ ÒÁÚÍÅÒÙ ÑÞÅÅË ÎÅÓÏ×ÍÅÓÔÉÍÙ É ÎÅÎÕÌÅ×ÏÊ ËÏÄ, +ÅÓÌÉ ÆÁÊÌÙ ÍÏÖÎÏ ÎÁËÌÁÄÙ×ÁÔØ. + +÷ÔÏÒÏÅ ÕÓÌÏ×ÉÅ, ËÏÔÏÒÏÅ ÎÅÏÂÈÏÄÉÍÏ ÐÒÏ×ÅÒÉÔØ~--- ÓÏ×ÐÁÄÁÅÔ ÌÉ +ÐÒÁ×ÉÌÏ ÐÅÒÅÓÞÅÔÁ ÁÌØÔÅÒÎÁÔÉ×ÎÙÈ ËÏÏÒÄÉÎÁÔ × ÒÑÄÙ/ËÏÌÏÎËÉ. + +äÌÑ ÜÔÏÇÏ ÐÒÅÄÎÁÚÎÁÞÅÎÁ ÆÕÎËÃÉÑ +\function {int is\_aligned(EPP *f1,EPP *f2);}\index{is_aligned} + +ïÎÁ ×ÏÚ×ÒÁÝÁÅÔ ÎÅÎÕÌÅ×ÏÊ ËÏÄ, ÅÓÌÉ ÏÂÒÁÝÅÎÉÅ Ë {\tt epp\_get}\index{epp_get} +Ó ÏÄÉÎÁËÏ×ÙÍÉ ÁÒÇÕÍÅÎÔÁÍÉ ÄÌÑ ÏÂÏÉÈ ÆÁÊÌÏ× ×ÏÚ×ÒÁÝÁÅÔ +ÉÎÆÏÒÍÁÃÉÀ Ï ÏÄÎÏÊ É ÔÏÊ ÖÅ ÔÏÞËÅ. + +îÅÓÏ×ÐÁÄÅÎÉÅ ÒÁÍËÉ ÆÁÊÌÏ× ÎÅ ÉÇÒÁÅÔ ÎÉËÁËÏÊ ÒÏÌÉ, ÐÏÓËÏÌØËÕ {\tt epp\_get} +ËÏÒÒÅËÔÎÏ ÏÂÒÁÂÁÔÙ×ÁÅÔ ÏÂÒÁÝÅÎÉÅ Ë ÔÏÞËÅ ÚÁ ÐÒÅÄÅÌÁÍÉ ÆÁÊÌÁ. + +åÓÌÉ {\tt compare\_cell\_size} ×ÏÚ×ÒÁÝÁÅÔ TRUE, Á {\tt is\_aligned}~--- +FALSE, ÔÏ ÆÁÊÌÙ ÍÏÇÕÔ ÂÙÔØ ×ÙÒÁ×ÎÅÎÙ ÐÕÔÅÍ ÉÚÍÅÎÅÎÉÑ ÎÏÍÅÒÁ ÐÅÒ×ÏÊ +ÓÔÒÏËÉ É/ÉÌÉ ËÏÌÏÎËÉ Ó ÐÏÍÏÝØÀ ÆÕÎËÃÉÉ {\tt shift\_epp}. + +åÓÌÉ ÖÅ ÎÅÏÂÈÏÄÉÍÏ ÓÏ×ÍÅÓÔÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÆÁÊÌÙ, Õ ËÏÔÏÒÙÈ ÎÅ +ÓÏ×ÐÁÄÁÅÔ ÒÁÚÍÅÒ ÑÞÅÊËÉ, ÔÏ ÎÅÏÂÈÏÄÉÍÏ ÒÁÓÞÉÔÁÔØ É ÉÓÐÏÌØÚÏ×ÁÔØ +ÐÅÒÅÓÞÅÔÎÙÅ ËÏÜÆÆÉÃÉÅÎÔÙ. + +äÌÑ ÜÔÏÇÏ ÉÓÐÏÌØÚÕÀÔÓÑ ÆÕÎËÃÉÉ: + +\function{EPP\_LINK link\_epp(EPP *base,EPP *overlay);}\index{link_epp}\index{EPP_LINK} + +õÓÔÁÎÁ×ÌÉ×ÁÅÔ Ó×ÑÚØ ÍÅÖÄÕ ÆÁÊÌÁÍÉ. ÷ÏÚ×ÒÁÝÁÅÔ ÕËÁÚÁÔÅÌØ ÎÁ +ÓÔÒÕËÔÕÒÕ {\tt LINK\_BUFFER}, ÓÏÄÅÒÖÁÝÕÀ ÎÁÂÏÒ ÐÅÒÅÓÞÅÔÎÙÈ +ËÏÜÆÆÉÃÉÅÎÔÏ× ÉÌÉ {\tt NULL}, ÅÓÌÉ Ó×ÑÚØ ÕÓÔÁÎÏ×ÉÔØ ÎÅ×ÏÚÍÏÖÎÏ +(ËÏÏÒÄÉÎÁÔÎÙÅ ÓÉÓÔÅÍÙ Ä×ÕÈ ÆÁÊÌÏ× ÉÍÅÀÔ ÐÒÏÔÉ×ÏÐÏÌÏÖÎÏ ÎÁÐÒÁ×ÌÅÎÎÙÅ +ÏÓÉ). + +æÕÎËÃÉÉ: + +\function{int linked\_row(EPP\_LINK link,int row);}\index{linked_row} +\function{int linked\_col(EPP\_LINK link,int col);}\index{linked_col} + +ÐÅÒÅÓÞÉÔÙ×ÁÀÔ ÒÑÄÙ/ËÏÌÏÎËÉ ÆÁÊÌÁ {\tt base} × ÒÑÄÙ/ËÏÌÏÎËÉ ÆÁÊÌÁ {\tt overlay} + + +\section{ðÒÏÞÅÅ} +÷ ÎÅËÏÔÏÒÙÈ ÓÌÕÞÁÑÈ ÄÏ ÏËÏÎÞÁÎÉÑ ÓÏÚÄÁÎÉÑ ÆÁÊÌÁ ÎÅÌØÚÑ ÏÐÒÅÄÅÌÉÔØ, +ÅÓÔØ ÌÉ × ÎÅÍ ËÌÁÓÓÙ Ó×ÙÛÅ 255. ÷ ÜÔÉÈ ÓÌÕÞÁÑÈ ÐÒÉÈÏÄÉÔÓÑ ×ÓÅÇÄÁ +ÓÏÚÄÁ×ÁÔØ 16-ÂÉÔÎÙÊ ÆÁÊÌ, Á ÐÏ ÏËÏÎÞÁÎÉÉ ÒÁÂÏÔÙ, ÅÓÌÉ $\mbox{max}\le 255$ ËÏÎ×ÅÒÔÉÒÏ×ÁÔØ +ÅÇÏ × ×ÏÓØÍÉÂÉÔÎÙÊ. äÌÑ ÕÐÒÏÝÅÎÉÑ (É ÕÓËÏÒÅÎÉÑ) ÜÔÏÊ ÏÐÅÒÁÃÉÉ, +× ÂÉÂÌÉÏÔÅËÕ ×ËÌÀÞÅÎÁ ÆÕÎËÃÉÑ: + +\function{int fast\_convert\_to\_8bit(EPP *source, char *filename);}% +\index{fast_convert_to_8bit} + +üÔÁ ÆÕÎËÃÉÑ ÐÏÌÕÞÁÅÔ ÏÔËÒÙÔÙÊ ÎÁ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÕÀ ÚÁÐÉÓØ ÆÁÊÌ, +ÐÅÒÅÏÔËÒÙ×ÁÅÔ ÅÇÏ ÎÁ ÞÔÅÎÉÅ É ËÏÐÉÒÕÅÔ × ÎÏ×ÙÊ ÆÁÊÌ, ÕËÁÚÁÎÎÙÊ ËÁË filename. + +æÕÎËÃÉÑ ÒÁÂÏÔÁÅÔ +ÔÁË ÂÙÓÔÒÏ, ËÁË ÔÏÌØËÏ ×ÏÚÍÏÖÎÏ, ÐÏÓËÏÌØËÕ ÉÓÐÏÌØÚÕÅÔ ÎÁÐÒÑÍÕÀ +ÎÅËÏÔÏÒÙÅ ×ÏÚÍÏÖÎÏÓÔÉ ÂÉÂÌÉÏÔÅËÉ, ÎÅ ×ÙÎÅÓÅÎÎÙÅ × ÉÎÔÅÒÆÅÊÓ. + +äÌÑ Ó×ÅÄÅÎÉÑ ÞÉÔÁÔÅÌÅÊ, ÉÍÅÀÝÉÈ ÏÐÙÔ ÒÁÂÏÔÙ Ó epp-ÆÁÊÌÏÍ ÎÁ ÎÉÚËÏÍ +ÕÒÏ×ÎÅ, ÕËÁÖÅÍ, ÞÔÏ ÚÁÐÁËÏ×ËÉ ÏÎÁ ÎÅ ×ÙÐÏÌÎÑÅÔ ×ÏÏÂÝÅ, Á ÒÁÓÐÁËÏ×Ù×ÁÅÔ +ÔÏÌØËÏ ÍÌÁÄÛÉÅ 8 ÂÉÔ 16-ÂÉÔÎÏÇÏ ÆÁÊÌÁ. + +ðÏ ÏËÏÎÞÁÎÉÉ ÒÁÂÏÔÙ ÚÁËÒÙ×ÁÅÔ ÏÂÁ ÆÁÊÌÁ. + +\section{ïÂÒÁÂÏÔËÁ ÏÛÉÂÏË} + +âÏÌØÛÁÑ ÞÁÓÔØ ÆÕÎËÃÉÊ ÂÉÂÌÉÏÔÅËÉ ËÏÒÒÅËÔÎÏ ÏÂÒÁÂÁÔÙ×ÁÅÔ +ÏÛÉÂÏÞÎÙÅ ÓÉÔÕÁÃÉÉ. äÏÓÔÁÔÏÞÎÏ ÞÁÓÔÏ ÉÎÄÉËÁÔÏÒÏÍ ÏÛÉÂËÉ ÓÌÕÖÉÔ +ÒÅÚÕÌØÔÁÔ, ×ÏÚ×ÒÁÝÁÅÍÙÊ ÆÕÎËÃÉÅÊ. + +óÕÝÅÓÔ×ÕÅÔ ÇÌÏÂÁÌØÎÁÑ ÐÅÒÅÍÅÎÎÁÑ {\tt map\_error}\index{map_error} × ËÏÔÏÒÕÀ ÐÏÍÅÝÁÅÔÓÑ +ËÏÄ ÏÛÉÂËÉ. ÷ÏÚÍÏÖÎÙÅ ËÏÄÙ ÏÐÒÅÄÅÌÅÎÙ ËÁË ËÏÎÓÔÁÎÔÙ × ÆÁÊÌÅ {\tt epp\_err.h}. + +\var{ME\_OK}{ÏÐÅÒÁÃÉÑ ÚÁ×ÅÒÛÉÌÁÓØ ÕÓÐÅÛÎÏ.} +\var{ME\_POINT\_OUTSIDE}{ðÏÐÙÔËÁ ÓÄÅÌÁÔØ {\tt epp\_put} ÚÁ ÐÒÅÄÅÌÁÍÉ ÆÁÊÌÁ.} +\var{ME\_INVALID\_MODE}{ðÏÐÙÔËÁ ÞÉÔÁÔØ ËÁÒÔÕ, ÏÔËÒÙÔÕÀ × ÒÅÖÉÍÅ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÊ +ÚÁÐÉÓÉ, ÉÌÉ ÍÏÄÉÆÉÃÉÒÏ×ÁÔØ ËÁÒÔÕ, ÏÔËÒÙÔÕÀ × ÒÅÖÉÍÅ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÇÏ ÞÔÅÎÉÑ} +\var{ME\_READ\_ERROR}{ïÛÉÂËÁ ÓÉÓÔÅÍÎÏÇÏ ×ÙÚÏ×Á ÉÌÉ ÂÉÂÌÉÏÔÅÞÎÏÊ ÆÕÎËÃÉÉ ÐÒÉ +ÞÔÅÎÉÉ Ó ÄÉÓËÁ. òÅËÏÍÅÎÄÕÅÔÓÑ ÐÏÓÍÏÔÒÅÔØ ÚÎÁÞÅÎÉÅ ÇÌÏÂÁÌØÎÏÊ ÐÅÒÅÍÎÎÏÊ {\tt errno}.} +\var{ME\_WRITE\_ERROR}{ôÏ ÖÅ ÓÁÍÏÅ, ÎÏ ÐÒÉ ÚÁÐÉÓÉ.} +\var{ME\_INVALID\_PUT}{ðÏÐÙÔËÁ ÉÚÍÅÎÉÔØ ÑÞÅÊËÕ, ÕÖÅ ÚÁÐÉÓÁÎÎÕÀ ÎÁ ÄÉÓË.} +\var{ME\_OUT\_OF\_MEMORY}{îÅ È×ÁÔÉÌÏ ÐÁÍÑÔÉ ÄÌÑ ÒÁÚÍÅÝÅÎÉÑ ÎÅÏÂÈÏÄÉÍÙÈ ÓÔÒÕËÔÕÒ ÄÁÎÎÙÈ} +\var{ME\_ACCESS\_DENIED}{îÅ ÕÄÁÌÏÓØ ÏÔËÒÙÔØ ÆÁÊÌ × ÔÒÅÂÕÅÍÏÍ ÒÅÖÉÍÅ} +\var{ME\_NO\_FILE}{æÁÊÌ Ó ÕËÁÚÁÎÎÙÍ ÉÍÅÎÅÍ ÎÅ ÓÕÝÅÓÔ×ÕÅÔ} +\var{ME\_INVALID\_FILE}{æÁÊÌ ÎÅ Ñ×ÌÑÅÔÓÑ ÐÒÁ×ÉÌØÎÙÍ epp ÉÌÉ dgt ÆÁÊÌÏÍ} +\var{ME\_CREATE\_ERROR}{ïÛÉÂËÁ ÓÏÚÄÁÎÉÑ ÆÁÊÌÁ, ÎÅ ÓÕÝÅÓÔ×ÕÅÔ ÐÕÔØ ÉÌÉ + ÎÅÄÏÐÕÓÔÉÍÏÅ ÉÍÑ. ðÏÄÒÏÂÎÏÓÔÉ~--- × ÓÉÓÔÅÍÎÏÊ ÐÅÒÅÍÅÎÎÏÊ {\tt errno}.} +åÓÌÉ ÐÒÉ ËÁËÏÊ-ÔÏ ÏÐÅÒÁÃÉÉ {\tt map\_error} ÕÓÔÁÎÏ×ÌÅÎÁ × ÎÅÎÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ, +ÔÏ ÉÍÅÅÔ ÓÍÙÓÌ ÐÅÒÅÄ ÐÒÏÄÏÌÖÅÎÉÅÍ ÒÁÂÏÔÙ ÅÅ ÏÂÎÕÌÉÔØ. îÅËÏÔÏÒÙÅ ÆÕÎËÃÉÉ +ÂÉÂÌÉÏÔÅËÉ ÐÒÏ×ÅÒÑÀÔ ÅÇÏ ÐÏÓÌÅ ×ÙÚÏ×Á ÄÒÕÇÉÈ ÆÕÎËÃÉÊ, Á ÏÂÎÕÌÅÎÉÅ ÐÏÓÌÅ +ÕÓÐÅÛÎÏÊ ÏÐÅÒÁÃÉÉ ÎÅ ÇÁÒÁÎÔÉÒÏ×ÁÎÏ. + +\chapter{æÕÎËÃÉÉ ÄÏÓÔÕÐÁ Ë ×ÅËÔÏÒÎÙÍ ÆÁÊÌÁÍ} + +æÕÎËÃÉÉ ÄÏÓÔÕÐÁ Ë ×ÅËÔÏÒÎÙÍ ÆÁÊÌÁÍ ÏÐÉÓÁÎÙ × ÚÁÇÏÌÏ×ÏÞÎÏÍ ÆÁÊÌÅ {\tt dgt.h}. +÷ ÎÅÍ ÏÐÒÅÄÅÌÅÎÁ ÓÔÒÕËÔÕÒÁ {\tt DGT}, ÁÎÁÌÏÇÉÞÎÁÑ ÐÏ ÓÍÙÓÌÕ ÓÔÒÕËÔÕÒÅ {\tt EPP}. + +ðÏÓËÏÌØËÕ × ÚÁÇÏÌÏ×ËÅ ×ÅËÔÏÒÎÙÈ ÆÁÊÌÏ× ÎÉËÁËÏÊ ÉÎÆÏÒÍÁÃÉÉ ËÒÏÍÅ ÁÌØÔÅÒÎÁÔÉ×ÎÙÈ +ËÏÏÒÄÉÎÁÔ É ÔÉÐÁ ÐÒÏÅËÃÉÉ ÎÅ ÈÒÁÎÉÔÓÑ, ÓÐÏÓÏÂÏ× ÐÒÑÍÏÊ ÒÁÂÏÔÙ Ó ÚÁÇÏÌÏ×ËÏÍ +ÎÅ ÐÒÅÄÕÓÍÏÔÒÅÎÏ. + +\section{TÉÐÙ ÄÁÎÎÙÈ} + +÷ ÏÔÌÉÞÉÅ ÏÔ ÒÁÓÔÒÏ×ÙÈ ÆÁÊÌÏ×, ÚÎÁÞÅÎÉÅÍ ËÏÔÏÒÙÈ × ÔÏÞËÅ Ñ×ÌÑÅÔÓÑ +ÏÂÙÞÎÏÅ ÃÅÌÏÅ ÞÉÓÌÏ, ×ÅËÔÏÒÎÙÅ ÆÁÊÌÙ ÈÒÁÎÑÔ ÄÏ×ÏÌØÎÏ ÓÌÏÖÎÙÅ ÏÂßÅËÔÙ. + +ðÒÉ×ÅÄÅÍ ÉÈ ÏÐÉÓÁÎÉÑ: +\index{POINT}% +\var{POINT}{óÔÒÕËÔÕÒÁ ÄÌÑ ÈÒÁÎÅÎÉÑ ËÏÏÒÄÉÎÁÔ ÔÏÞËÉ. éÍÅÅÔ Ä×Á ÐÏÌÑ +ÔÉÐÁ {\tt signed short int}~--- {\tt x} É {\tt y}. îÅÓÍÏÔÒÑ ÎÁ ÓÈÏÖÅÓÔØ +ÏÐÉÓÁÎÉÑ ÓÏ ÓÔÒÕËÔÕÒÏÊ {\tt XPoint}, ÐÏÐÙÔËÁ ÐÅÒÅÄÁÔØ ÍÁÓÓÉ× ÔÏÞÅË ÔÉÐÁ +{\tt POINT} × ÆÕÎËÃÉÀ {tt XDrawLine} ÐÏÞÅÍÕ-ÔÏ Ë ÕÓÐÅÈÕ ÎÅ ÐÒÉ×ÏÄÉÔ} +\index{DGT_ITEM} +\var{DGT\_ITEM}{óÔÒÕËÔÕÒÁ ÄÌÑ ÈÒÁÎÅÎÉÑ ÉÎÆÏÒÍÁÃÉÉ Ï ×ÅËÔÏÒÎÏÍ ÏÂßÅËÔÅ~--- +ÐÏÌÉÌÉÎÉÉ ÉÌÉ ÔÏÞËÅ (ÎÅ ÐÕÔÁÔØ ÔÏÞËÕ-ÏÂßÅËÔ Ó ÔÏÞËÏÊ-ÕÚÌÏÍ ÌÉÎÉÉ)). +åÅ ÐÏÌÑ:} +\var{long int ID}{ 32-ÂÉÔÎÙÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÏÂßÅËÔÁ.} +\var{short int x1,y1}{ ÌÅ×ÙÊ ÎÉÖÎÉÊ ÕÇÏÌ ÍÁÓËÉ, ÅÓÌÉ ÏÂßÅËÔ~--- ÐÏÌÉÌÉÎÉÑ ÉÌÉ ËÏÏÒÄÉÎÁÔÙ +ÔÏÞËÉ, ÅÓÌÉ ÏÂßÅËÔ~--- ÔÏÞËÁ.} +\var{short int x2,y2}{ ÐÒÁ×ÙÊ ×ÅÒÈÎÉÊ ÕÇÏÌ ÍÁÓËÉ. õ ÔÏÞÅË~--- ÎÅ ÉÓÐÏÌØÚÕÅÔÓÑ.} +\var{shott int npoints}{ ÞÉÓÌÏ ÕÚÌÏ× × ÌÉÎÉÉ. åÓÌÉ 0, ÔÏ ÏÂßÅËÔ~--- ÔÏÞËÁ, +ÏÔ 2 ÄÏ 500~--- ÐÏÌÉÌÉÎÉÑ, ÏÓÔÁÌØÎÙÅ ÚÎÁÞÅÎÉÑ ÎÅÄÏÐÕÓÔÉÍÙ.} +\var{POINT s[500]}{ ÍÁÓÓÉ× ËÏÏÒÄÉÎÁÔ ÔÏÞÅË ÐÏÌÉÌÉÎÉÉ.} + +óÔÒÕËÔÕÒÁ {\tt DGT}\index{DGT|textbf} ÈÒÁÎÉÔ ×ÓÀ ÉÎÆÏÒÍÁÃÉÀ, ÎÅÏÂÈÏÄÉÍÕÀ ÐÒÉ ÒÁÂÏÔÅ Ó ×ÅËÔÏÒÎÙÍ +ÆÁÊÌÏÍ. ðÒÏÇÒÁÍÍÉÓÔÕ ÉÍÅÅÔ ÓÍÙÓÌ ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÏ ÞÉÔÁÔØ ÓÌÅÄÕÀÝÉÅ ÅÅ ÐÏÌÑ: +\index{DGT!XLeft}\index{DGT!XRight}\index{DGT!YTop}\index{DGT!YBottom}% +\index{XLeft!DGT}\index{XRight!DGT}\index{YTop!DGT}\index{YBottom!DGT}% +\var{double XLeft,YBottom,XRight,YTop}{ ÁÌØÔÅÒÎÁÔÉ×ÎÙÅ ËÏÏÒÄÉÎÁÔÙ ÇÒÁÎÉà +ÆÁÊÌÁ.} +\index{mode!DGT}% +\var{int mode}{ òÅÖÉÍ ÄÏÓÔÕÐÁ. ëÏÍÂÉÎÁÃÉÑ ÔÅÈ ÖÅ ËÏÎÓÔÁÎÔ {\tt MAP\_INPUT} É +{\tt MAP\_OUTPUT}, ÞÔÏ É ÐÏÌÅ {\tt mode} ÓÔÒÕËÔÕÒÙ {\tt EPP}.} +\index{projection!DGT}% +\var{unsigned char projection}{ôÉÐ ËÏÏÒÄÉÎÁÔÎÏÊ ÓÉÓÔÅÍÙ. ÷ÏÚÍÏÖÎÙÅ ÚÎÁÞÅÎÉÑ +ÏÐÉÓÁÎÙ × ÒÁÚÄÅÌÅ \ref{EPPHEADER}.} +\var{DGT\_ITEM *buffer}{ âÕÆÅÒ ÄÌÑ ÈÒÁÎÅÎÉÑ ÔÅËÕÝÅÇÏ ÏÂßÅËÔÁ. ïÂÙÞÎÏ ÄÏÓÔÕÐ +Ë ÜÔÏÊ ÓÔÒÕËÔÕÒÅ ×ÙÐÏÌÎÑÅÔÓÑ Ó ÐÏÍÏÝØÀ ÍÁËÒÏÓÏ×, ÏÐÉÓÁÎÎÙÈ × ÒÁÚÄÅÌÅ \ref{ItemMacros}.} +\var{int eof}{ æÌÁÇ, ×ÙÓÔÁ×ÌÑÅÍÙÊ × ÎÅÎÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ, ÅÓÌÉ ÐÒÏÞÉÔÁÎ ÐÒÉÚÎÁË +ËÏÎÃÁ ÆÁÊÌÁ.} +\var{int item\_no}{ ðÏÒÑÄËÏ×ÙÊ ÎÏÍÅÒ ÔÅËÕÝÅÇÏ ÏÂßÅËÔÁ} +\section{ïÔËÒÙÔÉÅ ÆÁÊÌÁ} + +\index{open_dgt}% +\function{DGT *open\_dgt(char *filename)} +\index{fopen_dgt}% +\function{DGT *fopen\_dgt(FILE *f)} + +ïÔËÒÙ×ÁÀÔ ÓÕÝÅÓÔ×ÕÀÝÉÊ ÆÁÊÌ ÄÌÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÇÏ ÞÔÅÎÉÑ. ÷ÏÚ×ÒÁÝÁÀÔ ÕËÁÚÁÄÅÌØ +ÎÁ ÓÔÒÕËÔÕÒÕ {\tt DGT} ÉÌÉ {\tt NULL}, ÅÓÌÉ ÐÒÏÉÚÏÛÌÁ ÏÛÉÂËÁ. + +\index{creat_dgt}% +\function{DGT *creat\_dgt(char *filename, double x\_left, double y\_bottom, +double x\_right, double y\_top, unsigned char proj)} +\index{fcreat_dgt}% +\function{DGT *fcreat\_dgt(FILE *f, double x\_left, double y\_bottom, +double x\_right, double y\_top, unsigned char proj)} +\index{mcreat_dgt}% +\function{DGT *mcreat\_dgt(double x\_left, double y\_bottom, +double x\_right, double y\_top, unsigned char proj)} + +óÏÚÄÁÀÔ ÆÁÊÌ ÄÌÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÊ ÚÁÐÉÓÉ. ðÏÌÕÞÁÀÔ × ËÁÞÅÓÔ×Å ÐÁÒÁÍÅÔÒÏ× +ÐÒÅÄÅÌÙ ÁÌØÔÅÒÎÁÔÉ×ÎÙÈ ËÏÏÒÄÉÎÁÔ É ÔÉÐ ÐÒÏÅËÃÉÉ. + +ïÓÏÂÏÅ ×ÎÉÍÁÎÉÅ ÓÔÏÉÔ ÏÂÒÁÔÉÔØ ÎÁ ÆÕÎËÃÉÀ {\tt mcreat\_dgt}, ËÏÔÏÒÁÑ +ÓÏÚÄÁÅÔ ÐÕÓÔÏÊ ÆÁÊÌ × ÐÁÍÑÔÉ, ÏÔËÒÙÔÙÊ ÎÁ ÞÔÅÎÉÅ-ÚÁÐÉÓØ. ðÏÄÒÏÂÎÅÅ +ÒÁÂÏÔÁ Ó ÆÁÊÌÁÍÉ × ÐÁÍÑÔÉ ÏÐÉÓÁÎÁ × ÒÁÚÄÅÌÅ \ref{dgtInMemory} + +äÌÑ ÏÔËÒÙÔÉÑ ÆÁÊÌÏ× Ó ÐÒÅÄÅÌÁÍÉ É ÐÒÏÅËÃÉÅÊ ÁÎÁÌÏÇÉÞÎÙÍÉ ÕÖÅ ÓÕÝÅÓÔ×ÕÀÝÅÍÕ +ÆÁÊÌÕ, ÓÕÝÅÓÔ×ÕÀÔ ÆÕÎËÃÉÉ: + +\index{creat_dgt_as}% +\function{DGT *creat\_dgt\_as(char *filename,DGT *pattern);} +\index{fcreat_dgt_as}% +\function{DGT *fcreat\_dgt\_as(FILE *f,DGT *pattern);} +\index{mcreat_dgt_as}% +\function{DGT *mcreat\_dgt\_as(DGT *pattern);} + +\section{óÍÅÎÁ ÒÅÖÉÍÁ É ÚÁËÒÙÔÉÅ ÆÁÊÌÁ} + +æÕÎËÃÉÑ +\index{reset_dgt}% +\function{void reset\_dgt(DGT* dgt);} +ÄÅÌÁÅÔ ÔÅËÕÝÉÍ ÏÂßÅËÔÏÍ ÐÅÒ×ÙÊ. åÓÌÉ ÆÁÊÌ ÄÏ ÜÔÏÇÏ ÂÙÌ ÏÔËÒÙÔ × ÒÅÖÉÍÅ +ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÊ ÚÁÐÉÓÉ, ÏÎ ÐÅÒÅÏÔËÒÙ×ÁÅÔÓÑ × ÒÅÖÉÍÅ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÇÏ +ÞÔÅÎÉÑ. + +\index{load_dgt}% +\function{int load\_dgt(DGT *dgt);} +úÁÇÒÕÖÁÅÔ ÆÁÊÌ × ÐÁÍÑÔØ, ÄÅÌÁÑ ×ÏÚÍÏÖÎÙÍ ÐÒÑÍÏÊ ÄÏÓÔÕÐ ÎÁ ÞÔÅÎÉÅ-ÚÁÐÉÓØ +É ÍÎÏÇÉÅ ÄÒÕÇÉÅ ×ÏÚÍÏÖÎÏÓÔÉ, ÏÐÉÓÁÎÎÙÅ × ÒÁÚÄÅÌÅ \ref{dgtInMemory} + +\index{close_dgt}% +\function{void close\_dgt(DGT *dgt);} +úÁËÒÙ×ÁÅÔ ÆÁÊÌ, ÏÓ×ÏÂÏÖÄÁÑ ×ÓÀ ×ÙÄÅÌÅÎÎÕÀ ÐÏÄ ÎÅÇÏ ÐÁÍÑÔØ. éÚÍÅÎÅÎÉÑ +× ÐÏÓÌÅÄÎÅÍ ÏÂßÅËÔÅ ÓÏÈÒÁÎÑÀÔÓÑ, ÅÓÌÉ ÆÁÊÌ ÂÙÌ ÏÔËÒÙÔ ÄÌÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÊ +ÚÁÐÉÓÉ. + +\section{þÔÅÎÉÅ É ÚÁÐÉÓØ ÏÂßÅËÔÏ×} + +ðÏÓÌÅ ÏÔËÒÙÔÉÑ ÓÕÝÅÓÔ×ÕÀÝÅÇÏ ÆÁÊÌÁ, ÐÅÒ×ÙÊ ÏÂßÅËÔ Á×ÔÏÍÁÔÉÞÅÓËÉ ÓÞÉÔÙ×ÁÅÔÓÑ +× ÂÕÆÅÒ, É ÄÏÓÔÕÐÅÎ Ó ÐÏÍÏÝØÀ ÍÁËÒÏÓÏ× ÄÌÑ ÒÁÂÏÔÙ Ó ÂÕÆÅÒÏÍ (ÓÍ. ÒÁÚÄÅÌ +\ref{ItemMacros}). + +äÌÑ ÐÅÒÅÈÏÄÁ Ë ÓÌÅÄÕÀÝÅÍÕ ÏÂßÅËÔÕ ×ÙÚÙ×ÁÅÔÓÑ ÍÁËÒÏÓ +\index{dgt_next}% +\function{void dgt\_next(DGT *dgt);} + +÷ ÎÅËÏÔÏÒÙÈ ÓÌÕÞÁÑÈ ÕÄÏÂÎÏ ÒÁÂÏÔÁÔØ Ó ËÏÐÉÑÍÉ ÏÂßÅËÔÏ×, ÒÁÚÍÅÝÅÎÎÙÈ +× ÄÉÎÁÍÉÞÅÓËÏÊ ÐÁÍÑÔÉ. ÷ ÜÔÏÍ ÓÌÕÞÁÅ ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ +ÆÕÎËÃÉÀ + +\index{dgt_get}% +\function{DGT\_ITEM *dgt\_get(DGT *dgt)} + +ëÏÔÏÒÁÑ ÒÁÚÍÅÝÁÅÔ ÔÅËÕÝÉÊ ÏÂßÅËÔ × ÐÁÍÑÔÉ, ÐÅÒÅÍÅÝÁÅÔÓÑ ÎÁ ÓÌÅÄÕÀÝÉÊ +ÏÂßÅËÔ É ×ÏÚ×ÒÁÝÁÅÔ ÕËÁÚÁÔÅÌØ ËÏÐÉÀ ÏÂßÅËÔÁ, ÂÙ×ÛÉÊ ÔÅËÕÝÉÍ ÄÏ ÅÅ ×ÙÚÏ×Á. + +äÌÑ ÚÁÐÉÓÉ × ÆÁÊÌ ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÌÉÂÏ ÆÕÎËÃÉÀ + +\index{dgt_put}% +\function{void dgt\_put(DGT *dgt, DGT\_ITEM *item);} +ÌÉÂÏ ÍÏÄÉÆÉÃÉÒÏ×ÁÔØ ÔÅËÕÝÉÊ ÏÂßÅËÔ Ó ÐÏÍÏÝØÀ ÍÁËÒÏÓÏ× É ÆÕÎËÃÉÊ ÄÌÑ +ÒÁÂÏÔÙ Ó ÔÅËÕÝÅÊ ÚÁÐÉÓØÀ É ÚÁÔÅÍ ×ÙÚ×ÁÔØ {\tt dgt\_next} ÄÌÑ ÐÅÒÅÈÏÄÁ +Ë ÎÏ×ÏÍÕ ÏÂßÅËÔÕ. +\section{éÔÅÒÁÔÏÒÙ} +ðÏÓËÏÌØËÕ ×ÅËÔÏÒÎÙÅ ÆÁÊÌÙ ÈÒÁÎÑÔ Ä×Á ÔÉÐÁ ÏÂßÅËÔÏ×~--- ÌÉÎÉÉ É ÔÏÞËÉ, +É ÔÏÌØËÏ ÏÞÅÎØ ÎÅÍÎÏÇÉÅ ÁÌÇÏÒÉÔÍÙ (× ÏÓÎÏ×ÎÏÍ ÔÒÁÎÓÆÏÒÍÁÃÉÑ ËÏÏÒÄÉÎÁÔ) +ÚÁÔÒÁÇÉ×ÁÀÔ É ÔÅ É ÄÒÕÇÉÅ, ÏÐÒÅÄÅÌÅÎÙ ÉÔÅÒÁÔÏÒÙ: +\index{for_each_line}% +\function{for\_each\_line(DGT *dgt,void (*item\_proc)(DGT *dgt), + DGT *outstream);} +\index{for_each_point}% +\function{for\_each\_point(DGT *dgt,void (*item\_proc)(DGT *dgt), +DGT *outstream);} + +ïÎÉ ×ÙÚÙ×ÁÀÔ ÕËÁÚÁÎÎÕÀ ÆÕÎËÃÉÀ ÔÏÌØËÏ ÄÌÑ ÌÉÎÉÊ ÉÌÉ ÔÏÞÅË ÆÁÊÌÁ. +æÕÎËÃÉÉ ÐÅÒÅÄÁÅÔÓÑ ÕËÁÚÁÔÅÌØ ÎÁ ÓÔÒÕËÔÕÒÕ {\tt DGT} × ÂÕÆÅÒÅ +ËÏÔÏÒÏÊ ÎÁÈÏÄÉÔÓÑ ÏÂßÅËÔ. + +üÔÉ ÉÔÅÒÁÔÏÒÙ ÍÏÖÎÏ ÐÒÉÍÅÎÑÔØ Ë ÆÁÊÌÁÍ, ÏÔËÒÙÔÙÍ ÄÌÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÇÏ +ÞÔÅÎÉÑ ÉÌÉ Ë ÆÁÊÌÁÍ ÚÁÇÒÕÖÅÎÎÙÍ × ÐÁÍÑÔØ. + +åÓÌÉ ÐÁÒÁÍÅÔÒ {\tt outstream} ÎÅ {\tt NULL}, ÔÏ × ÆÁÊÌ, ÎÁ ËÏÔÏÒÙÊ +ÏÎ ÕËÁÚÙ×ÁÅÔ, ËÏÐÉÒÕÀÔÓÑ ×ÓÅ ÏÂßÅËÔÙ, ËÏÔÏÒÙÅ ÎÅ ÏÂÒÁÂÁÔÙ×ÁÌÉÓØ É +ÏÂÒÁÂÏÔÁÎÎÙÅ ÏÂßÅËÔÙ. + +ôÏ ÅÓÔØ, ÎÁÐÒÉÍÅÒ, × ÓÌÕÞÁÅ {\tt for\_each\_line} ÔÏÞËÁ ÂÕÄÅÔ ÓËÏÐÉÒÏ×ÁÎÁ +ÂÅÚ ÏÂÒÁÂÏÔËÉ, Á ÌÉÎÉÑ ÚÁÐÉÓÁÎÁ ÐÏÓÌÅ ÔÏÇÏ, ËÁË ÅÅ ÉÚÍÅÎÉÔ {\tt item\_proc}. + +ëÒÏÍÅ ÜÔÏÇÏ, ÓÕÝÅÓÔ×ÕÅÔ ÉÔÅÒÁÔÏÒ +\index{for_each_item} +\function{void for\_each\_item(DGT *dgt,void (*item\_proc)(DGT *dgt));} + +ËÏÔÏÒÙÊ ×ÙÐÏÌÎÑÅÔ ÐÅÒÅÄÁÎÎÕÀ ÆÕÎËÃÉÀ É ÄÌÑ ÌÉÎÉÊ É ÄÌÑ ÔÏÞÅË. +õ ÎÅÇÏ ÎÅÔ ÐÁÒÁÍÅÔÒÁ {\tt outstream}, ÔÁË ÞÔÏ ÅÓÌÉ ÎÕÖÎÏ ÚÁÐÉÓÁÔØ +ÉÚÍÅÎÅÎÎÙÅ ÏÂßÅËÔÙ, {\tt item\_proc} ÄÏÌÖÎÁ Ï ÜÔÏÍ ÐÏÚÁÂÏÔÉÔØÓÑ ÓÁÍÁ. +\section{òÁÂÏÔÁ Ó ÔÅËÕÝÉÍ ÏÂßÅËÔÏÍ} +\label{ItemMacros} +éÔÁË, ÎÕÖÎÁÑ ×ÁÍ ÌÉÎÉÑ (ÔÏÞËÁ) ÎÁÈÏÄÉÔÓÑ × ÂÕÆÅÒÅ ÓÔÒÕËÔÕÒÙ {\tt DGT}. +þÔÏ ÍÏÖÎÏ ÄÅÌÁÔØ Ó ÎÅÊ ÄÁÌØÛÅ? + +÷Ï-ÐÅÒ×ÙÈ, ÎÕÖÎÏ ÕÍÅÔØ ÏÐÒÅÄÅÌÑÔØ, ÌÉÎÉÑ ÜÔÏ ÉÌÉ ÔÏÞËÁ. +äÌÑ ÜÔÏÇÏ ÏÐÒÅÄÅÌÅÎÙ ÍÁËÒÏÓÙ: +\index{dgt_is_line}% +\function{int dgt\_is\_line(DGT *dgt)} +\index{dgt_is_point}% +\function{int dgt\_is\_point(DGT *dgt)} +÷Ï-×ÔÏÒÙÈ, ÎÅÚÁ×ÉÓÉÍÏ ÏÔ ÔÏÇÏ, ÌÉÎÉÑ ÜÔÏ ÉÌÉ ÔÏÞËÁ, +ÎÁÍ ÍÏÖÅÔ ÐÏÔÒÅÂÏ×ÁÔØÓÑ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÏÂßÅËÔÁ. +\index{dgt_id}% +\function{long int dgt\_id(DGT *dgt)} +÷-ÔÒÅÔØÉÈ, ËÏÏÒÄÉÎÁÔÙ ÔÏÞËÉ: +\index{dgt_pointx}% +\function{short int dgt\_pointx(DGT *dgt)} +\index{dgt_pointy}% +\function{short int dgt\_pointy(DGT *dgt)} +ÉÌÉ ËÏÏÒÄÉÎÁÔÙ ÐÒÑÍÏÕÇÏÌØÎÉËÁ-ÍÁÓËÉ ÌÉÎÉÉ: +\index{dgt_xl}% +\function{short int dgt\_xl(DGT *dgt)} +\index{dgt_yb}% +\function{short int dgt\_yb(DGT *dgt)} +\index{dgt_xr}% +\function{short int dgt\_xr(DGT *dgt)} +\index{dgt_yt}% +\function{short int dgt\_yt(DGT *dgt)} +÷-ÞÅÔ×ÅÒÔÙÈ, ËÏÌÉÞÅÓÔ×Ï ÔÏÞÅËÔ × ÌÉÎÉÉ: +\index{dgt_line_len}% +\function{short int dgt\_line\_len(DGT *dgt)} +é, ÎÁËÏÎÅÃ, ËÏÏÒÄÉÎÁÔÙ $i$-ÔÏÇÏ ÕÚÌÁ ÌÉÎÉÉ: +\index{dgt_nx}% +\function{short int dgt\_nx(DGT *dgt,int i)} +\index{dgt_ny}% +\function{short int dgt\_ny(DGT *dgt,int i)} +ïÂÒÁÔÉÔÅ ×ÎÉÍÁÎÉÅ, ÞÔÏ ÐÅÒ×ÁÑ ÔÏÞËÁ ÌÉÎÉÉ ÉÍÅÅÔ ÎÏÍÅÒ 0, Á ÐÏÓÌÅÄÎÑÑ~--- +{\tt dgt\_line\_len(dgt)-1}. + +ëÒÏÍÅ ÔÏÇÏ, ÉÎÏÇÄÁ ÕÄÏÂÎÅÅ ÐÏÌÕÞÉÔØ ÓÓÙÌËÕ ÎÁ ÔÏÞËÕ ÉÌÉ ÕÚÅÌ ÌÉÎÉÉ, +ËÁË ÎÁ ÓÔÒÕËÔÕÒÕ {\tt POINT}. äÌÑ ÜÔÏÇÏ ÐÒÅÄÎÁÚÎÁÞÅÎÙ ÍÁËÒÏÓÙ: +\index{dgt_node}% +\function{POINT dgt\_node(DGT *dgt,int i)} +\index{dgt_point}% +\function{POINT dgt\_point(DGT *dgt)} + +åÓÌÉ ×ÁÍ ÐÏ ËÁËÉÍ-ÔÏ ÐÒÉÞÉÎÁÍ ÎÕÖÎÏ ÒÁÂÏÔÁÔØ ÎÅ ÓÏ ÓÔÒÕËÔÕÒÏÊ {\tt DGT}, +Á Ó ÏÔÄÅÌØÎÙÍ ÏÂßÅËÔÏÍ, ÒÁÚÍÅÝÅÎÎÙÍ × ÄÉÎÁÍÉÞÅÓËÏÊ ÐÁÍÑÔÉ, ÔÏ ÚÁÍÅÎÉÔÅ +ÐÒÅÆÉËÓ {\tt dgt\_} ÎÁ ÐÒÅÆÉËÓ {\tt item\_} É × ËÁÞÅÓÔ×Å ÐÅÒ×ÏÇÏ +ÐÁÒÁÍÅÔÒÁ ÕËÁÚÙ×ÁÊÔÅ ÕËÁÚÁÔÅÌØ ÎÁ ÓÔÒÕËÔÕÒÕ {\tt DGT\_ITEM}\index{DGT_ITEM}. + +ôÅÐÅÒØ ÍÙ ÍÏÖÅÍ ÐÒÏÞÉÔÁÔØ ÌÀÂÏÊ ÐÁÒÁÍÅÔÒ ÏÂßÅËÔÁ. ÷ÏÐÒÏÓ × ÔÏÍ, ËÁË ÅÇÏ +ÉÚÍÅÎÉÔØ. + +ïÔ×ÅÔ ÐÅÒ×ÙÊ, ÐÁÒÁÄÏËÓÁÌØÎÙÊ: ÌÀÂÏÊ ÉÚ ×ÙÛÅÐÒÉ×ÅÄÅÎÎÙÈ ÍÁËÒÏÓÏ× (ËÒÏÍÅ +{\tt dgt\_is\_line}\index{dgt_is_line} É {\tt dgt\_is\_point})\index{dgt_is_point} ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ × {\bf ÌÅ×ÏÊ} +ÞÁÓÔÉ ÏÐÅÒÁÔÏÒÁ ÐÒÉÓ×ÁÉ×ÁÎÉÑ. + +÷ÅÄØ ÜÔÏ ÎÅ ÆÕÎËÃÉÉ, Á ÍÁËÒÏÓÙ, ÄÁÀÝÉÅ ÄÏÓÔÕÐ Ë ÎÅËÏÔÏÒÙÍ ÐÏÌÑÍ ÓÔÒÕËÔÕÒÙ +{\tt DGT\_ITEM}. + +ïÄÎÁËÏ ÔÁË ÐÏÓÔÕÐÁÔØ ÎÅ ÒÅËÏÍÅÎÄÕÅÔÓÑ. äÅÌÏ × ÔÏÍ, ÞÔÏ × ÔÁËÏÍ ÓÌÕÞÁÅ +ÎÉÇÄÅ ÎÅ ÂÕÄÅÔ ÏÔÍÅÞÅÎÏ, ÞÔÏ ÏÂßÅËÔ ÉÚÍÅÎÅÎ, ÐÏÜÔÏÍÕ ÉÚÍÅÎÅÎÉÑ ÍÏÇÕÔ ÂÙÔØ +ÎÅ ÓÏÈÒÁÎÅÎÙ. åÓÌÉ ÕÖ ÏÞÅÎØ ÈÏÞÅÔÓÑ, ÔÏ ÐÏÓÌÅ ÐÒÑÍÏÇÏ ÉÚÍÅÎÅÎÉÑ ÐÏÌÅÊ +ÏÂßÅËÔÁ, ÉÓÐÏÌØÚÕÊÔÅ ÆÕÎËÃÉÀ + +\function{void dgt\_touch(DGT *dgt)}\index{dgt_touch} +ÞÔÏÂÙ ÐÏÍÅÔÉÔØ ÏÂßÅËÔ ËÁË ÉÚÍÅÎÅÎÎÙÊ. + +îÏ ÌÕÞÛÅ ÐÏÌØÚÏ×ÁÔØÓÑ ÓÌÅÄÕÀÝÉÍÉ ÆÕÎËÃÉÑÍÉ: + +\function{void dgt\_set\_id(DGT *dgt,long int newID);}\index{dgt_set_id} +õÓÔÁÎÁ×ÌÉ×ÁÅÔ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÏÂßÅËÔÁ. +\function{void dgt\_set\_point(DGT *dgt, int x, int y);}\index{dgt_set_point} +úÁÄÁÅÔ ËÏÏÒÄÉÎÁÔÙ ÔÏÞËÉ É ÄÅÌÁÅÔ ÏÂßÅËÔ ÔÏÞËÏÊ. åÓÌÉ ×Ù ÈÏÔÉÔÅ ÓÏÈÒÁÎÉÔØ +ÏÄÎÕ ËÏÏÒÄÉÎÁÔÕ, ×ÍÅÓÔÏ ÎÅÅ ÐÅÒÅÄÁÊÔÅ ËÏÎÓÔÁÎÔÕ {\tt KEEP\_OLD\_VALUE}% +\index{KEEP_OLD_VALUE} +\function{int dgt\_add\_node(DGT *dgt,int x,int y);}\index{dgt_add_node} +äÏÂÁ×ÌÑÅÔ ÔÏÞËÕ × ËÏÎÅà ÌÉÎÉÉ (ÉÌÉ ÓÏÚÄÁÅÔ ÐÅÒ×ÕÀ ÔÏÞËÕ É ÐÏÍÅÞÁÅÔ +ÏÂßÅËÔ ËÁË ÌÉÎÉÀ. ÷ÏÚ×ÒÁÝÁÅÔ 0 × ÓÌÕÞÁÅ, ÅÓÌÉ ×ÓÅ × ÐÏÒÑÄËÅ ÉÌÉ +ÎÅÎÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ, ÅÓÌÉ ÔÏÞËÕ ÄÏÂÁ×ÉÔØ ÎÅ×ÏÚÍÏÖÎÏ (ÕÖÅ ÅÓÔØ 500 ÔÏÞÅË). +\function{int dgt\_ins\_node(DGT *dgt,int index,int x,int y)}\index{dgt_ins_node} +÷ÓÔÁ×ÌÑÅÔ ÔÏÞËÕ × ÌÉÎÉÀ ÐÅÒÅÄ ÕÚÌÏÍ ÎÏÍÅÒ {\tt index}. ÷ÏÚ×ÒÁÝÁÅÔ 0, +ÅÓÌÉ ×ÓÅ × ÐÏÒÑÄËÅ, 1 ÅÓÌÉ ÞÉÓÌÏ ÔÏÞÅË ÐÒÅ×ÙÓÉÔ 500, É 2 ÅÓÌÉ ÕÚÌÁ Ó ÔÁËÉÍ +ÎÏÍÅÒÏÍ ÎÅÔ. +\function{int dgt\_mv\_node(DGT *dgt,int index,int x,int y)}\index{dgt_mv_node} +íÅÎÑÅÔ ËÏÏÒÄÉÎÁÔÙ ÕËÁÚÁÎÎÏËÇÏ ÕÚÌÁ ÎÁ ÚÁÄÁÎÎÙÅ. ÷ÏÚ×ÒÁÝÁÅÔ 0, ÅÓÌÉ +×ÓÅ × ÐÏÒÑÄËÅ É ÎÅÎÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ, ÅÓÌÉ ÔÁËÏÇÏ ÕÚÌÁ ÎÅÔ. + +åÓÌÉ ×ÁÍ ÎÁÄÏ ÉÚÍÅÎÉÔØ ÔÏÌØËÏ ÏÄÎÕ ËÏÏÒÄÉÎÁÔÕ, ÐÅÒÅÄÁÊÔÅ ×ÍÅÓÔÏ ×ÔÏÒÏÊ +ËÏÎÓÔÁÎÔÕ {\tt KEEP\_OLD\_VALUE}\index{KEEP_OLD_VALUE}. + +\function{int dgt\_rm\_node(DGT *dgt,int index)}\index{dgt_rm_node} +õÄÁÌÑÅÔ ÕËÁÚÁÎÎÙÊ ÕÚÅÌ. ïÛÉÂËÁ ×ÏÚÎÉËÁÅÔ, ÅÓÌÉ ÜÔÏ ÂÙÌ ÐÒÅÄÐÏÓÌÅÄÎÉÊ ÕÚÅÌ +× ÌÉÎÉÉ. (ëÏÒÒÅËÔÎÁÑ ÌÉÎÉÑ ÄÏÌÖÎÁ ÓÏÄÅÒÖÁÔØ ÎÅ ÍÅÎÅÅ Ä×ÕÈ ÕÚÌÏ×). + +é, ÎÁËÏÎÅÃ, ÒÁÚÒÅÚÁÎÉÅ ÌÉÎÉÊ. + +\function{int dgt\_split(DGT *dgt,int index)}\index{dgt_split} +òÁÚÒÅÚÁÅÔ ÌÉÎÉÀ × ÕËÁÚÁÎÎÏÍ ÕÚÌÅ. ðÒÉ ÜÔÏÍ +ÕÚÅÌ ÄÕÂÌÉÒÕÅÔÓÑ É ÐÏÐÁÄÁÅÔ × ÏÂÅ ÐÏÌÏ×ÉÎËÉ. ôÅËÕÝÉÍ ÓÔÁÎÏ×ÉÔÓÑ È×ÏÓÔ ÌÉÎÉÉ, +Á ÎÁÞÁÌÏ, ÅÓÌÉ ÆÁÊÌ ÂÙÌ ÏÔËÒÙÔ × ÒÅÖÉÍÅ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÊ ÚÁÐÉÓÉ, ÓÂÒÁÓÙ×ÁÅÔÓÑ +ÎÁ ÄÉÓË. üÔÏÊ ÆÕÎËÃÉÅÊ ÎÅÌØÚÑ ÐÏÌØÚÏ×ÁÔØÓÑ ÉÚ ÉÔÅÒÁÔÏÒÁ {\tt for\_each\_line}\index{for_each_line}, +ÅÓÌÉ ÏÎ ÐÒÉÍÅÎÑÅÔÓÑ Ë ÆÁÊÌÕ, ÏÔËÒÙÔÏÍÕ × ÒÅÖÉÍÅ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÇÏ ÞÔÅÎÉÑ. + +\function{int dgt\_cut\_segment(DGT *dgt,int index)}\index{dgt_cut_segment} +òÁÚÒÅÚÁÅÔ ÌÉÎÉÀ, ÕÄÁÌÑÑ ÏÔÒÅÚÏË ÏÔ $n-1$ ÄÏ $n$-ÎÏÇÏ ÕÚÌÁ. ÷ÓÅ ÏÓÔÁÌØÎÏÅ +× ÔÏÞÎÏÓÔÉ ËÁË × ÐÒÅÄÙÄÕÝÅÍ ÓÌÕÞÁÅ. + +ðÒÏÃÅÄÕÒÁ {\tt dgt\_next}\index{dgt_next} ÐÏÚÁÂÏÔÉÔÓÑ Ï ÎÅËÏÔÏÒÙÈ ÉÚ ÏÛÉÂÏË, ËÏÔÏÒÙÅ +ÍÏÖÎÏ ÄÏÐÕÓÔÉÔØ ÐÒÉ ÒÅÄÁËÔÉÒÏ×ÁÎÉÉ ÏÂßÅËÔÁ. +\begin{enumerate} +\item íÁÓËÁ ÌÉÎÉÉ ÂÕÄÅÔ ÓËÏÒÒÅËÔÉÒÏ×ÁÎÁ. +\item éÚ Ä×ÕÈ ÓÏÓÅÄÎÉÈ ÕÚÌÏ× Ó ÓÏ×ÐÁÄÁÀÝÉÍÉ ËÏÏÒÄÉÎÁÔÁÍÉ ÂÕÄÅÔ ÏÓÔÁ×ÌÅÎ ÏÄÉÎ. +\item ìÉÎÉÉ ÉÚ ÏÄÎÏÊ ÔÏÞËÉ ÂÕÄÕÔ ×ÙÂÒÏÛÅÎÙ. +\item ôÏÞËÁ Ó ÎÕÌÅ×ÙÍ ÉÄÅÎÔÉÆÉËÁÔÏÒÏÍ ÂÕÄÅÔ ×ÙÂÒÏÛÅÎÁ. +\end{enumerate} + +\section{DGT-ÆÁÊÌÙ × ÐÁÍÑÔÉ} + +\label{dgtInMemory} +÷ÅËÔÏÒÎÙÊ ÆÁÊÌ, ÚÁÇÒÕÖÅÎÎÙÊ × ÐÁÍÑÔØ, ÍÏÖÎÏ ÒÁÓÓÍÁÔÒÉ×ÁÔØ ËÁË ÍÁÓÓÉ× +ÏÂßÅËÔÏ×. ðÏÓÌÅÄÏ×ÁÔÅÌØÎÙÊ ÄÏÓÔÕÐ ÐÒÏÄÏÌÖÁÅÔ ÒÁÂÏÔÁÔØ, ÎÏ ÓÕÝÅÓÔ×ÕÀÔ +ÆÕÎËÃÉÉ, ÐÏÚ×ÏÌÑÀÝÉÅ ÓÄÅÌÁÔØ ÔÅËÕÝÉÍ ÏÂßÅËÔÏÍ ÌÀÂÏÊ, ÎÅÚÁ×ÉÓÉÍÏ +ÏÔ ÐÏÒÑÄËÁ É ÏÂÒÁÝÁÔØÓÑ Ë ÏÂßÅËÔÁÍ, ÎÅ ÄÅÌÁÑ ÉÈ ÔÅËÕÝÉÍÉ. + +ðÏÓÌÅÄÎÉÊ ÓÐÏÓÏ ÉÍÅÅÔ ÓÕÝÅÓÔ×ÅÎÎÙÊ ÎÅÄÏÓÔÁÔÏË~--- ÅÓÌÉ ×Ù ÈÏÔÉÔÅ +ÉÚÍÅÎÉÔØ ÄÌÉÎÕ ÌÉÎÉÉ, ÔÏ ×ÁÍ ÐÒÉÄÅÔÓÑ ÓÁÍÏÍÕ ÐÏÚÁÂÏÔÉÔØÓÑ Ï ×ÙÄÅÌÅÎÉÉ +ÐÁÍÑÔÉ ÐÏÄ ÎÏ×ÕÀ ÌÉÎÉÀ. + +éÔÁË, ÐÒÏÃÅÄÕÒÙ, ÓÐÅÃÉÆÉÞÎÙÅ ÄÌÑ ÆÁÊÌÁ × ÐÁÍÑÔÉ: + +\function{int dgt\_seek(DGT *dgt,int index);}\index{dgt_seek} + +äÅÌÁÅÔ ÔÅËÕÝÉÍ ÏÂßÅËÔ Ó ÕËÁÚÁÎÎÙÍ ÎÏÍÅÒÏÍ. (ÐÏÓÌÅ ÞÅÇÏ ÍÏÖÎÏ +ÓÐÏËÏÊÎÏ ÅÇÏ ÍÅÎÑÔØ Ó ÐÏÍÏÝØÀ ÌÀÂÙÈ ÆÕÎËÃÉÊ É ÍÁËÒÏÓÏ× ÐÒÅÄÙÄÕÝÅÇÏ ÒÁÚÄÅÌÁ.) + +\function{DGT\_ITEM* dgt\_item\_ptr(DGT *dgt,int index);}\index{dgt_item_ptr} +% +÷ÏÚ×ÒÁÝÁÅÔ ÕËÁÚÁÔÅÌØ ÎÁ ÏÂßÅËÔ Ó ÕËÁÚÁÎÎÙÍ ÎÏÍÅÒÏÍ. äÌÑ ÄÏÓÔÕÐÁ +Ë ÜÔÏÍÕ ÏÂßÅËÔÕ ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÍÁËÒÏÓÙ {\tt item\_\dots}. + +üÔÏÔ ÓÐÏÓÏ ÄÏÓÔÕÐÁ ÒÅËÏÍÅÎÄÕÅÔÓÑ ÉÓÐÏÌØÚÏ×ÁÔØ ËÁË ÄÏÓÔÕÐ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ. +÷ ËÒÁÊÎÅÍ ÓÌÕÞÁÅ, ÅÓÌÉ ÎÅÏÂÈÏÄÉÍÏ ÉÚÍÅÎÉÔØ ÎÅ ÔÅËÕÝÕÀ ÌÉÎÉÀ, ×ÏÓÐÏÌØÚÕÊÔÅÓØ +ÆÕÎËÃÉÅÊ: +\function{int dgt\_replace(DGT *dgt,int index,DGT\_ITEM* new\_item);}\index{dgt_replace} + +üÔÁ ÆÕÎËÃÉÑ ÐÏÌÕÞÁÅÔ ÕËÁÚÁÔÅÌØ ÎÁ ÄÉÎÁÍÉÞÅÓËÉ ÒÁÚÍÅÝÅÎÎÙÊ ÏÂßÅËÔ +É ÐÏÍÅÝÁÅÔ ÅÇÏ × ÆÁÊÌ. äÌÑ ÔÏÇÏ, ÞÔÏÂÙ ÓÜËÏÎÏÍÉÔØ ÐÁÍÑÔØ, +ÒÁÚÍÅÝÁÊÔÅ ÏÂßÅËÔ Ó ÐÏÍÏÝØÀ ÆÕÎËÃÉÉ +\function{DGT\_ITEM *alloc\_item(DGT\_ITEM *item);}\index{alloc_item} +üÔÁ ÆÕÎËÃÉÑ ÐÏÌÕÞÁÅÔ ÕËÁÚÁÔÅÌØ ÎÁ ÏÂßÅËÔ, ×ÙÄÅÌÑÅÔ ÐÁÍÑÔÉ ÒÏ×ÎÏ ÓÔÏÌØËÏ, +ÓËÏÌØËÏ ÎÕÖÎÏ, ÞÔÏÂÙ ÒÁÚÍÅÓÔÉÔØ ÜÔÏÔ ÏÂßÅËÔ, É ËÏÐÉÒÕÅÔ ÅÇÏ ÔÕÄÁ. + +æÕÎËÃÉÉ ×ÓÔÁ×ËÉ ÏÂßÅËÔÁ × ÕËÁÚÁÎÎÏÍ ÍÅÓÔÅ × ÂÉÂÌÉÏÔÅËÅ ÎÅÔ. +ðÒÉ ÄÏÂÁ×ÌÅÎÉÉ ÏÂßÅËÔÁ Ó ÐÏÍÏÝØÀ {\tt dgt\_put}\index{dgt_put} ÅÇÏ ÍÅÓÔÏ ÏÐÒÅÄÅÌÑÅÔÓÑ +× ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó ÔÅËÕÝÉÍ ÐÏÒÑÄËÏÍ ÓÏÒÔÉÒÏ×ËÉ. åÓÌÉ ÐÏÒÑÄÏË ÓÏÒÔÉÒÏ×ËÉ +×ÏÏÂÝÅ ÎÅ ÚÁÄÁ×ÁÌÓÑ, ÔÏ ÜÔÏ ÂÕÄÅÔ ÓÌÅÄÕÀÝÉÊ ÏÂßÅËÔ ÐÏÓÌÅ ÔÅËÕÝÅÇÏ, +É ÏÎ ÓÔÁÎÅÔ ÔÅËÕÝÉÍ. + +ðÏÒÑÄÏË ÓÏÒÔÉÒÏ×ËÉ dgt ÆÁÊÌÁ × ÐÁÍÑÔÉ ÍÏÖÎÏ ÉÚÍÅÎÉÔØ ÐÒÉ +ÐÏÍÏÝÉ ÆÕÎËÃÉÉ +\function{void dgt\_sort(DGT *dgt,int (*compare\_func)(DGT\_ITEM* i1, DGT\_ITEM * i2));}\index{dgt_sort} + +æÕÎËÃÉÑ {\tt compare\_func} ÄÏÌÖÎÁ ×ÏÚ×ÒÁÝÁÔØ 1, ÅÓÌÉ i1 ÎÁÄÏ ÒÁÚÍÅÓÔÉÔØ +ÐÏÚÖÅ, ÞÅÍ i2, -1 ÅÓÌÉ ÎÁÏÂÏÒÏÔ, É 0, ÅÓÌÉ ÐÏ ÄÁÎÎÏÍÕ ËÒÉÔÅÒÉÀ ÓÏÒÔÉÒÏ×ËÉ +ÜÔÉ ÏÂßÅËÔÙ ÒÁ×ÎÙ. + +éÚÍÅÎÅÎÉÅ ËÒÉÔÅÒÉÑ ÓÏÒÔÉÒÏ×ËÉ ÐÒÉ ÕÖÅ ÚÁÇÒÕÖÅÎÎÏÍ ÆÁÊÌÅ ÐÒÉ×ÏÄÉÔ +Ë ÅÇÏ ÐÅÒÅÓÏÒÔÉÒÏ×ËÅ Ó ÐÏÍÏÝØÀ ÆÕÎËÃÉÉ {\tt qsort}. + +ðÏÜÔÏÍÕ ÌÕÞÛÅ ×ÙÚÙ×ÁÔØ {\tt dgt\_sort} {\bf ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÏ ÐÅÒÅÄ}{\tt load\_dgt}. + + +÷ÙÚÏ× {\tt dgt\_sort(dgt,NULL)} ÐÒÉ×ÏÄÉÔ Ë ÏÔÍÅÎÅ ÓÏÒÔÉÒÏ×ËÉ. +ðÏÒÑÄÏË ÒÁÓÐÏÌÏÖÅÎÉÑ ÓÕÝÅÓÔ×ÕÀÝÉÈ ÏÂßÅËÔÏ× ÎÅ ÍÅÎÑÅÔÓÑ, ÎÏ ÎÏ×ÙÅ ÄÏÂÁ×ÌÑÅÍÙÅ +ÏÂßÅËÔÙ ÂÕÄÕÔ ÒÁÓÐÏÌÁÇÁÔØÓÑ ÂÅÚ ÕÞÅÔÁ ÆÕÎËÃÉÉ ÓÏÒÔÉÒÏ×ËÉ. + +\section{òÁÂÏÔÁ Ó ËÏÏÒÄÉÎÁÔÁÍÉ} +äÌÑ ÐÅÒÅÓÞÅÔÁ ËÏÏÒÄÉÎÁÔ ÉÚ ×ÎÕÔÒÅÎÎÅÇÏ ÐÒÅÄÓÔÁ×ÌÅÎÉÑ dgt-ÆÁÊÌÁ × +ÁÌØÔÅÒÎÁÔÉ×ÎÙÅ É ÏÂÒÁÔÎÏ ÐÒÉÍÅÎÑÀÔÓÑ ÆÕÎËÃÉÉ: +\function{int dgt\_x(DGT* dgt,double x);}\index{dgt_x} +\function{int dgt\_y(DGT* dgt,double y);}\index{dgt_y} + +\function{double real\_x(DGT* dgt,int x);}\index{real_x} +\function{double real\_y(DGT* dgt,int y);}\index{real_y} +äÏÓÔÁÔÏÞÎÏ ÞÁÓÔÏ ×ÏÚÎÉËÁÅÔ ÚÁÄÁÞÁ ÐÅÒÅÓÞÅÔÁ ÉÎÔÅÒ×ÁÌÏ×, ËÏÔÏÒÁÑ ÍÏÖÅÔ +ÂÙÔØ ×ÙÐÏÌÎÅÎÁ Ó ÍÅÎØÛÉÍ ÞÉÓÌÏÍ ÏÐÅÒÁÃÉÊ, ÞÅÍ ×ÙÞÉÓÌÅÎÉÅ ÓÏÂÓÔ×ÅÎÎÏ +ËÏÏÒÄÉÎÁÔ. +äÌÑ ÜÔÏÇÏ ÏÐÒÅÄÅÌÅÎÙ ÆÕÎËÃÉÉ +\function{double real\_dx(DGT *dgt,int dx);}\index{real_dx} +\function{double real\_dy(DGT *dgt,int dy);}\index{real_dy} +é, ÎÁËÏÎÅÃ, ×ÙÞÉÓÌÅÎÉÅ ÒÁÓÓÔÏÑÎÉÊ. +\function{double dgt\_dist(DGT *dgt, int x1, int y1, int x2, int y2);}\index{dgt_dist} +÷ÙÞÉÓÌÑÅÔ ÒÁÓÓÔÏÑÎÉÅ ÍÅÖÄÕ Ä×ÕÍÑ ÔÏÞËÁÍÉ ÚÁÄÁÎÎÙÍÉ ÐÁÒÁÍÉ ×ÎÕÔÒÅÎÎÉÈ +ËÏÏÒÄÉÎÁÔ × ÅÄÉÎÉÃÁÈ ÁÌØÔÅÒÎÁÔÉ×ÎÙÈ ËÏÏÒÄÉÎÁÔ. + +äÌÑ ×ÙÞÉÓÌÅÎÉÑ ÒÁÓÓÔÏÑÎÉÑ ÍÅÖÄÕ Ä×ÕÍÑ ÕÚÌÁÍÉ ÌÉÎÉÉ ÍÏÖÎÏ +ÉÓÐÏÌØÚÏ×ÁÔØ ÆÕÎËÃÉÀ +\function{double dgt\_pdist(DGT *dgt, POINT p1, POINT p2);}\index{dgt_pdist} + +÷Ï ÍÎÏÇÉÈ ÁÌÇÏÒÉÔÍÁÈ ÒÁÓÓÔÏÑÎÉÑ ÉÓÐÏÌØÚÕÀÔÓÑ ÔÏÌØËÏ ÄÌÑ ÓÒÁ×ÎÅÎÉÑ +ÍÅÖÄÕ ÓÏÂÏÊ (É, ×ÏÚÍÏÖÎÏ, Ó ÎÅËÏÔÏÒÙÍÉ ËÏÎÓÔÁÎÔÁÍÉ). +÷ ÜÔÉÈ ÓÌÕÞÁÑÈ ÍÏÖÎÏ ÉÚÂÅÖÁÔØ ÎÅ ÔÏÌØËÏ ÐÅÒÅ×ÏÄÁ ÒÁÓÓÔÏÑÎÉÑ × ÏÓÍÙÓÌÅÎÎÙÅ +ÅÄÉÎÉÃÙ, ÎÏ É ÉÚ×ÌÅÞÅÎÉÑ ËÏÒÎÑ É Ó×ÅÓÔÉ ×ÓÅ ×ÙÞÉÓÌÅÎÉÑ Ë ÏÐÅÒÁÃÉÑÍ Ó +ÃÅÌÙÍÉ. + +äÌÑ ÜÔÏÇÏ ÐÒÅÄÎÁÚÎÁÞÅÎÙ ÆÕÎËÃÉÉ +\function{long int sq\_dist(DGT *dgt,int x1, int y1, int x2, int y2);}\index{sq_dist} +\function{long int sq\_pdist(DGT *dgt,POINT p1, POINT p2);}\index{sq_pdist} +×ÙÞÉÓÌÑÀÝÉÅ Ë×ÁÄÒÁÔ ÒÁÓÓÔÏÑÎÉÑ ÍÅÖÄÕ ÔÏÞËÁÍÉ × ÎÅËÏÔÏÒÙÈ ÕÓÌÏ×ÎÙÈ ÅÄÉÎÉÃÁÈ. +(ÉÚ×ÅÓÔÎÏ, ÞÔÏ Ë×ÁÄÒÁÔ ÐÒÉ $x>=0$~--- ÆÕÎËÃÉÑ ÍÏÎÏÔÏÎÎÁÑ). + +äÌÑ ÔÏÇÏ, ÞÔÏÂÙ ÉÍÅÔØ ×ÏÚÍÏÖÎÏÓÔØ ÓÒÁ×ÎÉ×ÁÔØ ÒÅÚÕÌØÔÁÔÙ ÆÕÎËÃÉÉ {\tt sq\_dist} +Ó ËÏÎÓÔÁÎÔÁÍÉ, ÚÁÄÁÎÎÙÍÉ ÉÚÎÁÞÁÌØÎÏ ËÁË ÒÁÓÓÔÏÑÎÉÑ × ÁÌØÔÅÒÎÁÔÉ×ÎÙÈ ËÏÏÒÄÉÎÁÔÁÈ, +ÉÓÐÏÌØÚÕÅÔÓÑ ÆÕÎËÃÉÑ +\function{long int sq\_const(DGT *dgt,double dist);}\index{sq_const} +ïÎÁ ÐÅÒÅ×ÏÄÉÔ ÒÁÓÓÔÏÑÎÉÅ, ÚÁÄÁÎÎÏÅ × ÅÄÉÎÉÃÁÈ ÁÌØÔÅÒÎÁÔÉ×ÎÙÈ ËÏÏÒÄÉÎÁÔ, +× ÕÓÌÏ×ÎÏÅ ÚÎÁÞÅÎÉÅ, ÁÎÁÌÏÇÉÞÎÏÅ ×ÏÚ×ÒÁÝÁÅÍÙÍ {\tt sq\_dist} + +ëÒÏÍÅ ÒÁÓÓÔÏÑÎÉÊ, ÎÅÓÏÏÔ×ÅÔÓÔ×ÉÅ ÅÄÉÎÉà ËÏÏÒÄÉÎÁÔ ÐÏ ÏÓÑÍ ×ÌÉÑÅÔ É ÎÁ + ÎÁ ×ÙÞÉÓÌÅÎÉÅ ÕÇÌÏ×. ðÏÜÔÏÍÕ × ÂÉÂÌÉÏÔÅËÕ ×ËÌÀÞÅÎÁ ÆÕÎËÃÉÑ + +\function{double dgt\_atan2(DGT *dgt,int dy, int dx);}\index{dgt_atan2} + +×ÙÞÉÓÌÑÀÝÁÑ ÁÒËÔÁÎÇÅÎÓ ÏÔÎÏÛÅÎÉÑ {$\Delta y\over \Delta x$} Ó ÐÏÐÒÁ×ËÏÊ ÎÁ ËÏÏÒÄÉÎÁÔÎÕÀ +ÓÉÓÔÅÍÕ ÕËÁÚÁÎÎÏÇÏ ÆÁÊÌÁ. ÷ ÏÓÔÁÌØÎÏÍ ÅÅ ÄÅÊÓÔ×ÉÅ ÐÏÌÎÏÓÔØÀ ÜË×É×ÁÌÅÎÔÎÏ +ÂÉÂÌÉÏÔÅÞÎÏÊ ÆÕÎËÃÉÉ {\tt atan2}. + +\chapter{æÕÎËÃÉÉ-ÕÔÉÌÉÔÙ} +\label{utils} +÷ ÂÉÂÌÉÏÔÅËÕ ×ËÌÀÞÅÎ ÒÑÄ ÆÕÎËÃÉÊ, ËÏÔÏÒÙÅ ÎÅ ÒÁÂÏÔÁÀÔ ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÏ +Ó ÆÁÊÌÁÍÉ EPPL7, ÎÏ ÐÏÌÅÚÎÙ ÐÒÉ ÎÁÐÉÓÁÎÉÉ ÍÁÌÅÎØËÉÈ ËÏÍÁÎÄÎÏ-ÓÔÒÏÞÎÙÈ +ÐÒÏÇÒÁÍÍ ÄÌÑ ÒÁÂÏÔÙ Ó ÜÔÉÍÉ ÆÁÊÌÁÍÉ. + +÷ ÏÔÌÉÞÉÅ ÏÔ ÏÓÔÁÌØÎÏÊ ÂÉÂÌÉÏÔÅËÉ, ÜÔÉ ÆÕÎËÃÉÉ ÓÉÓÔÅÍÎÏ-ÚÁ×ÉÓÉÍÙ. +ðÒÉ ÐÅÒÅÎÏÓÅ ÂÉÂÌÉÏÔÅËÉ × ÄÒÕÇÕÀ ÏÐÅÒÁÃÉÏÎÎÕÀ ÓÒÅÄÕ ÉÈ ÔÒÅÂÕÅÔÓÑ +ÐÅÒÅÐÉÓÁÔØ ÐÏÌÎÏÓÔØÀ É ÍÏÖÅÔ ÂÙÔØ ÄÁÖÅ ÉÚÍÅÎÉÔØ ÉÈ ÎÁÂÏÒ. + +îÁÐÒÉÍÅÒ, ÓÔÁÎÄÁÒÔÎÙÅ ÂÉÂÌÉÏÔÅËÉ ÂÏÌØÛÉÎÓÔ×Á ËÏÍÐÉÌÑÔÏÒÏ× C ÐÏÄ DOS +É Windows ÎÅ ×ËÌÀÞÁÀÔ ÆÕÎËÃÉÉ {\tt getopt}, ËÏÔÏÒÁÑ ÁËÔÉ×ÎÏ +ÉÓÐÏÌØÚÕÅÔÓÑ × Environmental Planning Utilities. + +æÕÎËÃÉÉ ÜÔÏÊ ÇÒÕÐÐÙ ÏÐÉÓÁÎÙ × ÚÁÇÏÌÏ×ÏÞÎÏÍ ÆÁÊÌÅ {\tt }. + +\section{ïÂÒÁÂÏÔËÁ ÉÍÅÎ ÆÁÊÌÏ×} + +\function{char *default\_ext(const char *name, const char *ext);}% +\index{default_ext} + +ÐÒÏ×ÅÒÑÅÔ, ÏËÁÎÞÉ×ÁÅÔÓÑ ÌÉ ÉÍÑ ÆÁÊÌÁ ÎÁ ÕËÁÚÁÎÎÏÅ ÒÁÓÛÉÒÅÎÉÅ. +åÓÌÉ ÎÅÔ, ÔÏ ÄÏÂÁ×ÌÑÅÔ ÅÇÏ. + +{\small \it ïÞÅ×ÉÄÎÏ, ÞÔÏ × ÆÁÊÌÏ×ÙÈ ÓÉÓÔÅÍÁÈ FAT É HPFS, ÇÄÅ ÎÅÓËÏÌØËÏ +ÒÁÓÛÉÒÅÎÉÊ ÎÅÄÏÐÕÓÔÉÍÙ, ÜÔÁ ÆÕÎËÃÉÑ ÄÏÌÖÎÁ ÐÒÏ×ÅÒÑÔØ ÎÁÌÉÞÉÅ ÎÅ ÄÁÎÎÏÇÏ, +Á ÌÀÂÏÇÏ ÒÁÓÛÉÒÅÎÉÑ.} + +\function{char *force\_ext(const char *name, const char *ext);} +\index{force_ext} + +ÚÁÍÅÎÑÅÔ ÐÏÓÌÅÄÎÅÅ ÒÁÓÛÉÒÅÎÉÅ ÎÁ ÕËÁÚÁÎÎÏÅ, ÉÌÉ ÄÏÂÁ×ÌÑÅÔ ÜÔÏ ÒÁÓÛÉÒÅÎÉÅ, +ÅÓÌÉ ÉÍÑ ÆÁÊÌÁ ÎÅ ÓÏÄÅÒÖÁÌÏ ÔÏÞËÉ. + +\function{char *last\_ext(const char *name);} +\index{last_ext} + ÷ÏÚ×ÒÁÝÁÅÔ ÐÏÓÌÅÄÎÅÅ ÒÁÓÛÉÒÅÎÉÅ ÆÁÊÌÁ ÉÌÉ {\tt NULL}, ÅÓÌÉ Õ ÆÁÊÌÁ +ÎÅÔ ÒÁÓÛÉÒÅÎÉÑ. + +÷ÓÅ ÜÔÉ ÔÒÉ ÆÕÎËÃÉÉ ×ÏÚ×ÒÁÝÁÀÔ ÕËÁÚÁÔÅÌØ ÎÁ ÓÔÁÔÉÞÅÓËÉÊ ÂÕÆÅÒ, +ËÏÔÏÒÙÊ ÂÕÄÅÔ ÐÅÒÅÚÁÐÉÓÁÎ ÐÒÉ ÓÌÅÄÕÀÝÅÍ ÏÂÒÁÝÅÎÉÉ Ë ÎÉÍ. + +\function{FILE *lookup\_file(const~char~*name, const~char~*sufux, +const~char~*dir);} +\index{lookup_file} + +éÝÅÔ ÆÁÊÌ Ó ÕËÁÚÁÎÎÙÍÉ ÉÍÅÎÅÍ × ÔÅËÕÝÅÊ ÄÉÒÅËÔÏÒÉÉ, × ÅÅ ÐÏÄÄÉÒÅËÔÏÒÉÉ +{\tt dir}, ÅÓÌÉ ÔÁËÏ×ÁÑ ÉÍÅÅÔÓÑ É × ÐÏÄÄÉÒÅËÔÏÒÉÉ {\tt dir} +ÓÉÓÔÅÍÎÏÊ ÂÉÂÌÉÏÔÅÞÎÏÊ ÄÉÒÅËÔÏÒÉÉ {\tt /usr/local/lib/fgis}. + +÷ÏÚ×ÒÁÝÁÅÔ ÕËÁÚÁÔÅÌØ ÎÁ ÓÔÒÕËÔÕÒÕ {\tt FILE}. æÁÊÌ ÏÔËÒÙ×ÁÅÔÓÑ +ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ. + +æÕÎËÃÉÑ ÐÒÅÄÎÁÚÎÁÞÅÎÁ ÄÌÑ ÐÏÉÓËÁ ×ÓÐÏÍÏÇÁÔÅÌØÎÙÈ ÆÁÊÌÏ×, ÔÁËÉÈ ËÁË +ÐÁÌÉÔÒÙ É ÛÔÒÉÈÏ×ËÉ. + +\section{ðÒÏÇÒÅÓÓ-ÉÎÄÉËÁÔÏÒ} + +÷ ÂÉÂÌÉÏÔÅËÕ ÔÁËÖÅ ×ËÌÀÞÅÎÁ ÓÔÁÎÄÁÒÔÎÁÑ ÆÕÎËÃÉÑ ×Ù×ÏÄÁ ÓÏÏÂÝÅÎÉÑ +{\tt Processing row ... of ...}. + +\function{int show\_progress(int rowno,int seqno,int nrows);} +\index{show_progress}% +ïÎÁ ×Ù×ÏÄÉÔ ÜÔÏ ÓÁËÒÁÍÅÎÔÁÌØÎÏÅ ÓÏÏÂÝÅÎÉÅ ÎÁ {\tt stderr}. +ëÒÏÍÅ ÜÔÏÇÏ, ÄÁÎÎÁÑ ÆÕÎËÃÉÑ ÏÂÒÁÂÁÔÙ×ÁÅÔ {\tt SIGINT}, +ÐÏÜÔÏÍÕ ÐÒÅÒÙ×ÁÎÉÅ ÐÒÏÇÒÁÍÍÙ ÐÏ Ctrl-C ÐÒÉ×ÏÄÉÔ Ë ËÏÒÒÅËÔÎÏÍÕ +ÅÅ ÚÁ×ÅÒÛÅÎÉÀ. + +ïÎÁ ÉÍÅÅÔ ÁÎÁÌÏÇ + +\function{int show\_percent(int rowno,int seqno,int nrows);}\index{show_percent} +ËÏÔÏÒÙÊ ×Ù×ÏÄÉÔ ÓÏÏÂÝÅÎÉÅ ×ÉÄÁ {\tt 99.9\% completed}. +÷ ÏÔÌÉÞÉÅ ÏÔ {\tt show\_progress} ÜÔÁ ÆÕÎËÃÉÑ ÍÏÖÅÔ +ÉÓÐÏÌØÚÏ×ÁÔØÓÑ É ÄÌÑ dgt-ÆÁÊÌÏ×. ëÒÏÍÅ ÔÏÇÏ, ÎÁ ÂÏÌØÛÉÈ ÆÁÊÌÁÈ +ÏÎÁ ÎÅÓËÏÌØËÏ ÜËÏÎÏÍÉÔ ×ÒÅÍÑ, ÐÏÓËÏÌØËÕ ÐÙÔÁÅÔÓÑ ×ÙÚÙ×ÁÔØ +ÍÅÄÌÅÎÎÙÅ ÏÐÅÒÁÃÉÉ ××ÏÄÁ-×Ù×ÏÄÁ, ÔÏÌØËÏ ÅÓÌÉ ÅÓÔØ ÐÒÏÇÒÅÓÓ +ÐÏ ËÒÁÊÎÅÊ ÍÅÒÅ ÎÁ 0.1\%, ÞÔÏ ÍÏÖÅÔ ÓÏÓÔÁ×ÌÑÔØ ÄÏ 30 ÓÔÒÏË. + +÷ ÔÏ ÖÅ ×ÒÅÍÑ ÄÁÖÅ ÎÁ ÆÁÊÌÁÈ ÍÁËÓÉÍÁÌØÎÏÇÏ ÒÁÚÍÅÒÁ ÂÏÌØÛÁÑ +ÞÁÓÔØ ÏÐÅÒÁÃÉÊ ÂÕÄÅÔ ×ÙÐÏÌÎÑÔØÓÑ Ó ÔÁËÏÊ ÓËÏÒÏÓÔØÀ, ÞÔÏ ÚÁ +0.1\% ×ÒÅÍÅÎÉ ÒÁÂÏÔÙ ÐÏÌØÚÏ×ÁÔÅÌØ ÎÅ ÕÓÐÅÅÔ ÒÅÛÉÔØ, ÞÔÏ ÐÒÏÇÒÁÍÍÁ ÚÁ×ÉÓÌÁ. + + +ëÒÏÍÅ ÔÏÇÏ, ÓÕÝÅÓÔ×ÕÅÔ ÆÕÎËÃÉÑ +\function{int check\_int(int rowno,int seqno,int nrows);} +\index{check_int}% +ËÏÔÏÒÁÑ ÎÉÞÅÇÏ ÎÅ ×Ù×ÏÄÉÔ, Á ÔÏÌØËÏ ÐÒÏ×ÅÒÑÅÔ ÓÉÇÎÁÌ. +òÅËÏÍÅÎÄÕÅÔÓÑ ×ÓÅÇÄÁ ÉÍÅÔØ ×ÏÚÍÏÖÎÏÓÔØ ÉÓÐÏÌØÚÏ×ÁÔØ ÅÅ × ËÁÞÅÓÔ×Å +ÁÌØÔÅÒÎÁÔÉ×Ù {\tt show\_percent}, ÎÁÐÒÉÍÅÒ ÄÌÑ ÆÏÎÏ×ÏÇÏ ×ÙÐÏÌÎÅÎÉÑ. + +õÓÔÁÎÁ×ÌÉ×ÁÅÔÓÑ ÏÄÎÁ ÉÚ ÜÔÉÈ ÆÕÎËÃÉÊ Ó ÐÏÍÏÝØÀ ÆÕÎËÃÉÉ + +\function{void install\_progress\_indicator(int (*func)(int,int,int));}% +\index{install_progress_indicator} + +æÕÎËÃÉÑ + +\function{int clear\_progress(int result);}\index{clear_progress} +óÔÉÒÁÅÔ ÓÏÏÂÝÅÎÉÅ, ÓÄÅÌÁÎÎÏÅ ÆÕÎËÃÉÅÊ~--- ÐÒÏÇÒÅÓÓ-ÉÎÄÉËÁÔÏÒÏÍ É ×Ù×ÏÄÉÔ +ÓÏÏÂÝÅÎÉÅ {\tt Done}, ÅÓÌÉ {\tt result = 0} ÉÌÉ {\tt Aborted}. + +÷ÏÚ×ÒÁÝÁÅÔ {\tt result}, ÐÏÜÔÏÍÕ ÌÏÇÉÞÎÙÊ ÓÐÏÓÏ ÅÅ ÐÒÉÍÅÎÅÎÉÑ +ÔÁËÏÊ: + +\begin{verbatim} +install_progress_indicator(show_percent); +if ((res=clear_progress(for_each_cell + (infile,my_iterator_func)))) + unlink(out_file_name); +close_epp(infile); +close_epp(outfile); +return res; +\end{verbatim} + +\chapter{÷ÎÕÔÒÅÎÎÅÅ ÕÓÔÒÏÊÓÔ×Ï ÂÉÂÌÉÏÔÅËÉ} +\section{õÓÔÒÏÊÓÔ×Ï ÒÁÓÔÒÏ×ÏÇÏ ÆÁÊÌÁ EPPL7} +\section{òÁÂÏÔÁ ÏÂßÅËÔÁ EPP} +\label{EPP-internals} +\section{÷ÅËÔÏÒÎÙÅ ÏÂßÅËÔÙ} +\section{÷ÅËÔÏÒÎÙÅ ÆÁÊÌÙ × ÐÁÍÑÔÉ} +\catcode`\_=11 +\input lib_doc.ind +\end{document} + + diff --git a/doc/lib_doc.toc b/doc/lib_doc.toc new file mode 100644 index 0000000..c966faa --- /dev/null +++ b/doc/lib_doc.toc @@ -0,0 +1,33 @@ +\select@language {russian} +\contentsline {chapter}{\IeC {\CYRV }\IeC {\cyrv }\IeC {\cyre }\IeC {\cyrd }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyri }\IeC {\cyre }}{3} +\contentsline {chapter}{\numberline {1}\IeC {\CYRL }\IeC {\cyro }\IeC {\cyrg }\IeC {\cyri }\IeC {\cyrch }\IeC {\cyre }\IeC {\cyrs }\IeC {\cyrk }\IeC {\cyra }\IeC {\cyrya } \IeC {\cyrm }\IeC {\cyro }\IeC {\cyrd }\IeC {\cyre }\IeC {\cyrl }\IeC {\cyrsftsn } \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyro }\IeC {\cyrv } \IeC {\cyrd }\IeC {\cyra }\IeC {\cyrn }\IeC {\cyrn }\IeC {\cyrery }\IeC {\cyrh }}{4} +\contentsline {section}{\numberline {1.1}\IeC {\CYRR }\IeC {\cyra }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrr }}{4} +\contentsline {section}{\numberline {1.2}\IeC {\CYRV }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrt }\IeC {\cyro }\IeC {\cyrr }}{5} +\contentsline {chapter}{\numberline {2}\IeC {\CYRF }\IeC {\cyru }\IeC {\cyrn }\IeC {\cyrk }\IeC {\cyrc }\IeC {\cyri }\IeC {\cyri } \IeC {\cyrd }\IeC {\cyro }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyru }\IeC {\cyrp }\IeC {\cyra } \IeC {\cyrk } epp \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyra }\IeC {\cyrm }}{7} +\contentsline {section}{\numberline {2.1}\IeC {\CYRP }\IeC {\cyro }\IeC {\cyrl }\IeC {\cyrya } \IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyru }\IeC {\cyrk }\IeC {\cyrt }\IeC {\cyru }\IeC {\cyrr }\IeC {\cyrery } EPP}{7} +\contentsline {section}{\numberline {2.2}\IeC {\CYRO }\IeC {\cyrt }\IeC {\cyrk }\IeC {\cyrr }\IeC {\cyrery }\IeC {\cyrt }\IeC {\cyri }\IeC {\cyre } \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyra } \IeC {\cyri } \IeC {\cyrr }\IeC {\cyre }\IeC {\cyrzh }\IeC {\cyri }\IeC {\cyrm }\IeC {\cyrery } \IeC {\cyrd }\IeC {\cyro }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyru }\IeC {\cyrp }\IeC {\cyra }}{8} +\contentsline {section}{\numberline {2.3}\IeC {\CYRI }\IeC {\cyrz }\IeC {\cyrm }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyri }\IeC {\cyre } \IeC {\cyrr }\IeC {\cyre }\IeC {\cyrzh }\IeC {\cyri }\IeC {\cyrm }\IeC {\cyro }\IeC {\cyrv } \IeC {\cyrd }\IeC {\cyro }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyru }\IeC {\cyrp }\IeC {\cyra }}{8} +\contentsline {section}{\numberline {2.4}\IeC {\CYRD }\IeC {\cyro }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyru }\IeC {\cyrp } \IeC {\cyrk } \IeC {\cyrya }\IeC {\cyrch }\IeC {\cyre }\IeC {\cyrishrt }\IeC {\cyrk }\IeC {\cyra }\IeC {\cyrm } \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyra }}{9} +\contentsline {section}{\numberline {2.5}\IeC {\CYRI }\IeC {\cyrt }\IeC {\cyre }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrt }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyrery }}{10} +\contentsline {section}{\numberline {2.6}\IeC {\CYRR }\IeC {\cyra }\IeC {\cyrb }\IeC {\cyro }\IeC {\cyrt }\IeC {\cyra } \IeC {\cyrs } \IeC {\cyrz }\IeC {\cyra }\IeC {\cyrg }\IeC {\cyro }\IeC {\cyrl }\IeC {\cyro }\IeC {\cyrv }\IeC {\cyrk }\IeC {\cyro }\IeC {\cyrm } epp-\IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyra }}{11} +\contentsline {section}{\numberline {2.7}\IeC {\CYRP }\IeC {\cyre }\IeC {\cyrr }\IeC {\cyre }\IeC {\cyrs }\IeC {\cyrch }\IeC {\cyre }\IeC {\cyrt } \IeC {\cyrk }\IeC {\cyro }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyrd }\IeC {\cyri }\IeC {\cyrn }\IeC {\cyra }\IeC {\cyrt }}{13} +\contentsline {section}{\numberline {2.8}\IeC {\CYRN }\IeC {\cyra }\IeC {\cyrl }\IeC {\cyro }\IeC {\cyrzh }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyri }\IeC {\cyre } \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyro }\IeC {\cyrv }}{13} +\contentsline {section}{\numberline {2.9}\IeC {\CYRP }\IeC {\cyrr }\IeC {\cyro }\IeC {\cyrch }\IeC {\cyre }\IeC {\cyre }}{14} +\contentsline {section}{\numberline {2.10}\IeC {\CYRO }\IeC {\cyrb }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrb }\IeC {\cyro }\IeC {\cyrt }\IeC {\cyrk }\IeC {\cyra } \IeC {\cyro }\IeC {\cyrsh }\IeC {\cyri }\IeC {\cyrb }\IeC {\cyro }\IeC {\cyrk }}{14} +\contentsline {chapter}{\numberline {3}\IeC {\CYRF }\IeC {\cyru }\IeC {\cyrn }\IeC {\cyrk }\IeC {\cyrc }\IeC {\cyri }\IeC {\cyri } \IeC {\cyrd }\IeC {\cyro }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyru }\IeC {\cyrp }\IeC {\cyra } \IeC {\cyrk } \IeC {\cyrv }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrt }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyrn }\IeC {\cyrery }\IeC {\cyrm } \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyra }\IeC {\cyrm }}{16} +\contentsline {section}{\numberline {3.1}T\IeC {\cyri }\IeC {\cyrp }\IeC {\cyrery } \IeC {\cyrd }\IeC {\cyra }\IeC {\cyrn }\IeC {\cyrn }\IeC {\cyrery }\IeC {\cyrh }}{16} +\contentsline {section}{\numberline {3.2}\IeC {\CYRO }\IeC {\cyrt }\IeC {\cyrk }\IeC {\cyrr }\IeC {\cyrery }\IeC {\cyrt }\IeC {\cyri }\IeC {\cyre } \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyra }}{17} +\contentsline {section}{\numberline {3.3}\IeC {\CYRS }\IeC {\cyrm }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyra } \IeC {\cyrr }\IeC {\cyre }\IeC {\cyrzh }\IeC {\cyri }\IeC {\cyrm }\IeC {\cyra } \IeC {\cyri } \IeC {\cyrz }\IeC {\cyra }\IeC {\cyrk }\IeC {\cyrr }\IeC {\cyrery }\IeC {\cyrt }\IeC {\cyri }\IeC {\cyre } \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyra }}{17} +\contentsline {section}{\numberline {3.4}\IeC {\CYRCH }\IeC {\cyrt }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyri }\IeC {\cyre } \IeC {\cyri } \IeC {\cyrz }\IeC {\cyra }\IeC {\cyrp }\IeC {\cyri }\IeC {\cyrs }\IeC {\cyrsftsn } \IeC {\cyro }\IeC {\cyrb }\IeC {\cyrhrdsn }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrt }\IeC {\cyro }\IeC {\cyrv }}{18} +\contentsline {section}{\numberline {3.5}\IeC {\CYRI }\IeC {\cyrt }\IeC {\cyre }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrt }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyrery }}{18} +\contentsline {section}{\numberline {3.6}\IeC {\CYRR }\IeC {\cyra }\IeC {\cyrb }\IeC {\cyro }\IeC {\cyrt }\IeC {\cyra } \IeC {\cyrs } \IeC {\cyrt }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyru }\IeC {\cyrshch }\IeC {\cyri }\IeC {\cyrm } \IeC {\cyro }\IeC {\cyrb }\IeC {\cyrhrdsn }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrt }\IeC {\cyro }\IeC {\cyrm }}{19} +\contentsline {section}{\numberline {3.7}DGT-\IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyrery } \IeC {\cyrv } \IeC {\cyrp }\IeC {\cyra }\IeC {\cyrm }\IeC {\cyrya }\IeC {\cyrt }\IeC {\cyri }}{21} +\contentsline {section}{\numberline {3.8}\IeC {\CYRR }\IeC {\cyra }\IeC {\cyrb }\IeC {\cyro }\IeC {\cyrt }\IeC {\cyra } \IeC {\cyrs } \IeC {\cyrk }\IeC {\cyro }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyrd }\IeC {\cyri }\IeC {\cyrn }\IeC {\cyra }\IeC {\cyrt }\IeC {\cyra }\IeC {\cyrm }\IeC {\cyri }}{21} +\contentsline {chapter}{\numberline {4}\IeC {\CYRF }\IeC {\cyru }\IeC {\cyrn }\IeC {\cyrk }\IeC {\cyrc }\IeC {\cyri }\IeC {\cyri }-\IeC {\cyru }\IeC {\cyrt }\IeC {\cyri }\IeC {\cyrl }\IeC {\cyri }\IeC {\cyrt }\IeC {\cyrery }}{23} +\contentsline {section}{\numberline {4.1}\IeC {\CYRO }\IeC {\cyrb }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrb }\IeC {\cyro }\IeC {\cyrt }\IeC {\cyrk }\IeC {\cyra } \IeC {\cyri }\IeC {\cyrm }\IeC {\cyre }\IeC {\cyrn } \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyro }\IeC {\cyrv }}{23} +\contentsline {section}{\numberline {4.2}\IeC {\CYRP }\IeC {\cyrr }\IeC {\cyro }\IeC {\cyrg }\IeC {\cyrr }\IeC {\cyre }\IeC {\cyrs }\IeC {\cyrs }-\IeC {\cyri }\IeC {\cyrn }\IeC {\cyrd }\IeC {\cyri }\IeC {\cyrk }\IeC {\cyra }\IeC {\cyrt }\IeC {\cyro }\IeC {\cyrr }}{24} +\contentsline {chapter}{\numberline {5}\IeC {\CYRV }\IeC {\cyrn }\IeC {\cyru }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyrn }\IeC {\cyre }\IeC {\cyre } \IeC {\cyru }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyro }\IeC {\cyrishrt }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrv }\IeC {\cyro } \IeC {\cyrb }\IeC {\cyri }\IeC {\cyrb }\IeC {\cyrl }\IeC {\cyri }\IeC {\cyro }\IeC {\cyrt }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyri }}{25} +\contentsline {section}{\numberline {5.1}\IeC {\CYRU }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyro }\IeC {\cyrishrt }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrv }\IeC {\cyro } \IeC {\cyrr }\IeC {\cyra }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyro }\IeC {\cyrv }\IeC {\cyro }\IeC {\cyrg }\IeC {\cyro } \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyra } EPPL7}{25} +\contentsline {section}{\numberline {5.2}\IeC {\CYRR }\IeC {\cyra }\IeC {\cyrb }\IeC {\cyro }\IeC {\cyrt }\IeC {\cyra } \IeC {\cyro }\IeC {\cyrb }\IeC {\cyrhrdsn }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrt }\IeC {\cyra } EPP}{25} +\contentsline {section}{\numberline {5.3}\IeC {\CYRV }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrt }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyrn }\IeC {\cyrery }\IeC {\cyre } \IeC {\cyro }\IeC {\cyrb }\IeC {\cyrhrdsn }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrt }\IeC {\cyrery }}{25} +\contentsline {section}{\numberline {5.4}\IeC {\CYRV }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrt }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyrn }\IeC {\cyrery }\IeC {\cyre } \IeC {\cyrf }\IeC {\cyra }\IeC {\cyrishrt }\IeC {\cyrl }\IeC {\cyrery } \IeC {\cyrv } \IeC {\cyrp }\IeC {\cyra }\IeC {\cyrm }\IeC {\cyrya }\IeC {\cyrt }\IeC {\cyri }}{25} diff --git a/doc/object_concept b/doc/object_concept new file mode 100644 index 0000000..f7c444d --- /dev/null +++ b/doc/object_concept @@ -0,0 +1,218 @@ +îÅËÏÔÏÒÙÅ ÉÄÅÉ + +1. îÕÖÅÎ ÌÉ ÎÁÍ ÇÌÏÂÁÌØÎÙÊ ÍÁÓÓÉ× map_items? Y +îÅ ÐÒÏÝÅ ÌÉ ÄÌÑ ËÁÖÄÏÇÏ mapcanvas ÓÏÚÄÁ×ÁÔØ Ó×ÏÊ ÍÁÓÓÉ×? + +ôÏÇÄÁ ×ÚÁÉÍÏÄÅÊÓÔ×ÉÅ ÓÌÏÑ Ó canvas ÄÏÌÖÎÏ ÂÙÔØ Ä×ÕÈÓÔÏÒÏÎÎÉÍ. +canvas ÄÏÌÖÅÎ ÚÎÁÔØ ×ÓÅ Ó×ÏÉ ÓÌÏÉ, Á ÓÌÏÊ - ×ÓÅ canvas, × ËÏÔÏÒÙÈ ÏÎ ×ÉÄÅÎ +(ÎÅ ÏÂÑÚÁÔÅÌØÎÏ ÔÅ, × ËÏÔÏÒÙÈ ÏÎ lookable - ÄÌÑ ÜÔÏÇÏ ÄÏÓÔÁÔÏÞÎÏ ÚÎÁÔØ +ËÏÏÒÄÉÎÁÔÙ) + +äÌÑ ÔÏÇÏ, ÞÔÏÂÙ ÐÅÒÅÒÉÓÏ×ÁÔØ ÓÌÏÊ (image) ÍÙ ÄÏÌÖÎÙ ÚÎÁÔØ +1. raster +2. palette/symbols +3. border mode +(ÜÔÏ ÚÎÁÅÔ ÓÌÏÊ) + +4. Item ID (ÎÁÈÏÄÉÔÓÑ ÐÏ tag) + +éÔÁË: ÄÌÑ ËÁÖÄÏÇÏ ÓÌÏÑ ÓÕÝÅÓÔ×ÕÅÔ ÐÒÏÃÅÄÕÒÁ redraw_${layer}_${mode} +Ó ÐÁÒÁÍÅÔÒÏÍ canvas +ËÏÔÏÒÁÑ ÐÅÒÅÒÉÓÏ×Ù×ÁÅÔ ÓÌÏÊ + +ÄÌÑ ÒÁÓÔÒÁ ÏÎÁ ÄÏÌÖÎÁ ×ÙÇÌÑÄÅÔØ ËÁË +layer_title $canvas self +raster image $self(raster) $canvas [force_image $canvas self] -palette $self(palette) ?-border ?base?? + +ðÒÉ ÒÅËÏÎÆÉÇÕÒÉÒÏ×ÁÎÉ ÂÏÒÄÅÒÁ ÏÎÁ ÐÅÒÅÓÏÚÄÁÅÔÓÑ. åÓÌÉ ÖÅ ÓÄÅÌÁÔØ +ÏÐÃÉÀ border ×ÏÓÐÒÉÎÉÍÁÀÝÕ ÔÒÉ ÆÌÁÇÁ (yes, no, base) ÔÏ ÐÒÏÃÅÄÕÒÕ +ÐÅÒÅÓÏÚÄÁ×ÁÔØ ÎÅ ÎÁÄÏ. + +ÏÎÁ ÂÕÄÅÔ ×ÙÇÌÑÄÅÔØ ËÁË + +proc __raster_redraw_base {layer canvas} { +upvar #0 $layer self +if [set t [get_title $canvas $layer] { + $canvas itemconf $t -text $self(title) +} else { $canvas create text [expr [winfo width $canvas]/2] 0 -anchor n -text + $self(title) + } +raster image $self(raster) $canvas [force_image $canvas $layer] -palette $self(palette) -border $self(border) -mapmode $self(mapmode) +} + +ôÉÐÙ ÓÌÏÅ× + +I ÒÁÓÔÒÏ×ÙÅ + ËÌÁÓÓÉÆÉËÁÃÉÑ (ÌÅÇÅÎÄÁ ÐÒÉÍÅÎÑÅÔÓÑ Ë ÔÏÍÕ ÖÅ ÒÅËÌÁÓÓÕ, ÞÔÏ É ÐÁÌÉÔÒÁ. + ÌÅÇÅÎÄÁ ÐÒÅÄÓÔÁ×ÌÑÅÔ ÓÏÂÏÊ ÎÁÂÏÒ ÓÔÒÏË (ÏÂßÅËÔ ÌÅÇÅÎÄÙ ÉÌÉ + ËÏÍÁÎÄÕ)) + ËÁÒÔÏÇÒÁÍÍÁ (ÌÅÇÅÎÄÁ ÐÒÉÍÅÎÑÅÔÓÑ Ë ÂÁÚÏ×ÏÍÕ ÓÌÏÀ ÉÌÉ ÏÄÎÏÍÕ ÒÅËÌÁÓÓÕ, + Á ÐÁÌÉÔÒÁ Ë ÄÒÕÇÏÍÕ ÒÅËÌÁÓÓÕ, ÐÒÉÞÅÍ ÐÏÓÌÅÄÎÉÊ£ + ÍÅÎÑÅÔÓÑ ÄÉÎÁÍÉÞÅÓËÉ × ÚÁ×ÉÓÉÍÏÓÔÉ ÏÔ ÚÁÄÁÎÎÙÈ ÉÎÔÅÒ×ÁÌÏ× + ÌÅÇÅÎÄÁ ÐÒÅÄÓÔ×ÁÌÑÅÔ ÓÏÂÏÊ ×ÙÒÁÖÅÎÉÅ (Tcl cËÒÉÐÔ) + çÏÌÙÊ ÒÁÓÔÒ - ÐÁÌÉÔÒÁ default, ÌÅÇÅÎÄÙ ÎÅÔ. ÞÔÏÂÙ ÓÄÅÌÁÔØ ÉÚ ÜÔÏÇÏ ÏÓÍÙÓÌÅÎÎÙÊ ÓÌÏÊ, ×ÏÓÐÏÌØÚÕÊÔÅÓÔØ ËÏÍÁÎÄÏÊ new +II ôÜÇÉ + 1. ïÂÙÞÎÙÊ ÔÜÇ - ÎÁÂÏÒ ÓÔÒÏË + ÷ÏÚÍÏÖÎÏÓÔØ ÚÁÄÁÔØ ËÏÍÁÎÄÕ, ×ÏÚ×ÒÁÝÁÀÝÕÀ ÔÉÐ ÍÁÒËÅÒÁ É ÛÒÉÆÔ ÐÏ + ÓÔÒÏËÅ + 2. äÉÁÇÒÁÍÍÁ - ÎÁÂÏÒ ÓÐÉÓËÏ× ÞÉÓÅÌ + ËÏÍÁÎÄÁ ÄÌÑ ÏÔÒÉÓÏ×ËÉ +III ÷ÅËÔÏÒÎÙÅ ÓÌÏÉ + ?? + +CÕÂËÏÍÁÎÄÙ ÄÌÑ ÒÁÓÔÒÏ×ÏÇÏ ÓÌÏÑ + +1. source - ×ÏÚ×ÒÁÝÁÅÔ ÉÍÑ ÆÁÊÌÁ (×ÏÚÍÏÖÎÏ ÞÅÒÅÚ C-ÛÎÙÊ ËÏÄ) +2. show canvas ?mode? - ÄÅÌÁÅÔ ÓÌÏÊ ×ÉÄÉÍÙÍ × ÕËÁÚÁÎÎÏÍ canvas. mode ÐÏ + ÕÍÏÌÞÁÎÉÀ base +3. look canvas {add|remove} +4. configure +5. cget +6. value x y - ×ÏÚ×ÒÁÝÁÅÔ ÚÎÁÞÅÎÉÅ ÐÏ ËÏÏÒÄÉÎÁÔÁÍ +7. classvalue class - ×ÏÚ×ÒÁÝÁÅÔ ÚÎÁÞÅÎÉÅ ÐÏ ËÌÁÓÓÕ (ÄÌÑ ÒÅÁÌÉÚÁÃÉÉ count - + ÐÏÄÏÂÎÙÈ ÏÐÅÒÁÃÉÊ +8. legtext index - ×ÏÚ×ÒÁÝÁÅÔ ÔÅËÓÔ ÌÅÇÅÎÄÙ ÐÏ ÉÎÄÅËÓÕ × ÐÁÌÉÔÒÅ +9. leglist - ×ÏÚ×ÒÁÝÁÅÔ ÓÐÉÓÏË ÐÏÚÉÃÉÊ ÌÅÇÅÎÄÙ +11. color index - ÄÅÌÁÅÔ palette get +13. pattern index - ×ÏÚ×ÒÁÝÁÅÔ ÛÔÒÉÈÏ×ËÕ (ÎÅ ÚÎÁÀ ËÁË) +14. drawopaque canvas - ÐÅÒÅÒÉÓÏ×Ù×ÁÅÔ Ã×ÅÔÏÍ +15. drawtransparent canvas - ÐÅÒÅÒÉÓÏ×Ù×ÁÅÔ ÛÔÒÉÈÏ×ËÏÊ +16. info legend - ×ÏÚ×ÒÁÝÁÅÔ true, ÅÓÌÉ ÅÓÔØ ÞÅÇÏ ÒÉÓÏ×ÁÔØ × legbox + info lookable - ×ÏÚ×ÒÁÝÁÅÔ true, ÅÓÌÉ ÅÓÔØ ÞÅÇÏ ×Ù×ÏÄÉÔØ × ÔÏÞËÅ (Ô.Å ×ÓÅÇÄÁ) + info opaque - ×ÏÚ×ÒÁÝÁÅÔ true, ÅÓÌÉ ÒÁÓÔÒ ÍÏÖÅÔ ÂÙÔØ ×Ù×ÅÄÅÎ ËÁË ÂÁÚÏ×ÙÊ + ÓÌÏÊ, Ô.Å. ×ÓÅÇÄÁ +17 hide canvas - ÕÄÁÌÑÅÔ ÓÌÏÊ ÉÚ canvas +ïÐÃÉÉ configure +-reclass, -table - ÍÏÄÉÆÉÃÉÒÕÀÔ ÂÁÚÏ×ÙÊ reclass. +-legend - ÚÁÄÁÀÔ ÏÂßÅËÔ ÌÅÇÅÎÄÙ ËÏÎÆÌÉËÔÕÅÔ Ó values É intervals. + -legfile - ×ÅÒÓÉÑ ÜÔÏÊ ÏÐÃÉÉ, ËÏÔÏÒÁÑ ÐÏÌÕÞÁÅÔ ÉÍÑ ÆÁÊÌÁ ×ÍÅÓÔÏ + ÇÏÔÏ×ÏÇÏ ÏÂßÅËÔÁ õËÁÚÁÎÉÅ ÜÔÏÊ ÏÐÃÉÉ ÒÁ×ÎÏÚÎÁÞÎÏ ÐÒÉÚÎÁÎÉÀ ËÁÒÔÙ + ÓÌÏÅÍ ËÌÁÓÓÉÆÉËÁÃÉÉ + +-palette - ÚÁÄÁÅÔ ÏÂßÅËÔ ÐÁÌÉÔÒÙ +-palfile - ÇÒÕÚÉÔ ÆÁÊÌ + +-values - ÚÁÄÁÅÔ ÓËÒÉÐÔ ÄÌÑ ÐÅÒÅÓÞÅÔÁ ËÌÁÓÓÁ × ÚÎÁÞÅÎÉÅ. õËÁÚÁÎÉÅ ÜÔÏÊ + ÏÐÃÉÉ ÒÁ×ÎÏÓÉÌØÎÏ ÐÒÉÚÎÁÎÉÀ ÓÌÏÑ ËÁÒÔÏÇÒÁÍÍÏÊ + ÐÏ ÕÍÏÌÞÁÎÉÀ ÒÁ×ÎÏ set +-legendheader ÚÁÄÁÅÔ ÔÏ, ÞÔÏ ÂÕÄÅÔ ×ÏÚ×ÒÁÝÅÎÏ legend title É legend subtitle +-intervals - ÚÁÄÁÅÔ ÓÐÉÓÏË ×ÅÝÅÓÔ×ÅÎÎÙÈ ÞÉÓÅÌ ÏÇÒÁÎÉÞÉ×ÁÀÝÉÊ ×ÉÄÉÍÙÅ ÄÉÁÐÁÚÏÎÙ + ÚÎÁÞÅÎÉÊ. ðÒÉÍÅÎÑÅÔÓÑ Ë ÔÅËÕÝÅÍÕ values +-border {none yes base} - ËÁË ÒÉÓÏ×ÁÔØ ÇÒÁÎÉÃÙ +-bordercolor color + ðÏËÁ undefined +-ovrborder +-ovrcolor +-patterns +-symbols + +ëÏÍÁÎÄÙ ÄÌÑ ÓÌÏÑ tag +title +legend title +legend subtitle +1. source - ×ÏÚ×ÒÁÝÁÅÔ ÉÍÑ ÆÁÊÌÁ ? +2. show canvas ?mode? - ÄÅÌÁÅÔ ÓÌÏÊ ×ÉÄÉÍÙÍ × ÕËÁÚÁÎÎÏÍ canvas. + mode ÍÏÖÅÔ ÂÙÔØ ÔÏÌØËÏ overlay +3. look canvas {add|remove} +4. configure +5. cget +6. value x y - ×ÏÚ×ÒÁÝÁÅÔ ÚÎÁÞÅÎÉÅ ÐÏ ËÏÏÒÄÉÎÁÔÁÍ. ÍÏÖÅÔ É ÎÅ ×ÅÒÎÕÔØ +7. classvalue class - ÎÅ ÏÐÒÅÄÅÌÅÎÁ +8. legtext index - ÎÅ ÏÐÒÅÄÅÌÅÎÁ?? +9. leglist - ×ÏÚ×ÒÁÝÁÅÔ ÓÐÉÓÏË ÐÏÚÉÃÉÊ ÌÅÇÅÎÄÙ (ÓÐÉÓÏË ÍÁÒËÅÒÏ×?) +11. color index - ÎÅ ÏÐÒÅÄÅÌÅÎÁ +13. pattern index - ÎÅ ÏÐÒÅÄÅÌÅÎÁ +14. drawopaque canvas - ÎÅ ÏÐÒÅÄÅÌÅÎÁ +15. drawtransparent canvas - ÐÅÒÅÒÉÓÏ×Ù×ÁÅÔ +16. info legend - ×ÏÚ×ÒÁÝÁÅÔ true, ÅÓÌÉ ÅÓÔØ ÞÅÇÏ ÒÉÓÏ×ÁÔØ × legbox + info lookable - ×ÏÚ×ÒÁÝÁÅÔ true, ÅÓÌÉ ÅÓÔØ ÞÅÇÏ ×Ù×ÏÄÉÔØ × ÔÏÞËÅ + info opaque - ×ÏÚ×ÒÁÝÁÅÔ true, ÅÓÌÉ ÒÁÓÔÒ ÍÏÖÅÔ ÂÙÔØ ×Ù×ÅÄÅÎ ËÁË ÂÁÚÏ×ÙÊ + ÓÌÏÊ, Ô.Å. ÎÉËÏÇÄÁ +17 marker ÓÔÒÏËÁ - ×ÏÚ×ÒÁÝÁÅÔ ÉÍÑ ÍÁÒËÅÒÁ ÄÌÑ ÓÔÒÏËÉ +18 font ÓÔÒÏËÁ - ×ÏÚ×ÒÁÝÁÅÔ ÉÍÑ ÓÌÏÑ ÄÌÑ ÓÔÒÏËÉ + +ÍÁÒËÅÒ ÒÉÓÕÅÔÓÑ ËÏÍÍÁÎÄÏÊ +set offset [eval $marker $canvas $x $y] +offset - ÐÒÉÎÉÍÁÅÔ ÚÎÁÞÅÎÉÅ ÄÉÓÔÁÎÃÉÉ × ÐÉËÓÅÌÁÈ, ÎÁ ËÏÔÏÒÕÀ ÎÁÄÏ ÓÍÅÓÔÉÔØ + ÎÁÞÁÌØÎÕÀ ÔÏÞËÕ ÔÅËÓÔÁ. + + planchet widget + +îÁ ÓÁÍÏÍ ÄÅÌÅ ÜÔÏ canvas ÓÏ ×ÓÅÍÉ Ó×ÏÉÍÉ ËÁÎ×ÁÓÎÙÍÉ Ó×ÏÊÓÔ×ÁÍÉ. +îÏ Ó ÎÉÍ ÁÓÓÏÃÉÉÒÏ×ÁÎ ÍÁÓÓÉ× (ÓÏ×ÐÁÄÁÀÝÉÊ ÐÏ ÉÍÅÎÉ) +× ËÏÔÏÒÏÍ ÈÒÁÎÉÔÓÑ ÄÏÐÏÌÎÉÔÅÌØÎÁÑ ÉÎÆÏÒÍÁÃÉÑ +1. limits - ÔÅËÕÝÉÅ ÐÒÅÄÅÌÙ ËÏÏÒÄÉÎÁÔ. åÖÅÌÉ ÏÔÓÕÔÓÔ×ÕÅÔ, ÔÏ ÍÎÏÇÉÅ +ËÏÍÁÎÄÙ ÂÕÄÕÔ ×ÏÚ×ÒÁÝÁÔØ ÏÛÉÂËÕ. +2. zoom - ÔÅËÕÝÉÊ ÓÔÅË Õ×ÅÌÉÞÅÎÉÊ +÷ÓÐÏÍÏÇÁÔÅÌØÎÙÅ ×ÉÄÇÅÔÙ +3. bzoom - ËÎÏÐËÁ Õ×ÅÌÉÞÅÎÉÑ + bunzoom - ÓÐÉÓÏË ËÎÏÐÏË ÕÍÅÎØÛÅÎÉÑ + shifts - ÓÐÉÓÏË ËÎÏÐÏË ÓÄ×ÉÇÁ left down up right + scalelabel - ÍÅÓÔÏ ÇÄÅ ÏÔÏÂÒÁÖÁÅÔÓÑ ÍÁÓÛÔÁ +óÌÏÉ base + overlays - ÓÐÉÓÏË + looks - ÓÐÉÓÏË + +îÏ×ÙÅ ÏÐÃÉÉ × widget command +$w limits ?ÞÅÔÙÒÅ ËÏÏÒÄÉÎÁÔÙ? - ÕÓÔÁÎÁ×ÌÉ×ÁÅÔ ÎÏ×ÙÅ ÐÒÅÄÅÌÙ. åÓÌÉ + ËÏÏÒÄÉÎÁÔÙ ÂÙÌÉ ÎÅ ÏÐÒÅÄÅÌÅÎÙ, ÔÏ ÐÏÒÑÄÏË ÓÞÉÔÁÅÔÓÑ + ÌÅ×Ï ÎÉÚ ÐÒÁ×Ï ×ÅÒÈ, ÉÎÁÞÅ ÎÁÐÒÁ×ÌÅÎÉÅ ÏÓÅÊ ÓÏÈÒÁÎÑÅÔÓÑ. +limits ÂÅÚ ÁÒÇÕÍÅÎÔÏ× ×ÏÚ×ÒÁÝÁÅÔ ÔÅËÕÝÉÅ ÁÒÇÕÍÅÎÔÙ +$w clear - ÏÞÉÝÁÅÔ ×ÓÅ (ÄÌÑ ÓÍÅÎÙ ÒÅÇÉÏÎÁ) +$w zoom - ÐÏÞÔÉ ÔÏ ÖÅ ÓÁÍÏÅ, ÞÔÏ É limits, ÎÏ ÐÏÌÕÞÁÅÔ ËÏÏÒÄÉÎÁÔÙ + × ÅÄÉÎÉÃÁÈ canvas, Á ÎÅ × ÁÌØÔÅÒÎÁÎÉ×ÎÙÈ ÅÄÉÎÉÃÁÈ. óÍ. ÔÁËÖÅ + ÐÒÏÃÅÄÕÒÕ zoom +$w unzoom ?-all? - ÏÔÍÅÎÑÅÔ ÐÏÓÌÅÄÎÅÅ ÉÌÉ ×ÓÅ Õ×ÅÌÉÞÅÎÉÑ +$w shift ÎÁÐÒÁ×ÌÅÎÉÅ - ÓÄ×ÉÇÁÅÔ ÔÅËÕÝÅÅ ÐÏÌÅ ÚÒÅÎÉÑ × ÕËÁÚÁÎÎÏÍ ÎÁÐÒÁ×ÌÅÎÉÉ + +$w layers - ×ÏÚ×ÒÁÝÁÅÔ ÓÐÉÓÏË ×ÓÅÈ ÓÌÏÅ×, ×ËÌÀÞÁÑ ÂÁÚÏ×ÙÊ +$w lookable - ×ÏÚ×ÒÁÝÁÅÔ ÓÐÉÓÏË ×ÓÅ lookable ÓÌÏÅ×. +÷ÎÉÍÁÎÉÅ - ÐÏËÁÚÙ×ÁÀÔÓÑ É ÓËÒÙ×ÁÀÔÓÑ ÓÌÏÉ ËÏÍÁÎÄÁÍÉ ÓÌÏÑ Á ÎÅ ÐÌÁÎÛÅÔÁ +$w scale ?denominator? - ×ÏÚ×ÒÁÝÁÅÔ ÔÅËÕÝÉÊ ÚÎÁÍÅÎÁÔÅÌØ ÍÁÓÛÔÁÂÁ ÉÌÉ + ÕÓÔÁÎÁ×ÌÉ×ÁÅÔ ÍÁÓÛÔÁÂ. ãÅÎÔÒÁÌØÎÁÑ ÔÏÞËÁ ÐÒÉ ÜÔÏÍ + ÏÓÔÁÅÔÓÑ ÎÅÉÚÍÅÎÎÏÊ, +$w ruler {on|off} - ×ËÌÀÞÁÅÔ/×ÙËÌÀÞÁÅÔ ÍÁÓÛÔÁÂÎÕÀ ÌÉÎÅÊËÕ + +$W MApx x +$w mapy y +$w scrx x +$w scry y +$w look x y - ×ÏÚ×ÒÁÝÁÅÔ ÓÐÉÓÏË ÓÌÏÅ× É ÉÈ ÚÎÁÞÅÎÉÊ × ÔÅËÕÝÅÊ ÔÏÞËÅ +$w statustext ÔÅËÓÔ - ×Ù×ÏÄÉÔ ÔÅËÓÔ × ÏËÏÛËÅ ÓÔÁÔÕÓÁ +$w projection type ?options? +- ÚÁÄÁÅÔ ÐÒÏÅËÃÉÀ +$w longitide x y +$w latitide x y +$w fit x y +1, ÅÓÌÉ ÔÏÞËÁ ÐÏÐÁÄÁÅÔ × canvas É 0 ÅÓÌÉ ÎÅÔ +îÏ×ÙÅ ÏÐÃÉÉ configure/cget +1. -legbox +2. -zoombutton +3. -unzoombuttons +4. -shiftbuttons +5. -statusline +6. -rulerpos - ÐÏÚÉÃÉÑ ÎÁÞÁÌÁ ÍÁÓÛÔÁÂÎÏÊ ÌÉÎÅÊËÉ + +îÅÄÏÓÔÕÐÎÙÅ ÏÐÃÉÉ canvas +-borderwidth -bd -highlightthickness -relief + +BINDINGS + - ÐÅÒÅÈ×ÁÔ resize É ÓÏÏÔ×ÅÔÓ×ÔÕÀÝÅÅ ÉÚÍÅÎÅÎÉÅ ÐÒÅÄÅÌÏ× ËÏÏÒÄÉÎÁÔ + - ÔÝÁÔÅÌØÎÏ ÚÁÍÅÔÁÅÔ ×ÓÅ ÓÌÅÄÙ ÔÏÇÏ, ÞÔÏ ÜÔÏ ÎÅ ÎÁÓÔÏÑÝÉÊ + widget, Õ×ÅÄÏÍÌÑÅÔ ×ÓÅ ÓÌÏÉ Ï ÔÏÍ, ÞÔÏ × ÜÔÏÍ ÐÌÁÎÛÅÔÅ ÏÎÉ ÂÏÌØÛÅ + ÎÅ ×ÉÄÎÙ. + - ÌÕËÏÛËÏ Ó ÏËÏÍ (ÏËÏÛËÏ Ó ÌÕËÏÍ) + zoom %W %x %y +(Á binding ÚÁÐÏÍÉÎÁÅÔÓÑ × ÐÒÉ×ÁÔÎÙÈ ÄÁÎÎÙÈ ÐÌÁÎÛÅÔÁ) + - ÅÓÌÉ ÏÐÒÅÄÅÌÅÎ ÓÔÁÔÕÓ, ÏÔÏÂÒÁÖÁÅÔ ËÏÏÒÄÉÎÁÔÙ + +ðÒÏÞÉÅ ÏÂßÅËÔÙ +ðÒÏÅËÃÉÑ - ÜÔÏ ÔÏÖÅ ÏÂßÅËÔ. ðÒÉÞÅÍ ÎÁÐÉÓÁÎÎÙÊ ÞÅÓÔÎÏ ÎÁ C. + +ðÒÏÞÉÅ ËÏÍÁÎÄÙ + +zoom - ÂÙ×ÛÉÊ mapzoom +print - ÂÙ×ÛÉÊ mapprint + +÷ÓÅ ËÏÍÁÎÄÙ, ËÏÔÏÒÙÅ ÒÁÂÏÔÁÀÔ Ó ËÏÏÒÄÉÎÁÔÁÍÉ, ÐÅÒÅÉÍÅÎÏ×Ù×ÁÀÔÓÑ +× __planchet_mapx + __planchet_mapy É Ô.Ä. diff --git a/doc/region.concept b/doc/region.concept new file mode 100644 index 0000000..ce411c6 --- /dev/null +++ b/doc/region.concept @@ -0,0 +1,31 @@ + ëÏÎÃÅÐÃÉÑ ÒÅÇÉÏÎÁ. + +÷ ÏÂÌÁÓÔÉ çéó-ÏÂÒÁÂÏÔËÉ ÐÒÁËÔÉÞÅÓËÉ ÎÉËÏÇÄÁ ÎÅÌØÚÑ ÏÇÒÁÎÉÞÉÔØÓÑ +ÒÁÓÓÍÏÔÒÅÎÉÅÍ ÏÄÎÏÊ ËÁÒÔÙ ÎÁ ÏÐÒÅÄÅÌÅÎÎÕÀ ÔÅÒÒÉÔÏÒÉÀ, ÏÓÏÂÅÎÎÏ +ÐÒÉ ÉÓÐÏÌØÚÏ×ÁÎÉÉ ËÏÎÃÅÐÃÉÉ ÆÕÎËÃÉÏÎÁÌØÎÙÈ ËÁÒÔ. + +ëÒÏÍÅ ÔÏÇÏ, ÄÏÓÔÁÔÏÞÎÏ ÞÁÓÔÏ ×ÏÚÎÉËÁÅÔ ÚÁÄÁÞÁ ÒÁÂÏÔÙ Ó ÎÅÓËÏÌØËÉÍÉ +ÒÁÚÎÏÍÁÓÛÔÁÂÎÙÍÉ ÕÞÁÓÔËÁÍÉ ÔÅÒÒÉÔÏÒÉÉ. + +ðÏÜÔÏÍÕ × fGIS ××ÅÄÅÎÁ ËÏÎÃÅÐÃÉÑ ÒÅÇÉÏÎÁ. òÅÇÉÏÎ ÜÔÏ ÇÒÕÐÐÁ ËÁÒÔ, +ÏÐÉÓÙ×ÁÀÝÉÈ ÏÄÎÕ É ÔÕ ÖÅ ÔÅÒÒÉÔÏÒÉÀ. ÷ÓÅ ËÁÒÔÙ ÒÅÇÉÏÎÁ ÄÏÌÖÎÙ +ÉÍÅÔØ ÏÄÉÎÁËÏ×ÕÀ ËÏÏÒÄÉÎÁÔÎÕÀ ÓÉÓÔÅÍÕ (ÐÒÏÅËÃÉÀ), ÈÏÔÑ ÎÉËÔÏ ÎÅ +ÍÅÛÁÅÔ ÓÏÚÄÁÔØ ÎÅÓËÏÌØËÏ ÒÅÇÉÏÎÏ× fGIS, ÉÍÅÀÝÉÈ ÒÁÚÎÕÀ ÐÒÏÅËÃÉÀ, +ÄÌÑ ÏÄÎÏÊ É ÔÏÊ ÖÅ ÔÅÒÒÉÔÏÒÉÉ. + +ëÏÐÉÒÏ×ÁÎÉÅ ËÁÒÔÙ ÉÚ ÏÄÎÏÇÏ ÒÅÇÉÏÎÁ × ÄÒÕÇÏÊ (ÅÓÔÅÓÔ×ÅÎÎÏ, ÓÒÅÄÓÔ×ÁÍÉ +fGIS, Á ÎÅ ÓÒÅÄÓÔ×ÁÍÉ ÏÐÅÒÁÃÉÏÎÎÏÊ ÓÉÓÔÅÍÙ) ÐÒÉ×ÏÄÉÔ Ë Á×ÔÏÍÁÔÉÞÅÓËÏÍÕ +ÉÚÍÅÎÅÎÉÀ ÐÒÏÅËÃÉÉ. + +òÅÇÉÏÎÙ ÍÏÇÕÔ ÂÙÔØ ÉÅÒÁÒÈÉÞÅÓËÉ ×ÌÏÖÅÎÙ ÄÒÕÇ × ÄÒÕÇÁ. ðÏÜÔÏÍÕ ÅÝÅ ÏÄÎÉÍ +Ó×ÏÊÓÔ×ÏÍ ÒÅÇÉÏÎÁ Ñ×ÌÑÅÔÓÑ ËÁÒÔÁ ÅÇÏ ÒÁÚÂÉÅÎÉÑ ÎÁ ÓÕÂÒÅÇÉÏÎÙ. +ó ÅÅ ÐÏÍÏÝØÀ ÍÏÖÎÏ ÐÅÒÅÊÔÉ × ÒÅÇÉÏÎ, ÄÁÀÝÉÊ ÂÏÌÅÅ ÄÅÔÁÌØÎÕÀ ÈÁÒÁËÔÅÒÉÓÔÉËÕ +ÐÒÏÓÔÏ ÐÕÔÅÍ ×ÙÂÏÒÁ ÔÏÞËÉ ÎÁ ËÁÒÔÅ. + +÷ÎÕÔÒÉ ÒÅÇÉÏÎÁ ËÁÒÔÙ ÍÏÇÕÔ ÂÙÔØ ÏÂßÅÄÉÎÅÎÙ × ÔÅÍÁÔÉÞÅÓËÉÅ ÇÒÕÐÐÙ, +ÞÔÏ ÏÂÌÅÇÞÁÅÔ ÎÁ×ÉÇÁÃÉÀ ÐÏ ÎÉÍ. + +òÅÇÉÏÎÕ ÓÏÏÔ×ÅÔÓÔ×ÕÅÔ ËÁÔÁÌÏÇ ÆÁÊÌÏ×ÏÊ ÓÉÓÔÅÍÙ OS, Á ÓÕÂÒÅÇÉÏÎÁÍ - +ÐÏÄËÁÔÁÌÏÇÉ ÄÁÎÎÏÇÏ ËÁÔÁÌÏÇÁ. ðÏÜÔÏÍÕ ÐÅÒÅÈÏÄ × ×ÙÛÅÌÅÖÁÝÉÊ ÒÅÇÉÏÎ +×ÓÅÇÄÁ ÏÐÒÅÄÅÌÅÎ ÏÄÎÏÚÎÁÞÎÏ. + diff --git a/doc/visualisagion.concept b/doc/visualisagion.concept new file mode 100644 index 0000000..0bcea71 --- /dev/null +++ b/doc/visualisagion.concept @@ -0,0 +1,18 @@ +ðÒÉÎÃÉÐÙ ×ÉÚÕÁÌÉÚÁÃÉÉ fGIS + +ïÄÎÉÍ ÉÚ ÏÓÎÏ×ÎÙÈ ÎÅÄÏÓÔÁÔËÏ× ÔÒÁÄÉÃÉÏÎÎÙÈ GIS (ARC/Info, Idrisi, EPPL7) +Ñ×ÌÑÅÔÓÑ ÒÁÚÄÅÌÅÎÉÅ ÓÏÂÓÔ×ÅÎÎÏ ÜÌÅËÔÒÏÎÎÙÈ ËÁÒÔ (ÐÏËÒÙÔÉÊ) É ËÁÒÔÏÇÒÁÆÉÞÅÓËÉÈ +ËÏÍÐÏÚÉÃÉÊ, ÐÒÅÄÎÁÚÎÁÞÅÎÎÙÈ ÄÌÑ ÐÒÏÓÍÏÔÒÁ É ÐÅÞÁÔÉ. + +÷ ÜÔÏÍ ÐÏÄÈÏÄÅ ÅÓÔØ Ó×ÏÉ ÐÒÅÉÍÕÝÅÓÔ×Á --- ÐÅÒÅÈÏÄ ÏÔ ËÏÒÒÅËÔÎÏ ÐÏÓÔÒÏÅÎÎÏÊ +ÍÏÄÅÌÉ ÍÅÓÔÎÏÓÔÉ, ËÁËÏ×ÏÊ Ñ×ÌÑÅÔÓÑ ÐÏËÒÙÔÉÅ, Ë ÐÒÏÉÚ×ÅÄÅÎÉÀ ÐÏÌÉÇÒÁÆÉÞÅÓËÏÇÏ +ÉÓËÕÓÓÔ×Á, ËÁËÏ×ÙÍ Ñ×ÌÑÅÔÓÑ ÂÕÍÁÖÎÁÑ ËÁÒÔÁ, ÚÁÄÁÞÁ ÎÅÐÒÏÓÔÁÑ É, ÎÅÓÏÍÎÅÎÎÏ, +ÔÒÅÂÕÀÝÁÑ ÕÞÁÓÔÉÑ ÞÅÌÏ×ÅËÁ. ôÅÍ ÎÅ ÍÅÎÅÅ ÄÌÑ ÂÏÌØÛÉÎÓÔ×Á ÐÏÌØÚÏ×ÁÔÅÌÅÊ +çéó, Ñ×ÌÑÀÝÉÍÉÈÓÑ ÓÐÅÃÉÁÌÉÓÔÁÍÉ × ÐÒÅÄÍÅÔÎÏÊ ÏÂÌÁÓÔÉ, Á ÎÅ ÐÒÏÆÅÓÓÉÏÎÁÌØÎÙÍÉ +ËÁÒÔÏÇÒÁÆÁÍÉ, ÎÅ×ÏÚÍÏÖÎÏÓÔØ ÍÇÎÏ×ÅÎÎÏ Õ×ÉÄÅÔØ ÒÅÚÕÌØÔÁÔ ÐÒÉÍÅÎÅÎÉÑ ÔÏÊ ÉÌÉ +ÉÎÏÊ ÏÐÅÒÁÃÉÉ, Ñ×ÌÑÅÔÓÑ ÓÕÝÅÓÔ×ÅÎÎÏÊ ÐÏÍÅÈÏÊ ÐÒÉ ÐÏÓÔÒÏÅÎÉÉ çéó ÍÏÄÅÌÅÊ. + +ðÏÜÔÏÍÕ × fGIS ÐÁÒÁÍÅÔÒÙ ×ÉÚÕÁÌÉÚÁÃÉÉ, ÔÁËÉÅ ËÁË ÐÁÌÉÔÒÁ, ÛÔÒÉÈÏ×ËÉ ÉÌÉ +ÎÁÂÏÒ ÓÌÏÅ×-ÏÒÉÅÎÔÉÒÏ×, ÏÂÌÅÇÞÁÀÝÉÈ ÞÔÅÎÉÅ ÏÓÎÏ×ÎÏÊ ÔÅÍÁÔÉÞÅÓËÏÊ ÉÎÆÏÒÍÁÃÉÉ, +Ñ×ÌÑÅÔÓÑ ÁÔÒÉÂÕÔÁÍÉ ËÁÒÔÙ É ËÁÖÄÁÑ ËÁÒÔÁ ÍÏÖÅÔ ÂÙÔØ ×ÉÚÕÁÌÉÚÉÒÏ×ÁÎÁ ÉÌÉ +ÎÁÐÅÞÁÔÁÎÁ ÐÒÏÓÔÏ ÐÕÔÅÍ ÕËÁÚÁÎÉÑ ÅÅ ÉÍÅÎÉ. diff --git a/epu/Makefile b/epu/Makefile new file mode 100644 index 0000000..d33ab0e --- /dev/null +++ b/epu/Makefile @@ -0,0 +1,42 @@ +CC=gcc +CFLAGS=-g -Wall -pedantic -O2 -I../lib/gnu_lib -I../include +LDFLAGS=-L../lib +LOADLIBES=-lm -lepp +SRC=\ +RCS/border.c,v\ +RCS/cluster.c,v\ +RCS/dgt2gen.c,v\ +RCS/eheader.c,v\ +RCS/extents.c,v\ +RCS/fill.c,v\ +RCS/intable.c,v\ +RCS/mosaic.c,v\ +RCS/neighbours.c,v\ +RCS/outtab.c,v\ +RCS/reclass1.c,v\ +RCS/window.c,v +ALL=\ +border\ +cluster\ +dgt2gen\ +eheader\ +extents\ +fill\ +intable\ +mosaic\ +neighbours\ +outtable\ +reclass1\ +centers\ +project\ +window +RCS/%,v : % + ci $< +% : %.o + ${CC} $< -o $@ ${LDFLAGS} ${LOADLIBES} +all: ${ALL} +rcs: ${SRC} +project: project.o + ${CC} $< -o $@ ${CFLAGS} ${LDFLAGS} -lproj ${LOADLIBES} +outtable: outtable.o outtable_func.o + gcc outtable.o outtable_func.o ${LDFLAGS} ${LOADLIBES} -o outtable diff --git a/epu/bil2epp b/epu/bil2epp new file mode 100755 index 0000000000000000000000000000000000000000..3e00b1346611faaf7bef930f1cd26ecf3741b367 GIT binary patch literal 60478 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 L8hM`W%!>a3TY+zA literal 0 HcmV?d00001 diff --git a/epu/bil2epp.c b/epu/bil2epp.c new file mode 100644 index 0000000..7e38cde --- /dev/null +++ b/epu/bil2epp.c @@ -0,0 +1,137 @@ +#define __USE_GNU +#define __USE_XOPEN +#include +#include +#include +#include +#include +#include +#include +void error(const char * message) +{ + fprintf(stderr,"%s\n",message); + exit(1); +} +void swab(const void *from,void *to,size_t size); +void dcopy(const void *from,void *to,size_t size) +{ + memcpy(to,from,size); +} + +int convert(EPP *epp,FILE *in,void (*copyrow)(const void *,void*,size_t), + int shift) +{ + int bytes=(epp->lc-epp->fc)*2,row,col,i,rows=epp->lr-epp->fr; + short int *buf,*buf2,*p; + buf=malloc(bytes); + buf2=malloc(bytes); + for (row=epp->fr,i=1;rowlr;row++,i++) { + fread(buf,bytes,1,in); + copyrow(buf,buf2,bytes); + for (col=epp->fc,p=buf2;collc;col++,p++) { + epp_put(epp,col,row,(unsigned short)(*p+shift)); + if (EndLineProc) + if (EndLineProc(row,i,rows)) return -1; + } + } + return 0; +} + +EPP *read_header(char *filename,int *swapbytes,int shift) +{ char buf[1024],*p; + int rows=0,cols=0,nodata=32768; + FILE *f=fopen(filename,"r"); + double X1=0,Y1=0,X2=0,Y2=0,DX=0,DY=0; + while (!feof(f)) { + fgets(buf,1024,f); + p=strchr(buf,'\n'); + if (p) *p=0; + p=buf; + while(isalpha(*p)) p++; + *p=0;p++; + if (!strcmp(buf,"BYTEORDER")) { + while(isspace(*p)) p++; + *swapbytes=toupper(*p)=='M'; + } else if (!strcmp(buf,"NROWS")) { + rows=atol(p); + } else if (!strcmp(buf,"NCOLS")) { + cols=atol(p); + } else if (!strcmp(buf,"NBITS")) { + if (atol(p)!=16) { + fprintf(stderr,"Data size in %s is not 16 bit\n",filename); + return NULL; + } + } else if (!strcmp(buf,"NODATA")) { + nodata=atol(p)+shift; + if (nodata<0) nodata+=65536; + } else if (!strcmp(buf,"ULXMAP")) { + X1=strtod(p,NULL); + } else if (!strcmp(buf,"ULYMAP")) { + Y1=strtod(p,NULL); + } else if (!strcmp(buf,"XDIM")) { + DX=strtod(p,NULL); + } else if (!strcmp(buf,"YDIM")) { + DY=strtod(p,NULL); + } + } + fclose(f); + X1-=DX/2; + Y1-=DY/2; + X2=X1+DX*cols; + Y2=Y1+DY*rows; + Create16bit=1; + return creat_epp(force_ext(filename,".epp"),1,1,cols, + rows,X1,Y1,X2,Y2,100,0,nodata); +} +int main(int argc, char **argv) +{ int shift=0; + char headersuffix[100]=".hdr",headername[1024]; + int i,c,verbose=0; + while ((c=getopt(argc,argv,"s:h:%"))!=EOF) { + switch (c) { + case 's': {char *erptr; + shift = strtol(optarg,&erptr,0); + if (!*erptr) { + error("Invalid shift value"); + } + break; + } + case 'h': strcpy(headersuffix, optarg); + break; + case '%': verbose=1; + break; + default: error("Invalid option.\n Usage bil2epp [-h header_suffix]" + " [-s shift_value] [-%] files\n"); + } + } + + install_progress_indicator(verbose?show_percent:check_int); + if (optind==argc) error("No files specified"); + + for (i=optind;i +#include +#include +#include "eppl_ut.h" +#include "epp.h" +#include "dgt.h" +#include +#ifndef __LINUX__ +#include +#endif +#define TRUE 1 +#define FALSE 0 +#define SEG_LEFT 1 +#define SEG_VERT 2 +#define SEG_RIGHT 4 +#define SEG_UP 8 +#define DELTA 16 +typedef struct U_POINT { + unsigned short x,y;} U_POINT; +typedef U_POINT *LINEBUF; +typedef struct INODE { + unsigned short int count; + short int both_ends; + unsigned short int limit; + int x_tail,x_head; + LINEBUF points; + } *LINE_INODE; +typedef struct LINE_END { LINE_INODE buf; + int tail; + } LINE_END; +/* ðÁÒÁÍÅÔÒÙ ËÏÎÆÉÇÕÒÁÃÉÉ */ +int offsite_option=1; +int tolerance=3; +/* ïÓÎÏ×ÎÙÅ ÒÁÂÏÞÉÅ ÓÔÒÕËÔÕÒÙ ÄÁÎÎÙÈ */ +LINE_END *lines; +unsigned short *rp1,*rp2; +EPP* source; +DGT* dest; +/* ïÓÎÏ×ÎÙÅ ÐÒÏÃÅÄÕÒÙ */ +int epp2dgtX(int col); +int epp2dgtY(int row); +void getrow(int row); +void add_segment(LINE_END line,int col,int row); +/* ÄÏÂÁ×ÌÑÅÔ ÓÅÇÍÅÎÔ × ÎÁÞÁÌÏ ÉÌÉ × ËÏÎÅÃ, × ÚÁ×ÉÓÉÍÏÓÔÉ ÏÔ + ÐÏÌÑ line->tail, ËÏÎÞÁÀÝÉÊÓÑ × ÔÏÞËÅ col,row */ +void put_line(LINE_INODE buf); +/* çÅÎÅÒÁÌÉÚÕÅÔ ÌÉÎÉÀ É ÚÁÐÉÓÙ×ÁÅÔ ÅÅ. ðÒÉ ÎÅÏÂÈÏÄÉÍÏÓÔÉ ÒÅÖÅÔ + ðÏ ÚÁ×ÅÒÛÅÎÉÉ ÏÐÅÒÁÃÉÉ ÏÓ×ÏÂÏÖÄÁÅÔ ×ÓÀ ÐÁÍÑÔØ, ÚÁÎÑÔÕÀ ÌÉÎÉÅÊ +*/ +int create_header(EPP *epp,char *dgtname); +/* óÏÚÄÁÅÔ ×ÙÈÏÄÎÏÊ ÆÁÊÌ */ +void write_labels(EPP *epp,DGT *dgt); +/* óÏÚÄÁÅÔ ÔÏÞËÉ */ +void end_line(LINE_END line); +/* úÁ×ÅÒÛÁÅÔ ÐÏÐÏÌÎÅÎÉÅ ÌÉÎÉÉ Ó ÕËÁÚÁÎÎÏÇÏ ËÏÎÃÁ. åÓÌÉ Ó ÄÒÕÇÏÇÏ ËÏÎÃÁ + ÏÎÁ ÕÖÅ ÎÅ ÍÏÖÅÔ ÐÏÐÏÌÎÑÔØÓÑ, ÄÅÌÁÅÔ ÅÊ put_line */ +LINEBUF enlarge(LINE_INODE buf); +/* õ×ÅÌÉÞÉ×ÁÅÔ ÄÌÉÎÕ ÌÉÎÉÉ ÎÁ 1. ðÒÉ ÎÅÏÂÈÏÄÉÍÏÓÔÉ ÄÏ×ÙÄÅÌÑÅÔ ÐÁÍÑÔØ */ +int smooth(LINE_INODE line,LINEBUF *buf); +/*óÇÌÁÖÉ×ÁÅÔ ÌÉÎÉÀ + ×ÏÚ×ÒÁÝÁÅÔ ËÏÌÉÞÅÓÔ×Ï ÕÚÌÏ×, ÏÓÔÁ×ÛÉÈÓÑ ÐÏÓÌÅ ÇÅÎÅÒÁÌÉÚÁÃÉÉ*/ +LINE_INODE new_line(int both,int col1,int row1,int col2,int row2); +/* óÏÚÄÁÅÔ ÎÏ×ÕÀ ÌÉÎÉÀ, ÐÏÍÅÝÁÑ × ÎÅÅ ÅÄÉÎÓÔ×ÅÎÎÙÊ ÓÅÇÍÅÎÔ Ó ÚÁÄÁÎÎÙÍÉ +ËÏÏÒÄÉÎÁÔÁÍÉ.*/ +void join_lines(LINE_END line1,LINE_END line2); +/* ïÂßÅÄÉÎÑÅÔ Ä×Å ÌÉÎÉÉ × ÏÄÎÕ. */ +int border_dgt(EPP *epp,char *dgtname,int offs_opt,int tol,int do_labels) +{int nrows=epp->lr-epp->fr+1; + int ncols=epp->lc-epp->fc+2; + unsigned short *left,*right,*up; + int this_node,next_node; + LINE_END hor_line,*vert_line; + int i,j; + offsite_option=offs_opt; + tolerance=tol; + if ((i=create_header(epp,dgtname))) return i; + rp1=calloc(ncols,sizeof(short int)); + rp2=calloc(ncols,sizeof(short int)); + lines=calloc(ncols,sizeof(struct LINE_END)); + for(i=0;ibuf) + this_node|=SEG_UP; +#ifdef DEBUG + if ((this_node&SEG_LEFT)&&(!hor_line.buf)) + fprintf(stderr,"Hor_line exists, where shouldn't x=%d y=%d\n",j,i); + if (!(this_node&SEG_LEFT)&&(hor_line.buf)) + fprintf(stderr,"Hor_line doesn't exist x=%d y=%d\n",j,i); + if (this_node&SEG_UP) + if ((vert_line->tail?vert_line->buf->x_tail:vert_line->buf->x_head)!=j) + fprintf(stderr,"Invalid vertical segment at x=%d y=%d\n",j,i); +#endif + switch(this_node) + {/* ìÉÎÉÉ ÐÒÏÄÏÌÖÁÀÔÓÑ ÐÒÑÍÏ*/ + case 0:/* äÅÌÁÔØ ÚÄÅÓØ ÎÅÞÅÇÏ */ break; + case SEG_UP|SEG_VERT:add_segment(*vert_line,j,i+1); + break; + case SEG_LEFT|SEG_RIGHT:add_segment(hor_line,j+1,i); + break; + /* ìÉÎÉÉ ÐÒÏÄÏÌÖÁÀÔÓÑ Ó ÉÚÇÉÂÏÍ */ + case SEG_LEFT|SEG_VERT:*vert_line=hor_line;hor_line.buf=NULL; + add_segment(*vert_line,j,i+1); + break; + case SEG_UP|SEG_RIGHT:hor_line=*vert_line;vert_line->buf=NULL; + add_segment(hor_line,j+1,i); + break; + /* ìÉÎÉÉ ÓÌÉ×ÁÀÔÓÑ */ + case SEG_UP|SEG_LEFT:join_lines(hor_line,*vert_line); + vert_line->buf=NULL; + hor_line.buf=NULL; + break; + /* ìÉÎÉÑ ÓÁÍÏÚÁÒÏÖÄÁÅÔÓÑ ÎÁ ÐÕÓÔÏÍ ÍÅÓÔÅ */ + case SEG_VERT|SEG_RIGHT:hor_line.buf=new_line(TRUE,j,i,j+1,i); + hor_line.tail=TRUE; + vert_line->buf=hor_line.buf; + vert_line->tail=FALSE; + add_segment(*vert_line,j,i+1); + /* ÓÏÚÄÁÔØ ÔÏÞËÕ */ + break; + /* ìÉÎÉÉ ÒÁÓÓÅËÁÀÔÓÑ - 5 ÓÌÕÞÁÅ× ËÏÇÄÁ × ÔÏÞËÅ 3 É ÂÏÌÅÅ ÌÉÎÉÊ */ + case SEG_VERT|SEG_LEFT|SEG_RIGHT: + /* T ×ÎÉÚ */ + end_line(hor_line); + hor_line.buf=new_line(FALSE,j,i,j+1,i); + hor_line.tail=TRUE; + vert_line->buf=new_line(FALSE,j,i,j,i+1); + vert_line->tail=TRUE; + /* cÏÚÄÁÔØ ÔÏÞËÕ */ + break; + case SEG_UP|SEG_LEFT|SEG_RIGHT: + /* ô ××ÅÒÈ ÎÏÇÁÍÉ */ + /*×ÙÂÒÏÓÉÔØ ÔÏÞËÕ*/ + end_line(hor_line); + end_line(*vert_line); + hor_line.buf=new_line(FALSE,j,i,j+1,i); + hor_line.tail=TRUE; + vert_line->buf=NULL; + break; + case SEG_UP|SEG_LEFT|SEG_VERT: + /* ô È×ÏÓÔÏÍ ×ÌÅ×Ï */ + /* ×ÙÂÒÏÓÉÔØ ÔÏÞËÕ */ + end_line(hor_line); + end_line(*vert_line); + vert_line->buf=new_line(FALSE,j,i,j,i+1); + vert_line->tail=TRUE; + hor_line.buf=NULL; + break; + case SEG_UP|SEG_RIGHT|SEG_VERT: + /* ô È×ÏÓÔÏÍ ×ÐÒÁ×Ï */ + /* ×ÙÂÒÏÓÉÔØ ÔÏÞËÕ */ + end_line(*vert_line); + hor_line.buf=new_line(FALSE,j,i,j+1,i); + hor_line.tail=TRUE; + vert_line->buf=new_line(FALSE,j,i,j,i+1); + vert_line->tail=TRUE; + /* ÓÏÚÄÁÔØ ÔÏÞËÕ */ + break; + case SEG_UP|SEG_RIGHT|SEG_LEFT|SEG_VERT: + /* ËÒÅÓÔ */ + end_line(*vert_line); + end_line(hor_line); + hor_line.buf=new_line(FALSE,j,i,j+1,i); + hor_line.tail=TRUE; + vert_line->buf=new_line(FALSE,j,i,j,i+1); + vert_line->tail=TRUE; + /* ÓÏÚÄÁÔØ ÔÏÞËÕ */ + break; + default: + /* ÷ÉÓÑÞÉÅ ÕÚÌÙ, ËÏÔÏÒÙÈ îå âù÷áåô */ + fprintf(stderr,"Dangling node at x=%d,y=%d\n",j,i); + } + this_node=next_node; + } + } +if (do_labels) write_labels(source,dest); +close_dgt(dest); + +return 0; +} + +void add_segment(LINE_END line,int col,int row) +{ + LINE_INODE l=line.buf; + + LINEBUF points; + if (line.tail) + {points=l->points+l->count-2; + if (points->x==col&&points[1].x==col) {points[1].y=row;return;} + if (points->y==row&&points[1].y==row) {points[1].x=col;l->x_tail=col;return;} + points=enlarge(l); + points+=l->count-1; + points->x=col; + points->y=row; + l->x_tail=col; + } + else + {LINEBUF tmp;int i=l->count; + points=l->points; + if (points->x==col&&points[1].x==col) {points->y=row;return;} + if (points->y==row&&points[1].y==row) {points->x=col;l->x_head=col;return;} + points=enlarge(l); + points+=l->count-1; + tmp=points-1; + for(;i>0;i--,*(points--)=*(tmp--)); + points->x=col; + points->y=row; + l->x_head=col; + } +} + +LINEBUF enlarge(LINE_INODE buf) +{ if (buf->count++==buf->limit) + buf->points=realloc(buf->points,(buf->limit+=DELTA)*sizeof(U_POINT)); + return buf->points; +} +void end_line(LINE_END line) +{ if (line.buf->both_ends) + line.buf->both_ends=FALSE; + else + put_line(line.buf); +} +#ifdef DEBUG +#define DEBUG_CHECK(x1,x2) if (line1.buf->x1!=line2.buf->x2) fprintf(stderr,"Joining lines with separate ends %d %d\n",line1.buf->x1,line2.buf->x2) +#else +#define DEBUG_CHECK(x1,x2) +#endif +#define COPY_DIRECT(l) for(i=l.buf->count,source=l.buf->points;i>0;i--,*(dest++)=*(source++)) +#define COPY_REVERSE(l) for(i=l.buf->count,source=l.buf->points+l.buf->count-1;i>0; i--,*(dest++)=*(source--)) +void join_lines(LINE_END line1,LINE_END line2) +{int i; + LINEBUF source,dest; + LINE_INODE new; + if (line1.buf==line2.buf) + { put_line(line1.buf); + return; + } + new=malloc(sizeof(struct INODE)); + new->count=line1.buf->count+line2.buf->count-1; + new->limit=(new->count+DELTA-1)/DELTA*DELTA; + new->points=malloc(new->limit*sizeof(U_POINT)); + dest=new->points; + + if (line1.tail) + { + new->x_head=line1.buf->x_head; + COPY_DIRECT(line1); + dest--; + + if (line2.tail) + { + DEBUG_CHECK(x_tail,x_tail); + new->x_tail=line2.buf->x_head; + COPY_REVERSE(line2); + } + else + { DEBUG_CHECK(x_tail,x_head); + new->x_tail=line2.buf->x_tail; + COPY_DIRECT(line2); + } + } + else + { + new->x_head=line1.buf->x_tail; + COPY_REVERSE(line1); + dest--; + if (line2.tail) + { DEBUG_CHECK(x_head,x_tail); + new->x_tail=line2.buf->x_head; + COPY_REVERSE(line2); + } + else + { DEBUG_CHECK(x_head,x_head); + new->x_tail=line2.buf->x_tail; + COPY_DIRECT(line2); + } + } + new->both_ends=-1; + if (line1.buf->both_ends) + { new->both_ends++; + lines[new->x_head].buf=new; + lines[new->x_head].tail=FALSE; + } + if (line2.buf->both_ends) + { new->both_ends++; + lines[new->x_tail].buf=new; + lines[new->x_tail].tail=TRUE; + } + if (new->both_ends<0) + put_line(new); + free(line1.buf->points); + free(line2.buf->points); + free(line1.buf); + free(line2.buf); +} +LINE_INODE new_line(int both,int col1,int row1,int col2,int row2) +{LINE_INODE tmp=malloc(sizeof(struct INODE)); + tmp->both_ends=both; + tmp->count=2; + tmp->limit=DELTA; + tmp->points=malloc(DELTA*sizeof(U_POINT)); + tmp->points[0].x=col1; + tmp->points[0].y=row1; + tmp->points[1].x=col2; + tmp->points[1].y=row2; + tmp->x_head=col1; + tmp->x_tail=col2; + return tmp; +} +void getrow(int row) +{ unsigned short int *tmp,*tmp2; + int i; + tmp=rp2; + rp2=rp1; + rp1=tmp; + if(row+source->frlr) + { + epp_get(source,source->fc,source->fr+row); + memcpy(rp1+1,source->row,(source->lc-source->fc)*sizeof(short)); + if (offsite_option) + { rp1[0]=source->offsite; + rp1[source->lc-source->fc+1]=source->offsite; + } + else + { rp1[0]=rp1[1]; + tmp=rp1+source->lc-source->fc; + *(tmp+1)=*tmp; + } + } + else + if (offsite_option) + for(i=source->lc-source->fc,tmp=rp1;i>=0;*(tmp++)=source->offsite,i--); + else + for(i=source->lc-source->fc,tmp=rp1,tmp2=rp2;i>=0;*(tmp++)=*(tmp2++),i--); + if (!row) + if (offsite_option) + for(i=source->lc-source->fc+1,tmp=rp2;i>=0;*(tmp++)=source->offsite,i--); + else + for(i=source->lc-source->fc,tmp=rp2,tmp2=rp1;i>=0;*(tmp++)=*(tmp2++),i--); +} +void put_line(LINE_INODE line) +{static int lineno=1; + int c,n;LINEBUF p;LINEBUF buf;POINT *s; + if (tolerance) c=smooth(line,&buf); + else {c=line->count;buf=line->points;} + p=line->points; + while (c>0) + { if (c>500) {n=500;c-=499;} else {n=c;c=0;} + s=dest->buffer->s; + dest->buffer->npoints=n; + dest->buffer->ID=1; + for(;n>0;p++,n--,s++) + {s->x=epp2dgtX(p->x); + s->y=epp2dgtY(p->y); + } + dgt_touch(dest); + dgt_next(dest); + p--; + } + lineno++; + free(buf); + free(line); +} +int rowfact,colfact; +int create_header(EPP *epp,char *dgtname) +{EPPHEADER h; + get_epp_header(epp,&h); + dest=creat_dgt(dgtname,epp->XLeft,epp->YBottom,epp->XRight,epp->YTop,h.coord_sys); +if (dest==NULL) return errno; +source=epp; +rowfact=epp->lr-epp->fr; +colfact=epp->lc-epp->fc; +if (tolerance) {rowfact*=2;colfact*=2;} +return 0; +} +int epp2dgtX(int col) +{ return (col*(unsigned long)65535/colfact-32768); +} +int epp2dgtY(int row) +{ return (32767-row*(unsigned long)65535/rowfact); + +} +#ifdef __GNUC__ +#define seg_len(a) abs(a->x-a[1].x?:a->y-a[1].y) +#else +#define seg_len(a) abs(a->x-a[1].x?a->x-a[1].x:a->y-a[1].y) +#endif +U_POINT make_middle_point(LINEBUF src1,LINEBUF src2) +{U_POINT tmp; + tmp.x=src1->x+src2->x; + tmp.y=src1->y+src2->y; + return tmp; +} +int smooth(LINE_INODE line,LINEBUF *buf) +{LINEBUF tmp; + LINEBUF dest,src1,src2; + int i,prev_kept=TRUE; + if (line->count==2) + { *buf=line->points; + line->points->x=2*line->points->x; + line->points->y=2*line->points->y; + line->points[1].x=2*line->points[1].x; + line->points[1].y=2*line->points[1].y; + return 2; + } + src1=line->points; + tmp=malloc(((4*line->count)/3+1)*sizeof(U_POINT)); + tmp->x=src1->x*2; + tmp->y=src1->y*2; + dest=tmp+1; + *buf=tmp; + for(i=line->count-2,src2=src1+1;i>=0;i--,src1++,src2++) + { + if (prev_kept) + { if (seg_len(src1)x=src2->x*2; + dest->y=src2->y*2;dest++; + } + } + } + else + { U_POINT tmp=make_middle_point(src1,src2); + dest--; + if (((dest-1)->x-dest->x)*(dest->y-tmp.y)== + ((dest-1)->y-dest->y)*(dest->x-tmp.x)) *dest=tmp; else *(++dest)=tmp; + dest++; + if(seg_len(src1)>tolerance) + { + if(i&&seg_len(src2)>tolerance) + { dest->x=src2->x*2; + dest->y=src2->y*2; + dest++; + prev_kept=TRUE; } + } + } + } + dest->x=src1->x*2; + dest->y=src1->y*2; + dest--; + if(line->count>4) + { + if(seg_len(dest)points); + line->count=dest-tmp+1; + line->points=tmp; + return line->count; +} +void write_labels(EPP *epp,DGT *dgt) +{ +} + +int main(int argc,char **argv) +{ struct option longoptions[]={ + {"tolerance",1,0,'t'}, + {"margin",0,0,'m'}, + {"output-file",1,0,'o'}, + {"labels",0,0,'l'}, + {"verbose",0,0,'%'}, + {"margins",0,0,'m'}, + {"help",0,0,1}, + {"version",0,0,2}, + {NULL,0,0,0}}; + int c,index; + int verbose=0; + int tolerance=0,draw_frame=1,do_labels=0; + char *endptr,outname[1024]=""; + EPP *epp; + while ((c=getopt_long(argc,argv,"t:mo:l%",longoptions,&index))!=-1) + switch(c) + { + case 't':tolerance=strtol(optarg,&endptr,0); + if (*endptr||tolerance<0||tolerance>100) + { fprintf(stderr,"Invalalid tolerance value %s\n",optarg); + exit(1); + } + break; + case 'f':draw_frame=0;break; + case 'l':do_labels=1;break; + case 'm':draw_frame=0;break; + + case '%':verbose=1;break; + case 'o':strcpy(outname,default_ext(optarg,".dgt")); + break; + case 2:show_version("border","$Revision: 1.1 $"); + case 1: + default: + printf ("Usage:border [-%%][-f][-l][-t value][-o file] file.epp\n"); + return (c!=1); + } + if (optind==argc) { fprintf(stderr,"No input file given\n"); + exit(1); + } + if (!*outname) strcpy(outname,force_ext(argv[optind],".dgt")); + epp=open_epp(default_ext(argv[optind],".epp")); + if (!epp) {fprintf(stderr,"Cannot open input file %s\n",argv[optind]); + exit(1); + } + install_progress_indicator(verbose?show_percent:check_int); + if ((c=clear_progress( + border_dgt(epp,outname,draw_frame,tolerance,do_labels)))) + unlink(outname); + return c; +} diff --git a/epu/centers.c b/epu/centers.c new file mode 100644 index 0000000..3cbd386 --- /dev/null +++ b/epu/centers.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include "epp.h" +#include "eppl_ut.h" +#include +void help(int exitcode) { + printf("Usage centers [-%%] cluster_file radius_file\n"); + printf("Table of coordinates and cluster values is written to stdout\n"); + exit (exitcode); +} +struct center { + int row,col; + int radius; + }; +struct center *table; + EPP *cluster_file,*radius_file; +int check_max_r (int col,int row, int value) { + int r=epp_get(radius_file,col,row); + struct center *rec = table+value; + if (rec->radiusradius=r; + rec->row=row; + rec->col=col; + } + return 0; +} +int main(int argc,char **argv) { + struct option long_options[]={ + {"help",0,0,1}, + {"version",0,0,2}, + {"verbose",0,0,'%'}, + }; + int c,index,result,i; + int verbose=0; + while ((c=getopt_long(argc,argv,"%",long_options,&index))!=-1) { + switch(c) { + case 2:show_version("centers","$Revision: 1.1 $"); + case '%':verbose=1;break; + case 1: + default: help(c==1?0:1); + } + } + cluster_file = open_epp(default_ext(argv[optind],".epp")); + if (!cluster_file) { + fprintf(stderr,"Cannot open file %s\n", + default_ext(argv[optind],".epp")); + exit (2); + } + optind++; + radius_file = open_epp(default_ext(argv[optind],".epp")); + if (!radius_file) { + fprintf(stderr,"Cannot open file %s\n", + default_ext(argv[optind],".epp")); + exit (2); + } + if (!is_aligned(cluster_file,radius_file)) { + fprintf(stderr,"Files don't have same coordinate system and cell size\n"); + exit(2); + } + table=calloc((cluster_file->max+1),sizeof(struct center)); + if (!table) { + perror("allocating table"); + exit(2); + } + install_progress_indicator(verbose?show_percent:check_int); + result=clear_progress(for_each_cell(cluster_file,check_max_r)); + if (result) { + return abs(result); + } + for (i=0;i<=cluster_file->max;i++) { + if (table[i].radius) { + printf ("%5d,%12g,%12g\n",i,alt_x(cluster_file,table[i].col), + alt_yc(cluster_file,table[i].row)); + } + } + return 0; +} diff --git a/epu/clip.c b/epu/clip.c new file mode 100644 index 0000000..807b883 --- /dev/null +++ b/epu/clip.c @@ -0,0 +1,154 @@ +#include +#include +#include +#include "epp.h" +#include "eppl_ut.h" +#include +#include +EPP *src,*dest,*mask; +EPP_LINK lnk; + int mask_value=-1; + int row1=32767, row2=-32768, col1=32767, col2=-32768; +void help(int exitcode) +{ + printf("Usage: clip [-%%] [-m number] [-o filename] [--help][--version] file mask_file\n" +"\t--help - displays this message\n" +"\t--version - shows version number\n" +"\t-%% --verbose - shows progress indicator\n" +"\t-m --mask-value - class in mask file, which denotes area to copy.\n" +"\t\t (default - all onsite classes)\n" +"\t-o name --output-file=name - sets name of output file\n"); +exit (exitcode); +} +int mask_offsite(int class) { + return class!=mask->offsite; +} + +int (*mask_func)(int)=mask_offsite; +int mask_class(int class) { + return class==mask_value; +} +int fill_cell(int col, int row, int value) +{ + if (mask_func(epp_get(mask,col,row))) + return epp_get(src,col,row); + else + return value; +} + +int fill_cell_transform(int col, int row, int value) +{ + if (mask_func(epp_get(mask,col,row))) + return epp_get(src,linked_col(lnk,col),linked_row(lnk,row)); + else + return value; +} + +int find_extent(int col, int row, int value) +{ + if (mask_func(value)) { + if (colcol2) col2=col; + if (rowrow2) row2=row; + } + return 0; +} +int main(int argc,char **argv) +{char output_file[1024]="clip.out.epp"; + struct option long_options[]= +{ + {"help",0,0,1}, + {"version",0,0,2}, + {"mask-value",1,0,'m'}, + {"verbose",0,0,'%'}, + {"output-file",1,0,'o'}, + {NULL,0,0,0}}; + int index,c;char *endptr; + int x1=32767,y1=32767,x2=-32767,y2=-32767, + result,verbose=0; + while ((c=getopt_long(argc,argv,"m:%o:",long_options,&index))!=-1) + { switch (c) + { case 2:show_version("mosaic","$Revision: 1.1 $"); + case '%':verbose=1;break; + case 'm':mask_value=strtol(optarg,&endptr,0); + if(*endptr) + { fprintf(stderr,"Invalid mask value %s\n",optarg); return 2; + } + mask_func=mask_class; + break; + case 'o':strcpy(output_file,default_ext(optarg,".epp"));break; + case 1: + case '?': + default: + help(c!=1); + } + } + if (argc-optind!=2) { help(1);} + src=open_epp(argv[optind]); + if (!src) src=open_epp(default_ext(argv[optind],".epp")); + if (!src) { + fprintf(stderr,"Cannot open file %s\n",argv[optind]); + exit(1); + } + mask=open_epp(argv[optind+1]); + if (!mask) mask=open_epp(default_ext(argv[optind+1],".epp")); + if (!mask) { + fprintf(stderr,"Cannot open file %s\n",argv[optind+1]); + exit(1); + } + if (mask_value>0&&(mask_valuemin||mask_value>mask->max)&& + mask_value!=mask->offsite) { + fprintf(stderr,"No cells with value %d in file %s\n",mask_value, + argv[optind+1]); + exit(1); + } + /* determine limits of new file */ + if (verbose) fprintf(stderr,"Determining output extent\n"); + install_progress_indicator(verbose?show_percent:check_int); + if (for_each_cell(mask,find_extent)!=0) exit(1); + fputc('\r',stderr); + x1=epp_col(mask,src->XLeft); + x2=epp_col(mask,src->XRight)+1; + y1=epp_row(mask,src->YTop); + y2=epp_row(mask,src->YBottom)+1; + if (y1>y2) { + int tmp=y1; + y1=y2; + y2=tmp; + } + if (x1>x2) { + int tmp=x1; + x1=x2; + x2=tmp; + } + row1=y1row2?row2:y2; + col1=x1col2?col2:x2; + if (row1>=row2||col1>=col2) { + fprintf(stderr,"No applicable cells found\n"); + exit(1); + } + dest=creat_epp(output_file,col1,row1,col2,row2, + alt_x(mask,col1),alt_y(mask,row1), alt_x(mask,col2+1), + alt_y(mask,row2+1), 100,0, src->offsite); + + + if (!dest) {fprintf(stderr,"Cannot create output file %s\n",output_file); + return 2; + } + if (verbose) fprintf(stderr,"Writing file\n"); + if (is_aligned(mask,src)) + result=clear_progress(for_each_cell(dest,fill_cell)); + else { + lnk=link_epp(mask,src); + result=clear_progress(for_each_cell(dest,fill_cell_transform)); + free(lnk); + } + close_epp(dest); + close_epp(src); + close_epp(mask); + if (result) unlink(output_file); + return result; +} diff --git a/epu/cluster b/epu/cluster new file mode 100755 index 0000000000000000000000000000000000000000..29577e3290c81181faf249bed4e8ce29dbc9ede9 GIT binary patch literal 85838 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
F`;iASx>{ByjY#-wE<(!HF9 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 J)dDa>{x2>B!u9|F literal 0 HcmV?d00001 diff --git a/epu/cluster.c b/epu/cluster.c new file mode 100644 index 0000000..5d11e28 --- /dev/null +++ b/epu/cluster.c @@ -0,0 +1,841 @@ +#include +#include +#include "epp.h" +#include "dgt.h" +#include +#include +#include "eppl_ut.h" +#include +#include + + +# ifdef __unix +# define EARLY_UNLINK 1 +# endif + +#define LABEL_DELTA 16384 +/* step to increase size of labels array */ +#define LABEL_INIT_SIZE 65536 +/* initial size of label array */ +int *labels, last, limit; +int megabytes=4; +int line_color=0; +EPP *epp;/*global pointer to input file for coordinate info access*/ +int new_label() +{ int tmp; + tmp=last; + labels[last]=0; + if (++last>=limit) + { labels=realloc(labels,(limit+=LABEL_DELTA)*sizeof(int)); + if (!labels) + { fprintf(stderr,"Cannot perform realloc()\n"); + exit(1); + } + } + return tmp; +} +void *check_alloc(size_t size) +{void *tmp; + if (!(tmp=malloc(size))) + { fprintf(stderr,"Cannot perform malloc()\n"); + exit(1); + } + return tmp; +} +unsigned short *alloc_buffer(int width,int *height) +{int i=0,l=0,h=megabytes*524288/width; + unsigned short *buffer; + buffer=malloc(h*width*sizeof(short)); + if (!buffer) + { while (l>1; + buffer=malloc(i*width*sizeof(short)); + if (buffer) + { free(buffer); + l=i+1; + } + else + { h=i-1; } + } + i--; + i=i*3/4; + buffer=malloc(i*width*sizeof(short)); + *height=i; + } + else + *height=h; + return buffer; +} +void alloc_labels() +{ labels=check_alloc(LABEL_INIT_SIZE*sizeof(int)); + limit=LABEL_INIT_SIZE; + labels[0]=1; + last=1; +} +int check_line(int this,int other) +{ + return other==line_color; +} +int check_border(int this,int other) +{ + return other!=this; +} + +int base_color(int color) +{ while (labels[color]<0) color=-labels[color]; + return color; +} +void report_dup(int row,int col,int class1,int class2) +{ static int dup_count=0; + fprintf(stderr,"\r Duplicate label %d:",++dup_count); + fflush(stderr); + printf("%10g %10g %6d %6d\n", + alt_xc(epp,col),alt_yc(epp,row),class1,class2); + +} +int merge_colors(int color1,int color2,int row,int col) +{ color1=base_color(color1); + color2=base_color(color2); + if (labels[color1]&&labels[color2]&&labels[color1]!=labels[color2]) + report_dup(row,col,labels[color1],labels[color2]); + if (color1==color2) + return color1; + if (color1lc-fin->fc; + nrows=fin->lr-fin->fr; +/* Allocating row buffers */ + in_rp1=check_alloc((ncol+2)*sizeof(short int)); + in_rp2=check_alloc((ncol+2)*sizeof(short int)); + out_rp1=check_alloc((ncol+2)*sizeof(long int)); + out_rp2=check_alloc((ncol+2)*sizeof(long int)); +/* initiliazing row buffers */ + for(i=0,cc=out_rp2,inp2=in_rp2;ifr;rowlr;seqrow++,row++) + { /*swap output row buffers*/ + cc=out_rp1;out_rp1=out_rp2;out_rp2=cc; + /* swap input row buffers*/ + inp1=in_rp1; in_rp1=in_rp2; in_rp2=inp1; + /*get input file row */ + memcpy(in_rp2+1,epp_getline(fin,fin->fc,row),ncol*sizeof(short int)); + /* position output files */ + epp_put(temp1,fin->fc,row,1); + epp_put(temp2,fin->fc,row,1); + /* handle progress indicator */ + if (*EndLineProc) + {int exitcode; + if ((exitcode=EndLineProc(row,seqrow,nrows))) + { return exitcode; } + } + /*scan row */ + for(j=epp->fc,col=1,inp1=in_rp1+1,inp2=in_rp2+1,cc=out_rp2+1; + col<=ncol;col++,inp1++,inp2++,cc++,j++) + { if (*inp2==line_color) *cc=0; + else + /*check for labels with id!=0&&id!=line_color */ + { if (do_labels&&*inp2) + { int* lptr=labels+base_color(*inp2); + if (*lptr) report_dup(row,col,*inp2,*lptr); + else *lptr=*inp2; + } + if (is_border(*inp2,*inp1)) color=0; else color= out_rp1[col]; + if (!is_border(*inp2,*(inp2-1))) + if (color) + {if(*(cc-1)) + color=merge_colors(*(cc-1),color,row,j); + } + else color=*(cc-1); + if (eight_way) + { if (!is_border(*inp2,*(inp1-1))) + if (color) color=merge_colors(out_rp1[col-1],color,row,j); + else color=out_rp1[col-1]; + if (!is_border(*inp2,*(inp1+1))) + if (color) color=merge_colors(out_rp1[col+1],color,row,j); + else color=out_rp1[col+1]; + } + if (!color) + { int j; + unsigned short int *this,*next; + /* no color found. Trying to get it from some right cell*/ + for (this=inp2,next=this+1,j=col;j<=ncol&& + is_border(*this,in_rp1[j]) + &&!is_border(*this,*next);this++,next++,j++); + if (j<=ncol&&!is_border(*this,in_rp1[j])) color=out_rp1[j]; + else + { color=new_label();} + } else color=base_color(color); + *cc=color; + } + } /* end of inner loop */ + /* save out_rp2 */ + for (i=0,inp1=temp1->row,inp2=temp2->row,cc=out_rp2+1; + i> 16; + } + } + reset_epp(temp1); + reset_epp(temp2); + close_epp(fin); + free(in_rp1); + free(in_rp2); + free(out_rp1); + free(out_rp2); + last--; + labels[0]=0; + return 0; +} + + +int remap_labels() +/* search array of labels to actual numer of clusters */ +/* case where there are no label points */ +{ long int i,j,c=1; + + for (i=1;i<=last;i++) + { j=base_color(i); + if (!labels[j]) + labels[i]=labels[j]=c++; + else + labels[i]=labels[j]; + } + c--; + if (c>65535) + { fprintf(stderr,"Count of contours exceedes EPPL limit of 65535\n"); + exit(2); + } + Create16bit=c>255; + printf("Temporary numbers used %d\nContours found %ld\n Output file will be %d-bit\n", + last, + c, + c>255?16:8); + return c; +} +int remap_hard_labels() +/* link temporary numbers with actual labels . + mark each temporary contour with no labels by unique number greater than + 65535 + + returns count of classes in resulting file. + Side effects: label[i] contain value to fill temporary contour i; + Create16bit is set appropriate. +*/ +{ long int i,j,c=65536,unlabelled=0,max=0; + for (i=1;imax) max=labels[j]; + } + } + Create16bit=max>255; + printf("Temporary numbers used %d\nMaximal class is %ld\nUnlabelled polygons found %ld\n", + last,max,unlabelled); + return max; +} +int second_pass(EPP *temp1,EPP *temp2,EPP *fout) +/* creates final clusterized file in case, if no fill rules given + file is not from rasterize */ +{int i,row,col,nrows,fc,secondc,exitcode; + unsigned short *src1,*src2,*dest; + nrows=fout->lr-fout->fr; + secondc=(fc=fout->fc)+1; + for (i=1,row=fout->fr;rowlr;i++,row++) + { if (EndLineProc) + if ((exitcode=EndLineProc(row,i,nrows))) return exitcode; + epp_put(fout,fc,row, + labels[epp_get(temp1,fc,row)|(epp_get(temp2,fc,row)<<16)]); + for (col=secondc,src1=epp_getline(temp1,secondc,row), + src2=epp_getline(temp2,secondc,row), + dest=fout->row+1; + collc; + *(dest++)=labels[*(src1++)|(*(src2++)<<16)],col++); + } + close_epp(temp1); + close_epp(temp2); + return 0; +} +void report_unlabelled(int row,int col,int class,int offsite) +{ int i,*lbl; + printf("%g %g unlabelled\n",alt_xc(epp,col),alt_yc(epp,row)); + for (i=1,lbl=labels+1;i<=last;i++,lbl++) + if (*lbl==class) *lbl=offsite; +} +void fill_and_save(EPP *fout,EPP *fill, unsigned short *rp1, + unsigned short *rp2, unsigned short *rp3, int row) +{int col=fout->fc,value; + for (rp1++,rp2++,rp3++;collc;rp1++,rp2++,rp3++,col++) + { value=*rp2; + if (!value) + switch (epp_get(fill,row,col)) + { case 1:value=*rp1;break; + case 2:value=*(rp2+1);break; + case 3:value=*(rp1+1);break; + case 4:value=*(rp3);break; + case 6:value=*(rp3+1);break; + case 8:value=*(rp2-1);break; + case 9:value=*(rp1-1);break; + case 12: value=*(rp3-1);break; + } + epp_put(fout,col,row,value?value:fout->offsite); + } +} +int second_pass_fill(EPP *temp1,EPP *temp2,EPP *fill,EPP *fout) +{unsigned short *rp1,*rp2,*rp3,*rtmp; + int i,row,col,ncols,nrows,fc,secondc,exitcode,value; + unsigned short *src1,*src2,*dest; + nrows=fout->lr-fout->fr; + secondc=(fc=fout->fc)+1; + ncols=fout->lc-fout->fc+2; + /*set global pointer */ + epp=fout; + /* allocate buffers */ + rp1=check_alloc(ncols*sizeof(short int)); + rp2=check_alloc(ncols*sizeof(short int)); + rp3=check_alloc(ncols*sizeof(short int)); + for(i=0,rtmp=rp2;ioffsite); + *rp1=rp1[ncols-1]=*rp3=rp3[ncols-1]=fout->offsite; + for (row=fout->fr,i=1;rowlr;i++,row++) + { if (EndLineProc) + if ((exitcode=EndLineProc(row,i,nrows))) return exitcode; + for (col=fout->fc, + dest=rp3+1, + src1=epp_getline(temp1,fc,row), + src2=epp_getline(temp2,fc,row); + collc; + dest++,src1++,src2++,col++) + {value=labels[*src1|(*src2<<16)]; + if (value>65535) + report_unlabelled(row,col,value,*dest=fout->offsite); + else *dest=value==65534?0:value; + } + if (row>fout->fr) fill_and_save(fout,fill,rp1,rp2,rp3,row-1); + rtmp=rp1; + rp1=rp2; rp2=rp3; rp3=rtmp; + } + fill_and_save(fout,fill,rp1,rp2,rp3,fout->lc-1); + close_epp(temp1); + close_epp(temp2); + close_epp(fill); + return 0; +} +/* rasterize should fill this variables near its beginning */ +int right_border, bottom_border, nrow, ncol,half_vert,half_horiz; +int dgt2col(int x) +{ return (((unsigned long)(x+32767))*ncol)/right_border; +} +int dgt2absrow(int y) +{ + return (((unsigned long)(32767-y))*nrow)/bottom_border+1; +} +int absrow2dgt(int row) +{ + return 32767-((long)((unsigned long)(row-1)*bottom_border/nrow)); +} +#define CELL(buf,row,col) *(buf+row*width+col) +#define row2dgt(row) (absrow2dgt(row+firstrow)) +#define dgt2row(y) (dgt2absrow(y)-firstrow) + +int save_buffer(EPP *epp,unsigned short *buf,int firstrow,int lastrow,int width) +{unsigned short *b; int row; + for (row=firstrow,b=buf;rowoffsite); + memcpy(epp->row,b,width*sizeof(short)); + if (EndLineProc) + { + if ((*EndLineProc)(row,row,nrow)) return -1; + } + + } + return 0; +} + + + +int rasterize(DGT *dgt,EPP *fout,EPP *fill,int modulo,int divisor) +{unsigned short *buf,*fillbuf=NULL; + int width,height,firstrow,lastrow,fry,lry; + width=fout->lc-fout->fc; + ncol=width; + nrow=fout->lr-fout->fr; + right_border=(fout->XRight-fout->XLeft)/(dgt->XRight-dgt->XLeft)*65535; + bottom_border=(fout->YBottom-fout->YTop)/(dgt->YBottom-dgt->YTop)*65535; + half_horiz=right_border>>1; + half_vert=bottom_border>>1; + buf=alloc_buffer(width,&height); + if (fill) + { + height>>=1; + fillbuf=buf+height*width; + } + firstrow=fout->fr; + lastrow=fout->fr+height; + do { + if (lastrow>fout->lc) lastrow=fout->lc; + memset(buf,0,width*height*sizeof(short)); + if (fill) memset(fillbuf,0,width*height*sizeof(short)); + reset_dgt(dgt); + fry=absrow2dgt(firstrow); + lry=absrow2dgt(lastrow); + while (!dgt_eof(dgt)) + { if (dgt_is_point(dgt)) + { int y,id,row,col; + if ((y=dgt_pointy(dgt))=fry)) + { if (divisor) id=(dgt_id(dgt)%modulo)/divisor; + else id=dgt_id(dgt); + if (id>65533) + { fprintf(stderr,"Label ID too large. Use -d or -x options\n"); + return 1; + } + if (!id) id=65534; + row=dgt2row(dgt_pointx(dgt)); + col=dgt2col(y); + if (CELL(buf,row,col)) + { printf("%g %g more than one object in same cell\n",alt_xc(fout,col),alt_yc(fout,row)); + } + CELL(buf,row,col)=id; + } + } + else + { if (dgt_yt(dgt)>lry&&dgt_yb(dgt)65533) + { fprintf(stderr,"Line ID too large. Use -d or -x options\n"); + return 1; + } + if (!id) id=65534; + } + /* Now we can begin an actual drawing */ + for (i=1,start=dgt->buffer->s,end=dgt->buffer->s+1; + iy>lry&&end->yyy>lry)) + { POINT rc1,rc2; + if (start->y>end->y) {p1=*end;p2=*start;} + else + {p1=*start;p2=*end;} + if (p1.yfry) + {int xx=(fry-p1.y)*((int)p2.x-p1.x)/((int)p2.y-p1.y)+p1.x; + p2.x=xx; + p2.y=fry; + } + rc2.x=dgt2col(p1.x); + rc2.y=dgt2row(p1.y); + rc1.x=dgt2col(p2.x); + rc1.y=dgt2row(p2.y); + if(rc2.x==rc1.x&&rc2.y==rc1.y) + { CELL(buf,rc1.y,rc1.x)=id; + if (fill) CELL(buf,rc1.y,rc1.x)|=2; + } + else + if ((unsigned long)abs((int)p1.x-p2.x)*bottom_border>(unsigned long)abs((int)p1.y-p2.y)*right_border) + { /* ïÔÒÅÚÏË ÛÉÒÅ ÞÅÍ ÄÌÉÎÎÅÅ */ + int xn,ndx,dy; + if (rc1.x>rc2.x) + { POINT tmp=rc1; + rc1=rc2; + rc2=tmp; + tmp=p1; + p1=p2; + p2=tmp; + } + xn=((int)p1.x+32767)*ncol-half_horiz; + ndx=((int)p2.x-p1.x)*ncol; + dy=(int)p2.y-p1.y; + for (x=rc1.x;x<=rc2.x;x++) + { unsigned long ybig=(32767UL-((right_border*x-xn)*dy/ndx+p1.y))*nrow; + y=ybig/bottom_border+1-firstrow; + CELL(buf,y,x)=id; + if (fill) + { + CELL(fillbuf,y,x)|=ybig%bottom_border>half_vert?4:1; + } + } + } + else + {int yn,ndy,dx; + yn=(32767-(int)p1.y)*nrow-half_vert; + ndy=((int)p2.y-p1.y)*nrow; + dx=(int)p2.x-p1.x; + for (y=rc1.y;y<=rc2.y;y++) + { unsigned long xbig=(32767UL+((yn-bottom_border* + (y-1+firstrow))*dx /ndy+p1.x))*ncol; + x=xbig/right_border; + CELL(buf,y,x)=id; + if (fill) { + CELL(fillbuf,y,x)|=xbig%right_border>half_horiz?8:2; + } + } + } + } + + + } + } + dgt_next(dgt); + } + if (save_buffer(fout,buf,firstrow,lastrow,width)) {free(buf);return 1;}; + if (fill) + if (save_buffer(fill,fillbuf,firstrow,lastrow,width)) {free(buf);return 1;}; + firstrow+=height; + lastrow+=height; + } while(firstrowlc); + free(buf); + return 0; +} +void extract_digits(int base,char *s,int *divisor,int *modulo) +{char *c; + *divisor=0; + *modulo=0; + for (c=s;*c;c++) + switch(*c) + {case '_':if (*modulo&&!*divisor)*divisor=base; + else + *divisor*=base; + *modulo*=base; + break; + case 'x':if(!*modulo) *modulo=base; + else *modulo*=base; + if (*divisor) {fprintf(stderr,"Digits in -d or -x option must form continous range\n"); + exit(1); + } + break; + default: fprintf(stderr,"Parameter of -d or -x option must consist of ``x''-es\n" +"for each digit to use and ``_'' for each digit to ignore\n"); + exit(1); + } + if (*divisor==0) *divisor=1; + if (*modulo/ *divisor>0x10000) + { fprintf(stderr,"EPP file classes cannot contain more than four digits\n"); + exit(1); + } +} + +# ifndef EARLY_UNLINK + +char __tempnames[4][80]; +char *tempnames[]={__tempnames[0],__tempnames[1],__tempnames[2],__tempnames[3]}; +char **tempptr=tempnames; +void store_temp_name(char *name) +{strcpy(*(tempptr++),name); +} +void remove_temp_files() +{while(--tempptr>=tempnames) + { unlink(*tempptr); + } +} + +# endif +char cluster_help[]= +"Usage: cluster [--help] [-version] [-%%8lu] [-o file] [-c color] file\n"; +char rasterize_help[]= +"Usage: rasterize [--help] [-version] [-o file] [-c color] [-s size]\n" +"\t[-x string] [-d string] [-m megabytes] [-%%pu] file\n"; + +int main(int argc,char **argv) +{struct option cluster_options[]={ + {"help",0,0,1}, + {"version",0,0,2}, + {"verbose",0,0,'%'}, + {"output-file",1,0,'o'}, + {"line-color",1,0,'c'}, + {"8-way",0,0,'8'}, + {"rasterize",0,0,'R'}, + {"labels",0,0,'l'}, + {"unuque",0,0,'u'}, + {NULL,0,0,0}}, + rasterize_options[]={ + {"help",0,0,1}, + {"version",0,0,2}, + {"verbose",0,0,'%'}, + {"output-file",1,0,'o'}, + {"cell-size",1,0,'s'}, + {"line-color",1,0,'c'}, + {"line-point",0,0,'p'}, + {"digits",1,0,'d'}, + {"hex-digits",1,0,'x'}, + {"unique",0,0,'u'}, + {"memory",1,0,'m'}, + {NULL,0,0,0}}, + *options=cluster_options; + int c,index,expect_vector=0; + char c_opt[]="%o:c:8Rlu", + r_opt[]="%o:c:s:pudxm:", + *optstring=c_opt; + char *basename; + char tempname[1024],outname[1024]=""; + int verbose=0,eight_way=0,do_labels=0,result,maxclass; + EPP *fin,*ffill=NULL,*ftmp1,*ftmp2,*fout; + int modulo=0,divisor=0; + int (*remap)(void)=remap_labels; + double cell_size=0.0; + + if ((basename=strrchr(argv[0],'/'))) + basename++; else basename=argv[0]; + if (!strcmp(basename,"rasterize")) + { optstring=r_opt; options=rasterize_options; + expect_vector=1; + remap=remap_hard_labels; + do_labels=1; + } + while ((c=getopt_long(argc,argv,optstring,options,&index))!=-1) + switch (c) + { + case '%' :verbose=1;break; + case 2 : show_version("cluster","$Revision: 1.1 $"); + case 'o':strcpy(outname,default_ext(optarg,".epp"));break; + case 'R':optstring=r_opt;options=rasterize_options; + remap=remap_hard_labels; + do_labels=1; + expect_vector=1;break; + case 'c':{char *endptr; + line_color=strtol(optarg,&endptr,0); + if (*endptr||line_color<=0||line_color>65535) + { fprintf(stderr,"Invalid line color %s\n",optarg); + exit(1); + } + break; + } + case 'u':if (!expect_vector) is_border=check_border; + else {remap=remap_labels;do_labels=0;} + break; + case '8':if (expect_vector) + {fprintf(stderr,"option -8 is valid only in cluster mode\n"); + exit(1); + } + eight_way=1; + break; + case 'l':if (expect_vector) + {fprintf(stderr,"option -l is valid only in cluster mode\n"); + exit(1); + } + remap=remap_labels;do_labels=1; + break; + case 's':if (!expect_vector) + {fprintf(stderr,"option -%c is valid only in rasterize mode\n",c); + exit(1); + }else + {char *endptr; + cell_size=strtod(optarg,&endptr); + if (*endptr) + { fprintf(stderr,"Invalid cell size value %s\n",optarg); + exit(1); + } + } + break; + case 'p': if (!expect_vector) + {fprintf(stderr,"option -%c is valid only in rasterize mode\n",c); + exit(1); + } + expect_vector=2; + break; + case 'd':if (!expect_vector) + {fprintf(stderr,"option -%c is valid only in rasterize mode\n",c); + exit(1); + } + extract_digits(10,optarg,&divisor,&modulo); + break; + case 'x':if (!expect_vector) + {fprintf(stderr,"option -%c is valid only in rasterize mode\n",c); + exit(1); + } + extract_digits(16,optarg,&divisor,&modulo); + break; + case 'm':if (!expect_vector) + {fprintf(stderr,"option -%c is valid only in rasterize mode\n",c); + exit(1); + }else + {char *endptr; + megabytes=strtol(optarg,&endptr,0); + if (*endptr) + { fprintf(stderr,"Invalid integer value %s\n",optarg); + + exit(1); + } + } + break; + case 1: + case '?': + default: printf(expect_vector?rasterize_help:cluster_help); + exit(c!=1); + } + /***********************************************************/ + if (argc==optind) + {fprintf(stderr,"No input file name given\n"); + exit(1); + } + strcpy(tempname,default_ext(argv[optind],expect_vector?".dgt":".epp")); + if (!*outname) + if (expect_vector) strcpy(outname,force_ext(tempname,".epp")); + else +# ifdef __unix + strcpy(outname,"cluster.out.epp"); +# else + strcpy(outname,"cluster.epp"); +# endif + install_progress_indicator(verbose?show_percent:check_int); + /*** Zero pass,rasterizing **********************************/ + if (expect_vector) + {DGT *dgt=open_dgt(tempname); + int rows,cols; + double XR,YB; + if (!dgt) { fprintf(stderr,"Cannot open file %s\n",tempname); + exit(1); + } + /*calculating file dimensions*/ + if (cell_size==0.0) + { /*no cell size given, defaulting to 1024 cells/line*/ + cell_size=fabs(dgt->XRight-dgt->XLeft)/1024.0; + } + cols=ceil(fabs(dgt->XRight-dgt->XLeft)/cell_size); + rows=ceil(fabs(dgt->YTop-dgt->YBottom)/cell_size); + XR=cols*cell_size; + if (dgt->XRightXLeft) XR=dgt->XLeft-XR; + else XR+=dgt->XLeft; + YB=rows*cell_size; + if (dgt->YTop>dgt->YBottom) YB=dgt->YTop-YB; + else YB+=dgt->YTop; + fprintf(stderr,"EPP file would be %d rows by %d columns\n",rows,cols); + + /*creating outputfile*/ + Create16bit=1; + if(expect_vector==1) + { /*rasterized file would be temporary */ + line_color=65535; + strcpy(tempname,force_ext(tmpnam(NULL),".epp")); + } else + strcpy(tempname,outname); + fin=creat_epp(tempname,1,1,cols,rows,dgt->XLeft,dgt->YTop,XR,YB, + 100,0,0); + + if (!fin) {fprintf(stderr,"Cannot create file %s\n",tempname); + exit(1); + } + if (expect_vector==1) + { Create16bit=0; +#ifdef EARLY_UNLINK + unlink(tempname); +#else + store_temp_name(tempname); +#endif + strcpy(tempname,force_ext(tmpnam(NULL),".epp")); + ffill=creat_epp(tempname,1,1,cols,rows,dgt->XLeft,dgt->YTop,XR,YB, + 100,0,0); + if (!ffill) {fprintf(stderr,"Cannot create file %s\n",tempname); + exit(1); + } +#ifdef EARLY_UNLINK + unlink(tempname); +#else + store_temp_name(tempname); +#endif + } + if (verbose) fprintf(stderr,"Rasterizing...\n"); + if ((result=rasterize(dgt,fin,ffill,modulo,divisor))) + exit(clear_progress(result)); + close_dgt(dgt); + if (expect_vector==2) + { /* nothing more to do - close and exit */ + if (fin->max<=255) + { + if (verbose) fprintf(stderr,"\rConverting to 8 bit\n"); +#ifdef EARLY_UNLINK + unlink(outname); + fast_convert_to_8bit(fin,outname); +#else + strcpy(tempname,force_ext(outname,".8bi")); + fast_convert_to_8bit(fin,tempname); + unlink(outname); + rename(tempname,outname); +#endif + } else close_epp(fin); + exit(clear_progress(result)); + } + else + { reset_epp(fin); + reset_epp(ffill); + } + } else + if (!(fin=open_epp(tempname))) + { fprintf(stderr,"Cannot open file %s",tempname); + exit(1); + } +/*************** First pass -- counting unique contours ***************/ +if (verbose) fprintf(stderr,"\rAssembling polygons...\n"); + + Create16bit=1; + strcpy(tempname,force_ext(tmpnam(NULL),".epp")); + if(!(ftmp1=creat_epp_as(tempname,fin))) + { fprintf(stderr,"Cannot create file %s\n",tempname); + exit(1); + } +#ifdef EARLY_UNLINK + unlink(tempname); +#else + store_temp_name(tempname); +#endif + strcpy(tempname,default_ext(tmpnam(NULL),".epp")); + if(!(ftmp2=creat_epp_as(tempname,fin))) + { fprintf(stderr,"Cannot create file %s\n",tempname); + exit(1); + } +#ifdef EARLY_UNLINK + unlink(tempname); +#else + store_temp_name(tempname); +#endif + if (!expect_vector&&(is_border==check_border))line_color=fin->offsite; + if((result=first_pass(fin,ftmp1,ftmp2,eight_way,do_labels))) + exit(clear_progress(result)); +/**** creating correspondence table *************/ + if (verbose) {fputc('\r',stderr);fflush(stderr);} + maxclass=remap(); +/************* Second pass -- creating final file *****************/ +fout=creat_epp_as(outname,ftmp1); +if (do_labels) fout->offsite=Create16bit?65535:255; +if (verbose) fprintf(stderr,"\rWriting final file...\n"); +if (ffill) + result=second_pass_fill(ftmp1,ftmp2,ffill,fout); +else + result=second_pass(ftmp1,ftmp2,fout); + fout->max=maxclass; +close_epp(fout); +#ifndef EARLY_UNLINK + remove_temp_files(); +#endif +return(clear_progress(result)); +} diff --git a/epu/dgt2gen b/epu/dgt2gen new file mode 100755 index 0000000000000000000000000000000000000000..699239decc23932998900483c7c3f4af2d96e236 GIT binary patch literal 74260 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
    V^sgAd#~5In*PU%2`0~6ys^cl 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 EA0cJIcK`qY literal 0 HcmV?d00001 diff --git a/epu/dgt2gen.c b/epu/dgt2gen.c new file mode 100644 index 0000000..9329ea5 --- /dev/null +++ b/epu/dgt2gen.c @@ -0,0 +1,128 @@ +#include +#include +#include "dgt.h" +#include "math.h" +#include "eppl_ut.h" +#include +FILE *lines,*points; +long int linecount=0,pointcount=0; +char line_feed[3]="\n"; +void putreal(FILE *f,double x) +{ + if (fabs(x)>1000000000.0||fabs(x)<0.01) + fprintf(f,"%13E",x); + else + if (fabs(x)<10.0) + fprintf(f,"%13.10f",x); + else + if (fabs(x)<1000.0) + fprintf(f,"%13.8f",x); + else if(fabs(x)<1000000.0) + fprintf(f,"%13.5f",x); + else + fprintf(f,"%13.2f",x); +} +void putpoint(FILE *f,DGT *dgt,POINT p) +{ putreal(f,real_x(dgt,p.x)); + fputc(' ',f); + putreal(f,real_y(dgt,p.y)); + fputs(line_feed,f); +} + +void putline(DGT* dgt) +{int i; + fprintf(lines,"%ld%s",dgt_id(dgt),line_feed); + for(i=0;i +/*#define LSB_FIRST 1*/ +#ifdef LSB_FIRST +/* portability issues when reading binary files */ +/* define LSB_FIRST, when your processor uses Intel byte order */ +# define COPY_DOUBLE(x) x +# define COPY_LONG(x) x +# define COPY_SHORT(x) x +#else +# define COPY_DOUBLE(x) swapdouble(x) +# define COPY_LONG(x) swaplong(x) +# define COPY_SHORT(x) swapshort(x) +#endif +#include +#include +#include +#include + +#define DO_XSHIFT 1 +#define DO_YSHIFT 2 +#define DO_SCALE 4 +#define RESCALING 7 +#define SET_X_LEFT 0x10 +#define SET_X_RIGHT 0x20 +#define SET_Y_BOTTOM 0x40 +#define SET_Y_TOP 0x80 +#define SET_PRJ 8 +#define DGT_OPS 0xFF +#define EXPLICIT_COORDS 0xF0 +#define SET_FR 0x100 +#define SET_FC 0x200 +#define EXPLICIT_ROW_COL 0x300 +#define DO_ALIGN 0x400 +#define SET_AREA 0x800 +#define SET_COMMENT 0x1000 +#define SET_UNIT 0x2000 +#define SET_OFFSITE 0x4000 +#define VERBOSE_MODE 0x8000 +#define MAX_PROJECTION 3 +#define MAX_UNIT 5 + +long operations=0;/* Bit mask of operations to apply */ +void usage(int return_code) +{ printf( +"Usage eheader options files\n\ +where options may be:\n\ +These are applicable to both EPP and DGT files:\n\ +-x n - shifts alternative x by n\n\ +-y n - same with alternative y\n\ +-s factor - multiplies all coordinates by factor\n\ +-Xl n - sets alternative x of left border to specified value\n\ +-Xr n - same with right border\n\ +-Yb n, Yt - same with bottom and top y\n\ +-p xxx - set projection type, where projection can be:\n\ +\tnone - cause EPPL ver 3 to say \"No alternate coordinates\"\n\ +\tutm - UTM projection\n\ +\tstplate - state plane\n\ +\tll - geographic coordinates\n\ +Following is applicable to EPP files only:\n\ +-o n - set offsite value\n\ +-fr n - set first row to n\n\ +-fc n - set first column to n\n\ +-A filename - align to specified file\n\ +-a n - set cell area\n\ +-c \"string\" - set description\n\ +-u xxx - set area unit type, where unit type may be:\n\ +\tnone - cause EPPL ver 3 to say \"No alternate coordinates\"\n\ +\tft - square feet\n\ +\tm - square meters\n\ +\tkm - square kilometers\n\ +\tmile - square miles\n\ +\tha - hectares\n\ +\tacre - acres\n"); + exit(return_code); +} + +int get_epp_header(FILE *f,EPPHEADER *hdr); +int put_epp_header(FILE *f,EPPHEADER *hdr); +int get_dgt_header(FILE *f,EPPHEADER *hdr,long *maxline,long *maxpt); +int put_dgt_header(FILE *f,EPPHEADER *hdr); +void main(int argc,char **argv) +{ int i=1; + char *progname; + int option(int *num,char **argv); + void process_file(const char *filename); + void read_align_values(const char *filename); + if (argc==1) usage(0); +progname=strrchr(argv[0],'/'); +if (progname==NULL) progname=argv[0]; +else progname++; + if (!strcmp(progname,"maplist")) + operations|=VERBOSE_MODE; + else + if (!strcmp(progname,"mapalign")) + { operations|=DO_ALIGN; + if (!strcmp(argv[1],"-v")) {operations|=VERBOSE_MODE;i++;} + read_align_values(argv[i++]); + if (!strcmp(argv[i],"-v")) {operations|=VERBOSE_MODE;i++;} + } + else + while (argv[i]&&(argv[i][0]=='-')) + { if (!option(&i,argv)) + { fprintf(stderr,"Unknown option :%s\n",argv[i]); + exit(1); + } + } + for(;i32767) offsite=65536-offsite; + if (offsite<-32768) + { fprintf(stderr,"Invalid offsite value %s\n",argv[*num]); + exit(1); + } + break; + } + case 's' : { check_key(argv[(*num)],DO_SCALE,EXPLICIT_COORDS); + scale_fact=double_value(argv[++(*num)]); + break; + } + case 'f': { switch((argv[(*num)])[2]) + { case 'r':{ check_key(argv[(*num)],SET_FR,DO_ALIGN); + fr=int_value(argv[++(*num)]); + break; + } + case 'c':{ check_key(argv[(*num)],SET_FC,DO_ALIGN); + fc=int_value(argv[++(*num)]); + break; + } + default: { fprintf(stderr,"Invalid option %s\n",argv[(*num)]); + exit(1); + } + break; + } + break; + } + case 'a':{ check_key(argv[(*num)],SET_AREA,RESCALING|EXPLICIT_COORDS); + area_val=double_value(argv[++(*num)]); + break; + } + case 'A':{ check_key(argv[(*num)],DO_ALIGN,EXPLICIT_ROW_COL); + read_align_values(argv[++(*num)]); + break; + } + case 'c':{check_key(argv[(*num)],SET_COMMENT,0); + strncpy(header,argv[++(*num)],32); + break; + } + case 'u':{check_key(argv[(*num)],SET_UNIT,0); + (*num)++; + if (!strcmp(argv[(*num)],"none")) + { unit=0; } + else + if (!strcmp(argv[(*num)],"ft")) + { unit=1; } + else + if (!strcmp(argv[(*num)],"m")) + { unit=2; } + else + if (!strcmp(argv[(*num)],"km")) + { unit=3; } + else + if (!strcmp(argv[(*num)],"mile")) + { unit=4; } + else + if (!strcmp(argv[(*num)],"ha")) + { unit=5; } + else + if (!strcmp(argv[(*num)],"acre")) + { unit=6; } + else + { fprintf(stderr,"Invalid area unit %s\n",argv[(*num)]); + exit(1); + } + break; + } +case 'v': { operations|=VERBOSE_MODE; + break; + } +default: { return 0; + } +} + +(*num)++; +return 1; +} + +int get_epp_header(FILE *f,EPPHEADER *hdr) +{ EPPHEADER buf; + if (fseek(f,0,SEEK_SET)) return 0; + if (!fread(&buf,sizeof(buf),1,f)) return 0; + hdr->kind=COPY_SHORT(buf.kind); + if ((hdr->kind!=8)&&(hdr->kind!=16)) return 0; +hdr->fr = COPY_SHORT(buf.fr); +hdr->lr = COPY_SHORT(buf.lr); +hdr->fc = COPY_SHORT(buf.fc); +hdr->lc = COPY_SHORT(buf.lc); +hdr->fry = COPY_DOUBLE(buf.fry); +hdr->lry = COPY_DOUBLE(buf.lry); +hdr->fcx = COPY_DOUBLE(buf.fcx); +hdr->lcx = COPY_DOUBLE(buf.lcx); +hdr->kind = COPY_SHORT(buf.kind); +hdr->base = COPY_SHORT(buf.base); +hdr->scale = COPY_SHORT(buf.scale); +hdr->offsite = COPY_SHORT(buf.offsite); +hdr->sfact = COPY_DOUBLE(buf.sfact); +hdr->access_ptr = COPY_LONG(buf.access_ptr); +hdr->minclass = COPY_SHORT(buf.minclass); +hdr->maxclass = COPY_SHORT(buf.maxclass); +hdr->area_unit =(buf.area_unit); +hdr->coord_sys =(buf.coord_sys); +memcpy(&(hdr->date),&(buf.date),16+8+32); +return 1; +} +int put_epp_header(FILE *f,EPPHEADER *hdr) +{ EPPHEADER buf; + if (fseek(f,0,SEEK_SET)) return 0; +memset(&buf,0x20,128); +buf.kind=COPY_SHORT(hdr->kind); +buf.fr = COPY_SHORT(hdr->fr); +buf.lr = COPY_SHORT(hdr->lr); +buf.fc = COPY_SHORT(hdr->fc); +buf.lc = COPY_SHORT(hdr->lc); +buf.fry = COPY_DOUBLE(hdr->fry); +buf.lry = COPY_DOUBLE(hdr->lry); +buf.fcx = COPY_DOUBLE(hdr->fcx); +buf.lcx = COPY_DOUBLE(hdr->lcx); +buf.kind = COPY_SHORT(hdr->kind); +buf.base = COPY_SHORT(hdr->base); +buf.scale = COPY_SHORT(hdr->scale); +buf.offsite = COPY_SHORT(hdr->offsite); +buf.sfact = COPY_DOUBLE(hdr->sfact); +buf.access_ptr = COPY_LONG(hdr->access_ptr); +buf.minclass = COPY_SHORT(hdr->minclass); +buf.maxclass = COPY_SHORT(hdr->maxclass); +buf.area_unit =(hdr->area_unit); +buf.coord_sys =(hdr->coord_sys); +memcpy(&(buf.date),&(hdr->date),16+8+32); +{int i; + for(i=strlen(buf.date);i<16;buf.date[i++]=' '); + for(i=strlen(buf.time);i<8;buf.time[i++]=' '); + for(i=strlen(buf.comment);i<32;buf.comment[i++]=' '); +} +return fwrite(&buf,sizeof(buf),1,f); +} +int get_dgt_header(FILE *f,EPPHEADER *hdr,long *maxline,long *maxpt) +{ DGTHEADER buf; + if (fseek(f,0,SEEK_SET)) return 0; + if (!fread(&buf,sizeof(buf),1,f)) return 0; + hdr->fry = COPY_DOUBLE(buf.ytop); + hdr->lry = COPY_DOUBLE(buf.ybottom); + hdr->fcx = COPY_DOUBLE(buf.xleft); + hdr->lcx = COPY_DOUBLE(buf.xright); + hdr->coord_sys =(buf.coord_sys); + *maxline=COPY_LONG(buf.maxline); + *maxpt=COPY_LONG(buf.maxpt); + return 1; +} +int put_dgt_header(FILE *f,EPPHEADER *hdr) +{ DGTHEADER buf; + if (fseek(f,0,SEEK_SET)) return 0; + fread(&buf,sizeof(buf),1,f); + if (fseek(f,0,SEEK_SET)) return 0; + buf.ytop = COPY_DOUBLE(hdr->fry); + buf.ybottom = COPY_DOUBLE(hdr->lry); + buf.xleft = COPY_DOUBLE(hdr->fcx); + buf.xright = COPY_DOUBLE(hdr->lcx); + buf.coord_sys =(hdr->coord_sys); + return fwrite(&buf,sizeof(buf),1,f); +} +char *coord_name[]={"Alternative","UTM","State plane","Geographic"}; +char *unit_name[]={"unknown units","sq.feet","sq.m","sq.km","sq.miles","ha","acres"}; +void print_epp_header(const char *filename,EPPHEADER hdr) +{ char commentstr[33],datestr[17],timestr[9]; + commentstr[32]=datestr[16]=timestr[8]='\0'; + strncpy(datestr,hdr.date,16); + strncpy(timestr,hdr.time,8); + if ((unsigned char)hdr.area_unit>6) hdr.area_unit=0; + if ((unsigned char)hdr.coord_sys>3) hdr.coord_sys=0; + printf("File:%s\n\ +Description:%s\n\ +First row = %6d Last row = %6d\n\ +First column = %6d Last column = %6d\n\ +%s coordinates:\nFirst row = %12g Last row = %12g\n\ +First column = %12g Last column = %12g\n\ +Cell area: %12g %s\n\ +Created: %s %s\n\ +Data size = %d\n\ +Minimum class = %d, Maximum class = %d, Offsite class = %d\n", +filename,strncpy(commentstr,hdr.comment,32), +hdr.fr,hdr.lr,hdr.fc,hdr.lc,coord_name[(int)hdr.coord_sys], +hdr.fry,hdr.lry,hdr.fcx,hdr.lcx,hdr.sfact,unit_name[(int)hdr.area_unit], +datestr,timestr,hdr.kind, +hdr.minclass,hdr.maxclass,hdr.offsite); +} +void print_dgt_header(const char*filename,EPPHEADER hdr,long maxline,long maxpt) +{ printf("File: %s\n\ +%s coordinates:\n\ +Xleft = %12g, XRight = %12g\n\ +Ytop = %12g, YBottom = %12g\n\ +Maximum point id = %ld, Maximum line id = %ld\n", +filename,coord_name[(int)hdr.coord_sys],hdr.fcx,hdr.lcx,hdr.fry,hdr.lry, +maxline,maxpt); +} +void set_row( EPPHEADER *hdr,int row) +{ + hdr->lr=hdr->lr-hdr->fr+row; + hdr->fr=row; +} +void set_column( EPPHEADER *hdr,int column) +{ + hdr->lc=hdr->lc-hdr->fc+column; + hdr->fc=column; +} +int align(EPPHEADER *hdr,const char *name) +{ double cw,sfx,sfy; + int new_row,new_col; + cw=(align_val.XRight-align_val.XLeft)/(align_val.lc-align_val.fc+1); + sfx=cw/((hdr->lcx-hdr->fcx)/(hdr->lc-hdr->fc+1)); + cw=(align_val.YBottom-align_val.YTop)/(align_val.lr-align_val.fr+1); + sfy=cw/((hdr->lry-hdr->fry)/(hdr->lr-hdr->fr+1)); + if (fabs(sfx-1)>(1.0/(hdr->lc-hdr->fc+1))||fabs(sfy-1)>(1.0/(hdr->lr-hdr->fr+1))) + { fprintf(stderr,"Unable to align file %s.\nRescale it with X factor %7.4f and Y factor %7.4f\n", + name,sfx,sfy); + return 0;} + + new_col=(hdr->fcx-align_val.XLeft)/(align_val.XRight-align_val.XLeft)* + (align_val.lc-align_val.fc+1); + new_col+=align_val.fc; + new_row=(hdr->fry-align_val.YTop)/(align_val.YBottom-align_val.YTop)* + (align_val.lr-align_val.fr+1); + new_row+=align_val.fr; + set_row(hdr,new_row); + set_column(hdr,new_col); + return 1; +} +void process_file(const char *filename) +{ FILE *f; + EPPHEADER hdr; + long maxline,maxpt; + int isdgt; + char ext[8]; + int readonly=0; + strncpy(ext,filename+(strlen(filename)-3),4); + #ifdef __MSDOS__ + strlwr(ext);/* dos filenames are not case-sensitive */ + #endif + isdgt=0; + if (!strcmp(ext,"dgt")||!strcmp(ext,"DGT")) + { if (!(operations&(DGT_OPS|VERBOSE_MODE))) + { fprintf(stderr,"No operations to apply to %s\n",filename); + return; + } + isdgt=1; + } + else + if (strcmp(ext,"epp")&&strcmp(ext,"EPP")) + { fprintf(stderr,"File %s has unknown extension\n",filename); + return; + } + f=fopen(filename,"r+b"); + if (NULL==f) + if (NULL==(f=fopen(filename,"rb"))) + { + fprintf(stderr,"Cannot open file %s\n",filename); + return; + } else readonly=1; + if (!(isdgt?get_dgt_header(f,&hdr,&maxline,&maxpt):get_epp_header(f,&hdr))) + { fprintf(stderr,"invalid %s file %s\n",ext,filename); + return; + } + if (hdr.coord_sys>MAX_PROJECTION) + hdr.coord_sys=0; + if (!isdgt) + { if (hdr.area_unit>MAX_UNIT) + hdr.area_unit=0; + if (hdr.kind==8) + { if (hdr.maxclass>255) hdr.maxclass=255; + if (hdr.minclass>hdr.maxclass) hdr.minclass=0; + } + } + /****************** Applying requested operations *****************/ + if (operations & DO_XSHIFT) + { hdr.fcx+=x_shift; + hdr.lcx+=x_shift; + } + if (operations & DO_YSHIFT) + { hdr.fry+=y_shift; + hdr.lry+=y_shift; + } + if (operations & DO_SCALE) + { hdr.fcx*=scale_fact; + hdr.fry*=scale_fact; + hdr.lcx*=scale_fact; + hdr.lry*=scale_fact; + } + if (operations & SET_X_LEFT) hdr.fcx=XLeft; + if (operations & SET_X_RIGHT) hdr.lcx=XRight; + if (operations & SET_Y_BOTTOM) hdr.lry=YBottom; + if (operations & SET_Y_TOP) hdr.fry=YTop; + if (operations & SET_PRJ) hdr.coord_sys=proj; + if (!isdgt &&(operations & SET_FR)) set_row(&hdr,fr); + if (!isdgt &&(operations & SET_FC)) set_column(&hdr,fc); + if (!isdgt &&(operations & DO_ALIGN)) align(&hdr,filename); + if (!isdgt &&(operations & SET_AREA)) hdr.sfact=area_val; + if (!isdgt &&(operations & SET_COMMENT)) + { char *src=header; + char *dest=hdr.comment; + int count=0; + memset(&(hdr.comment),' ',32); + while (*src!='\0'&&count++<32) *(dest++)=*(src++); + } + if (!isdgt &&(operations & SET_UNIT )) hdr.area_unit=unit; + if (!isdgt &&(operations & SET_OFFSITE )) + +if (hdr.kind==16||(offsite<=255&&offsite>=-1))hdr.offsite=offsite; + else + hdr.offsite=-1; + /******************** End of operations ***************************/ + if (operations & VERBOSE_MODE ) + { if (readonly) printf("Read-only "); + if (isdgt) + print_dgt_header(filename,hdr,maxline,maxpt); + else + print_epp_header(filename,hdr); + } +if ((operations& ~VERBOSE_MODE)&& !readonly) + if (!(isdgt?put_dgt_header(f,&hdr):put_epp_header(f,&hdr))) + { fprintf(stderr,"Cannot modify file %s\n",filename); + clearerr(f); + } + fclose(f); +} diff --git a/epu/extents.c b/epu/extents.c new file mode 100644 index 0000000..d23f28f --- /dev/null +++ b/epu/extents.c @@ -0,0 +1,187 @@ +#include +#include +#include "epp.h" +#include "eppl_ut.h" +typedef struct Contour {int Class,XMin,YMin,XMax,YMax,Count;} CONTOUR; +/* ÏÐÉÓÁÎÉÅ ÏÄÎÏÇÏ ËÏÎÔÕÒÁ */ +CONTOUR *a; +EPP *epp; +EPPHEADER *h; +int first_class; /* ÄÌÑ ÐÅÒÅÓÞÅÔÁ */ + +int sort_area(const void *p1, const void *p2) +/* óÒÁ×ÎÅÎÉÅ ÐÏ ÐÌÏÝÁÄÉ */ +{ +int t1,t2; +t1=(((CONTOUR *)p1))->Count; +t2=(((CONTOUR *)p2))->Count; +if (t1>t2) return 1; +if (t1==t2) return 0; +return -1; +} + +int sort_y_top(const void *p1, const void *p2) +/* óÒÁ×ÎÅÎÉÅ ÐÏ ×ÅÒÈÎÅÊ ÇÒÁÎÉÃÅ */ +{ +int t1, t2; +t1=((CONTOUR *)p1)->YMin; +t2=((CONTOUR *)p2)->YMin; +if (t1>t2) return 1; +if (t1==t2) return 0; +return -1; +} + +int sort_y_bottom(const void *p1, const void *p2) +{ +int t1, t2; +t1=((CONTOUR *)p1)->YMax; +t2=((CONTOUR *)p2)->YMax; +if (t1>t2) return 1; +if (t1==t2) return 0; +return -1; +} +int sort_x_right(const void *p1, const void *p2) +{ +int t1, t2; +t1=((CONTOUR *)p1)->XMax; +t2=((CONTOUR *)p2)->XMax; +if (t1>t2) return 1; +if (t1==t2) return 0; +return -1; +} +int sort_x_left(const void *p1, const void *p2) +{ +int t1, t2; +t1=((CONTOUR *)p1)->XMin; +t2=((CONTOUR *)p2)->XMin; +if (t1>t2) return 1; +if (t1==t2) return 0; +return -1; +} + +int sort_x(const void *p1, const void *p2) +/* óÒÁ×ÎÅÎÉÅ ÐÏ ÓÒÅÄÎÅÍÕ X */ +{ +int t1, t2; +t1=((CONTOUR *)p1)->XMin+((CONTOUR *)p1)->XMax; +t2=((CONTOUR *)p2)->XMin+((CONTOUR *)p2)->XMax; +if (t1>t2) return 1; +if (t1==t2) return 0; +return -1; +} + +int sort_y(const void *p1, const void *p2) +/* óÒÁ×ÎÅÎÉÅ ÐÏ ÓÒÅÄÎÅÍÕ Y */ +{ +int t1, t2; +t1=((CONTOUR *)p1)->YMin+((CONTOUR *)p1)->YMax; +t2=((CONTOUR *)p2)->YMin+((CONTOUR *)p2)->YMax; +if (t1>t2) return 1; +if (t1==t2) return 0; +return -1; +} + +/*int sort_s(const void *p1, const void *p2)*/ +/* óÒÁ×ÎÅÎÉÅ ÐÏ ÏÔÎÏÛÅÎÉÀ count/(W*H) */ +/*{ +}*/ + + + +int process_cell(int col,int row, int value) +{ +CONTOUR *b=a+value; +if (b->XMin>col) b->XMin=col; +if (b->XMaxXMax=col; +if (b->YMin>row) b->YMin=row; +if (b->YMaxYMax=row; +b->Count++; +return 0; +} + +int main(int argc,char **argv) +{ +int (*sort_function)(const void *,const void *)=NULL; +/*òÁÚÂÏÒ ÐÁÒÁÍÅÔÒÏ× ËÏÍÁÎÄÎÏÊ ÓÔÒÏËÉ*/ +struct option longoptions[]={ +{"help",0,0,1}, +{"version",0,0,2}, +{"verbose",0,0,'%'}, +{"alt-coords",0,0,'a'}, +{"sort-left",0,0,'l'}, +{"sort-right",0,0,'r'}, +{"sort-top",0,0,'t'}, +{"sort-bottom",0,0,'b'}, +{"sort-area",0,0,'A'}, +{"sort-x-center",0,0,'x'}, +{"sort-y-center",0,0,'y'}, +{"output-file",1,0,'o'}, +{"header",0,0,'h'}, +{NULL,0,0,0} +}; +int c,index,i; +int verbose=0; +int use_alt=0; +int print_header=0; +CONTOUR *b; +FILE *f=stdout; +while((c=getopt_long(argc,argv,"alrtbxyA%ho:",longoptions,&index))!=-1) + switch(c) + { case 2:show_version("extents","$Revision: 1.1 $"); + case '%': verbose=1; break; + case 'a': use_alt=1;break; + case 'o': if (!(f=fopen(optarg,"w"))) + {fprintf(stderr,"Cannot open file %s\n",optarg); return 2;} + break; + case 'l':sort_function=sort_x_left; break; + case 'r':sort_function=sort_x_right; break; + case 't':sort_function=sort_y_top; break; + case 'b':sort_function=sort_y_bottom; break; + case 'x':sort_function=sort_x; break; + case 'y':sort_function=sort_y; break; + case 'A':sort_function=sort_area; break; + case 'h':print_header=1;break; + case 1: + case '?': + default: printf("Usage: extents [-%%alrtbxtA] [-o file] file.epp\n"); + return c!=1; + } + + +/*ïÔËÒÙÔØ epp-ÛÎÉË, ÐÒÏÞÉÔÁÔØ ÚÁÇÏÌÏ×ÏË, ÓÏÚÄÁÔØ ÍÁÓÓÉ× CONTOUR ÄÌÉÎÙ +*/ +epp=open_epp(default_ext(argv[optind],".epp")); +if(epp==NULL) {fprintf(stderr,"Can not open file %s\n", + default_ext(argv[optind],".epp")); + return 2;} +a=calloc(sizeof(CONTOUR),epp->max+1); +for(i=0,b=a;i<=epp->max;i++,b++) +{ b->XMin=epp->lc; + b->XMax=epp->fc; + b->YMin=epp->lr; + b->YMax=epp->fr; + b->Class=i; +} +install_progress_indicator(verbose?show_percent:check_int); +if (clear_progress(for_each_cell(epp,process_cell))) return 3; +if (sort_function) qsort(a,epp->max+1,sizeof(CONTOUR),sort_function); +if (print_header) + fprintf(f,use_alt? +" Class X Left X Right Y Top Y Bottom Area\n": +" Class Min Col Max Col Min Row Max Row Count\n"); +for(i=0;i<=epp->max;i++) + if (a[i].Count) + { if (use_alt) + fprintf(f,"%6d %13g %13g %13g %13g %14g\n", + a[i].Class,alt_x(epp,a[i].XMin),alt_x(epp,a[i].XMax+1), + alt_y(epp,a[i].YMin),alt_y(epp,a[i].YMax+1), + a[i].Count*epp->cell_area); + else + fprintf(f,"%6d %7d %7d %7d %7d %9d\n", + a[i].Class,a[i].XMin,a[i].XMax,a[i].YMin,a[i].YMax,a[i].Count); + } + +close_epp(epp); +if (f!=stdout) fclose(f); +return 0; +} diff --git a/epu/fill.c b/epu/fill.c new file mode 100644 index 0000000..afa35e0 --- /dev/null +++ b/epu/fill.c @@ -0,0 +1,157 @@ +#include +#include +#include +#include "epp.h" +#include "eppl_ut.h" +int color_to_fill=0; +int color_to_not_expand=-1;/* 1 in eppl */ +int cells_filled,cells_remain; +int verbose=0; +int gap_size=0; +void add_color(int color,int *col_list,int *col_count,int *list_len) +{ int i; + if(color==color_to_fill||color==color_to_not_expand) return; + for (i=0;i<*list_len;i++,col_list++,col_count++) + if (color==col_list[i]) {col_count[i]++;return;} + *col_list=color;*col_count=1;(*list_len)++; +} +#define addcolor(i) add_color(i,color,count,&cc); +void fillrow(unsigned short *out_row,unsigned short *prev_row, + unsigned short *cur_row,unsigned short *next_row, + int ncols) +{ int i; + for (i=1;i<=ncols;i++) + if (cur_row[i]!=color_to_fill) *(out_row++)=cur_row[i]; + else + { int color[8],count[8],ii,jj,cc=0,cnt=0; + unsigned short *clr_ptr=prev_row+i-1; + addcolor(*(clr_ptr++)); + addcolor(*(clr_ptr++)); + addcolor(*(clr_ptr++)); + addcolor(cur_row[i-1]); + addcolor(cur_row[i+1]); + addcolor(*(clr_ptr=next_row+i-1)); + addcolor(*(++clr_ptr)); + addcolor(*(++clr_ptr)); + for(ii=0,jj=color_to_fill;iicnt) {cnt=count[ii];jj=color[ii];} + if (jj==color_to_fill) + {cells_remain++;*(out_row++)=color_to_fill;} + else + {cells_filled++;*(out_row++)=jj;}; + } +} +int fill(char *in_file_name,char *out_file_name) +{ unsigned short int *prev_row,*cur_row,*next_row,*rptr,*dest; + int i,j,nrows,seqrow,ncols; + EPP *in_file; + EPP *out_file; + + cells_filled=0; + cells_remain=0; + + in_file=open_epp(in_file_name); + if (NULL==in_file) + { fprintf(stderr,"Cannot open file %s\n",in_file_name); + exit(2); + } + Create16bit=in_file->kind==16; + out_file=creat_epp_as(out_file_name,in_file); + if (NULL==out_file) + { fprintf(stderr,"Cannt create file %s\n",out_file_name); + exit(2); + } + ncols=in_file->lc-in_file->fc; + prev_row=malloc(sizeof(short)*(ncols+2)); + cur_row=malloc(sizeof(short)*(ncols+2)); + next_row=malloc(sizeof(short)*(ncols+2)); + for(i=0;i<=ncols+1;prev_row[i++]=color_to_fill); + cur_row[0]=cur_row[ncols+1]=next_row[0]=next_row[ncols+1]=color_to_fill; + rptr=epp_getline(in_file,in_file->fc,in_file->fr); + for(i=1,dest=cur_row+1;i<=ncols;*(dest++)=*(rptr++),i++); + rptr=epp_getline(in_file,in_file->fc,in_file->fr+1); + for(i=1,dest=next_row+1;i<=ncols;*(dest++)=*(rptr++),i++); + nrows=in_file->lr-in_file->fr; + for(seqrow=1,i=in_file->fr+2;seqrow<=nrows;i++,seqrow++) + { + if (EndLineProc) + if ((*EndLineProc)(i,seqrow,nrows)) return 1; + epp_put(out_file,out_file->fc,i-2,out_file->offsite); + fillrow(out_file->row,prev_row,cur_row,next_row,ncols); + {unsigned short int *tmp; + tmp=prev_row; + prev_row=cur_row; + cur_row=next_row; + next_row=tmp; + } + if (ilr) + { rptr=epp_getline(in_file,in_file->fc,i); + for(j=1,dest=next_row+1;j<=ncols;*(dest++)=*(rptr++),j++); + } + else + for(j=1,dest=next_row+1;j<=ncols;*(dest++)=color_to_fill,j++); +} +out_file->max=in_file->max; +out_file->min=in_file->min; +close_epp(out_file); +close_epp(in_file); +return 0; +} +int main(int argc,char **argv) +{ +#ifdef unix + char out_name[256]="fill.out.epp"; +#else + char out_name[256]="fill.epp"; +#endif + struct option long_options[]={ + {"help",0,0,1}, + {"version",0,0,2}, + {"verbose",0,0,'%'}, + {"gap-size",required_argument,0,'g'}, + {"color-to-fill",required_argument,0,'f'}, + {"exclude-color",required_argument,0,'x'}, + {"output-file",required_argument,0,'o'}, + {NULL,0,0,0} }; + int c; + int index; + while ((c=getopt_long(argc,argv,"%g:c:f:x:o:",long_options,&index))!=-1) + { switch(c) + { + case 2:/*version*/ + show_version("fill","$Revision: 1.1 $"); + + case '%':verbose=1;break; + case 'g':/*gap size is unused now*/ + gap_size=atoi(optarg);break; + case 'c':/*color to fill*/ + color_to_fill=atoi(optarg);break; + case 'x':color_to_not_expand=atoi(optarg);break; + case 'o':strcpy(out_name,optarg);break; + case 1: + case '?': + default: + /*help*/ + printf("Usage %s [--help] [--version] [-v] [-g gap size]\n" + "\t[-c color to fill] [-x color to exclude] [-o output file]\n" + "\tepp file\n",argv[0]); + return c==1?0:2; + } + } + if (argc==optind) + {fprintf(stderr,"No input files specified\n"); + return 2; + } + if (argc>optind+1) + { fprintf(stderr,"Too many input files\n"); + return 2; + } + install_progress_indicator(verbose?show_percent:check_int); + if((c=clear_progress(fill(argv[optind],out_name)))) + {unlink(out_name); + return 2; + } + printf("Cells filled %d\nCells of class %d remain:%d\n", + cells_filled,color_to_fill,cells_remain); + return cells_remain?1:0; +} diff --git a/epu/intable b/epu/intable new file mode 100755 index 0000000000000000000000000000000000000000..99482a125e7d16e25f59283950a6218804f21c75 GIT binary patch literal 66559 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 literal 0 HcmV?d00001 diff --git a/epu/intable.c b/epu/intable.c new file mode 100644 index 0000000..25c1251 --- /dev/null +++ b/epu/intable.c @@ -0,0 +1,252 @@ +#include +#include +#include +#include +#include +#include +#include "epp.h" +#include "eppl_ut.h" +struct record { + unsigned short int outclass; + unsigned short int classes[32]; + }; +typedef struct record *rec; + +void help(int exitcode) +{ printf("Usage: intable [-%%] [-i] [-o file] [-f file] [-O value] [-u value] files\n"); + exit(exitcode); +} + +short int* table; + +EPP *files[32]; +char skip[32]={0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,}; +int files_count,count,limit,delta; +int skip_count=0; +char delimiter=','; + +int offsite=-1; +int unmatched=-1; + +int compare(struct record *r1, struct record *r2) +{int i; + for (i=0;iclasses[i]>r2->classes[i]) return 1; + else + if (r1->classes[i]classes[i]) return -1; + } + return 0; + +} +int search(struct record *key,int *index) +{int l=0,h=count-1,i,c; + while(l<=h) + { i=(l+h)>>1; + c=compare((struct record *)(table+(1+files_count)*i),key); + if (c<0) l=i+1; + else + { h=i-1; + if (!c) { *index=i;return 1;} + } + } + *index=l; + return 0; +} +void insert(struct record *key,int index) +{ int i;unsigned short int *l; + if (count==limit) + { + table=realloc(table,(limit+=delta)*(1+files_count)*sizeof(short int)); + if (!table) + { fprintf(stderr,"Couldn't realloc table. Table limit is %d\n",limit); + exit(1); + } + } + + for(i=count;i>index;i--) + memcpy(table+(i)*(1+files_count),table+(i-1)*(1+files_count), + (1+files_count)*sizeof(short int)); + l=(unsigned short int *)(table+index*(1+files_count)); + memcpy(l,key,(files_count+1)*sizeof(short int)); + count++; +} +void setvalue(int index,int value) +{ + unsigned short int *l=(unsigned short int *)(table+index*(1+files_count)); + *l=value; +} +int lineno=0; +int add_record(FILE *f) +{ /* ÷ÏÚ×ÒÁÝÁÅÔ 0, ÅÓÌÉ ÔÁËÁÑ ËÏÍÂÉÎÁÃÉÑ ÕÖÅ ÅÓÔØ*/ + struct record tmp; + char *endptr; + char line[256]; + int i,v,j; + endptr=fgets(line,256,f); + if (!endptr) return 1; + lineno++; + for(i=0,j=0;imin||v>files[i]->max)&&v!=files[i]->offsite) */ + if (v<0||v>65535) + { fprintf(stderr,"Illegal value %d in column %d of line %d\n", + v,i+1,lineno); + exit(2); + } + if (!skip[i]) + tmp.classes[j++]=v; + } + v=strtol(endptr,&endptr,0); + while (*endptr==' '||*endptr=='\t')endptr++; + if(*endptr!='\n') + { fprintf(stderr,"Extra data in line %d\n",lineno); + exit(2); + } + if (v<0||v>65535) + { fprintf(stderr,"Illegal value %d in column %d of line %d\n", + v,files_count+1,lineno); + exit(2); + } + tmp.outclass=v; + if (v>255) Create16bit=1; + if (search(&tmp,&i)) + { setvalue(i,v); return 0;} + else + { insert(&tmp,i); return 1;} +} + +int make_cell(int x,int y,int value) +{ struct record tmp; + int i;EPP **epp; + for(i=0,epp=files;i65535) + { fprintf(stderr,"Invalid class value %s\n",s); + exit(2); + } + return tmp; +} + +int main(int argc,char **argv) +{ struct option long_options[]={ +{"help",0,0,1}, +{"version",0,0,2}, +{"verbose",0,0,'%'}, +{"delimiter",1,0,'d'}, +{"input-file",1,0,'f'}, +{"output-file",1,0,'o'}, +{"offsite",1,0,'O'}, +{"unmatched",1,0,'u'}, +{"skip",1,0,3}, +{"ignore-dupes",0,0,'i'}, +{NULL,0,0,0} +}; +char outname[1024]="intable.out.epp"; +int index,c,i; +int ignore_dupes=0,verbose=0; +FILE *f=stdin; +EPP *new_file,**epp; +while ((c=getopt_long(argc,argv,"%iu:d:f:o:O:129456789", + long_options,&index))!=-1) +switch(c) +{case 2:show_version("intable","$Revision: 1.1 $"); + case '%':verbose=1;break; + case 'd':delimiter=optarg[0];break; + case 'f':if (!(f=fopen(optarg,"r"))) + { fprintf(stderr,"Cannot open file %s\n",optarg); + exit(2); + } break; + case 'o':strcpy(outname,default_ext(optarg,".epp"));break; + case 'O':offsite=getclass(optarg); + break; + case 'u':unmatched=getclass(optarg);break; + case 'i':ignore_dupes=1;break; + case '?': + case '1': case '2': case '3': case '4': case '5': case '6': case '7': + case '8': case '9': + skip_count++; + skip[c-'1']=1; + break; + case 3:{char *endptr; + i=strtol(optarg,&endptr,0); + if (*endptr||i<1||i>32) + { fprintf(stderr,"Invalid column number %s\n",optarg); + exit(2); + } + skip_count++; + skip[i]=1; + break; + } + case 1: + default: + help(c==1); + + } + files_count=argc-optind; + table=malloc(65536*sizeof(short)*(files_count+1)); + limit=65536; + delta=1024; + count=0; + epp=files; + for(i=0,index=optind;ioffsite=offsite; + install_progress_indicator(verbose?show_percent:check_int); + if ((i=clear_progress(for_each_cell(new_file,make_cell)))) + unlink(outname); + if (!Create16bit||new_file->max>255) + close_epp(new_file); + else + {unlink(outname); + fast_convert_to_8bit(new_file,outname); + } + +return abs(i); +} diff --git a/epu/mosaic.c b/epu/mosaic.c new file mode 100644 index 0000000..beebeaa --- /dev/null +++ b/epu/mosaic.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include "epp.h" +#include "eppl_ut.h" +#include +#include +EPP **files; +int count; + +int fill_cell(int col,int row,int value) +{ int i,c; + EPP **epp; + for (i=count,epp=files+count-1;i>0;i--,epp--) + if ((c=epp_get(*epp,col,row))!=(*epp)->offsite) return c; + return value; +} + +void help(int exitcode) +{ + printf("Usage: mosaic [-%%RA] [-O number] [-o filename] [--help][--version]files\n" +"\t--help - displays this message\n" +"\t--version - shows version number\n" +"\t-%% --verbose - shows progress indicator\n" +"\t-R --force-row - process misaligned files using row/col coords\n" +"\t-A --force-alt - process misaligned files using alternative coords\n" +"\t-O number --offsite=number - set offsite value of output file\n" +"\t-o name --output-file=name - sets name of output file\n"); +exit (exitcode); +} + +int main(int argc,char **argv) +{char output_file[1024]="mosaic.out.epp"; + struct option long_options[]= +{ + {"help",0,0,1}, + {"version",0,0,2}, + {"offsite",1,0,'O'}, + {"verbose",0,0,'%'}, + {"force-row",0,0,'R'}, + {"force-alt",0,0,'A'}, + {"output-file",1,0,'o'}, + {NULL,0,0,0}}; + int index,i,c;char *endptr; + int offsite=-1, x1=32767,y1=32767,x2=-32767,y2=-32767, + max=0,min=65535,force=0,use_alt=1,result,verbose=0; + double X1,Y1,X2,Y2; + EPP *out_f; + while ((c=getopt_long(argc,argv,"O:%RAo:",long_options,&index))!=-1) + { switch (c) + { case 2:show_version("mosaic","$Revision: 1.1 $"); + case '%':verbose=1;break; + case 'O':offsite=strtol(optarg,&endptr,0); + if(*endptr||offsite<0||offsite>65535) + { fprintf(stderr,"Invalid offsite value %s\n",optarg); return 2; + } + break; + case 'A':force=1;use_alt=1;break; + case 'R':force=1;use_alt=0;break; + case 'o':strcpy(output_file,default_ext(optarg,".epp"));break; + case 1: + case '?': + default: + help(c!=1); + } + } + count=argc - optind; + if (!count) { fprintf(stderr,"No input files specified\n");return 2;} + files=malloc(count*sizeof(EPP *)); + for (i=optind,index=0;i0&&!compare_cell_size(files[0],files[index])) + { fprintf(stderr,"File %s is incompatible with %s\n",argv[i],argv[optind]); + return 2; + } + if (index>0&&!is_aligned(files[0],files[index])) + { fprintf(stderr,"File %s is misaligned with %s\n",argv[i],argv[optind]); + if (!force) return 2; + if (use_alt) + {if (!shift_epp(files[index],epp_row(files[0],files[index]->YTop), + epp_col(files[0],files[index]->XLeft))) + {fprintf(stderr,"Cannot align file %s\n",argv[i]) ; + return 2; + } + } + else + { files[index]->XLeft=alt_x(files[0],files[index]->fc); + files[index]->XRight=alt_x(files[0],files[index]->lc); + files[index]->YTop=alt_y(files[0],files[index]->fr); + files[index]->YBottom=alt_y(files[0],files[index]->lr); + } + } + if (!index||x1>files[index]->fc){ x1=files[index]->fc;X1=files[index]->XLeft;} + if (!index||x2lc){ x2=files[index]->lc;X2=files[index]->XRight;} + if (!index||y1>files[index]->fr){ y1=files[index]->fr;Y1=files[index]->YTop;} + if (!index||y2lr){ y2=files[index]->lr;Y2=files[index]->YBottom;} + if (maxmax) max=files[index]->max; + if (min>files[index]->min) min=files[index]->min; + if (files[index]->kind==16) Create16bit=1; + + } + x2--; + y2--; + if (offsite<0) + { if (files[0]->offsiteoffsite>max) + offsite=files[0]->offsite; + else + offsite=Create16bit?65535:255; + } + install_progress_indicator(verbose?show_percent:check_int); + out_f=creat_epp(output_file,x1,y1,x2,y2,X1,Y1,X2,Y2, + 100,0,offsite); + if (!out_f) {fprintf(stderr,"Cannot create output file %s\n",output_file); + return 2; + } + result=clear_progress(for_each_cell(out_f,fill_cell)); + close_epp(out_f); + if (result) unlink(output_file); + for (i=0;i +#include +#include +#include "epp.h" +#include "eppl_ut.h" +void help() +{ printf("Usage: neighbours [-%%][-d] file\n"); + exit(0); +} + +short int* table; + +EPP *file; + +int count,limit,delta; +int duplicates=0; + +int compare(unsigned short int *r1, unsigned short int *r2) +{int i; + for (i=0;i<2;i++,r1++,r2++) + { if (*r1>*r2) return 1; + else + if (*r1<*r2) return -1; + } + return 0; + +} +int search(unsigned short *key,int *index) +{int l=0,h=count-1,i,c; + while(l<=h) + { i=(l+h)>>1; + c=compare(table+2*i,key); + if (c<0) l=i+1; + else + { h=i-1; + if (!c) { *index=i;return 1;} + } + } + *index=l; + return 0; +} +void insert(unsigned short *key,int index) +{ int i; + if (count==limit) + { + table=realloc(table,(limit+=delta)*2*sizeof(short int)); + if (!table) + { fprintf(stderr,"Couldn't realloc table. Table limit is %d\n",limit); + exit(1); + } + } + + for(i=count;i>index;i--) + {table[2*i]=table[2*(i-1)]; + table[2*i+1]=table[2*i-1];} + table[2*index]=key[0]; + table[2*index+1]=key[1]; + count++; +} +void delete(int index) +{ int i; + for(i=index+1;ioffsite||v2==file->offsite) return; + if (v1>v2) {key[0]=v2;key[1]=v1;} + else {key[0]=v1;key[1]=v2;} + if (!search(key,&index)) + insert(key,index); +} + +void print_table() +{int i,j;unsigned short int pair[2]; + unsigned short *t=table; + i=0; + while (ilr-file->fr; + install_progress_indicator(verbose?show_percent:check_int); + for(i=file->fr,k=1;ilr;i++,k++) + { if (EndLineProc) + if ((c=(*EndLineProc)(i,k,rows))) + {break;} + for(j=file->fc;jlc;j++) + { add_pair((c=epp_get(file,j,i)),epp_get(file,j+1,i)); + add_pair(c,epp_get(file,j,i+1)); + add_pair(c,epp_get(file,j+1,i+1)); + } + } + if(clear_progress(c)) exit(abs(c)); + print_table(); + free(table); + close_epp(file); + return 0; +} diff --git a/epu/outtab.c b/epu/outtab.c new file mode 100644 index 0000000..4aeb629 --- /dev/null +++ b/epu/outtab.c @@ -0,0 +1,180 @@ +#include +#include +#include +#include "eppl_ut.h" +#include "epp.h" + +/* This structure is used to keep information about + combination of classes. count is count of cells already found, + classes are classes. Really each of these structures occupies + less then sizeof(struct record) bytes, becouse count of files is + usially less than 32 */ +struct record { + long int count; + unsigned short int classes[32]; + }; + + + + +unsigned short int* table; +typedef struct record *rec; + +EPP *files[32]; /* array of pointers to files + +int tuple_size, /* bytes in tuple != files_count*sizeof(short)+sizeof(int) + due to 4-byte alignment of + files_count, /* Count of files */ + count, /* current size of table */ + limit, /* number of records, currently allocated */ + delta; /* Increment of record number to reallocate when reserves + exhausted */ + +/* comparation function. Sorts two records according to classes + of files in order + returns -1 if *r1 <*r2 ,0 if *r1=*r2 1 if *r1>*r2 +*/ +int compare(struct record *r1, struct record *r2) +{int i; + for (i=0;iclasses[i]>r2->classes[i]) return 1; + else + if (r1->classes[i]classes[i]) return -1; + } + return 0; + +} + +/* Searches table for record which contains classes, specified + in record key. if found, returns non-zero and places index of it + into index. If not, returns zero and places index, where to insert + record into index */ +int search(struct record *key,int *index) +{int l=0,h=count-1,i,c; + while(l<=h) + { i=(l+h)>>1; + c=compare((struct record *)(table+(tuple_size)*i),key); + if (c<0) l=i+1; + else + { h=i-1; + if (!c) { *index=i;return 1;} + } + } + *index=l; + return 0; +} +/* Inserts given record into table at position index. + Fills count field of inserted record by 1 + */ +void insert(struct record *key,int index) +{ int i;long int *l; + if (count==limit) + { + table=realloc(table,(limit+=delta)*(tuple_size)*sizeof(short int)); + if (!table) + { fprintf(stderr,"Couldn't realloc table. Table limit is %d\n",limit); + exit(1); + } + } + + for(i=count;i>index;i--) + memcpy(table+(i)*(tuple_size),table+(i-1)*(tuple_size), + (tuple_size)*sizeof(short int)); + l=(long int *)(table+index*(tuple_size)); + *l=1L; + memcpy(table+index*tuple_size+2,key->classes,files_count*sizeof(short int)); + count++; +} +/* + adds pixel into table, i.e. if record with such combination of classes + already exists, increments its count. Otherwise inserts new record. + */ +void add_pixel(struct record *key) +{int index;long int *l; + if (search(key,&index)) + { + l=((long int *)(table+index*(tuple_size))); + (*l)++; + } + else insert(key,index); +} + +void help() +{ printf("Usage: outtab [-%%] files\n"); + exit(0); +} + +/* + Processes cell - forms record and adds it to table + */ +void do_cell(int x,int y) + { int k; + struct record r; + unsigned short int *c=r.classes; + for(k=0;koffsite) return; + add_pixel(&r); + } + +/* + Prints table. + */ +void print_table() +{int i,j; + unsigned short *t; +for(i=0,t=table;iclasses[j]); + printf("%ld\n",((struct record *)t)->count); +} +} +/******************** main ***********************************/ +int main(int argc,char **argv) +{int i=1,j,k,rows; + int verbose=0; + if (!strcmp(argv[1],"-%")) {verbose=1;i++;} + for(j=0;i=32) + { fprintf(stderr,"To many files in command line, 32 max\n"); + exit(1); + } + files[j]=open_epp(argv[i]); + if (!files[j]) files[j]=open_epp(default_ext(argv[i],".epp")); + if (!files[j]) { fprintf(stderr,"Cannot open file %s\n",argv[i]); + exit(1); + } + if(j){ if(files[j]->fr!=files[0]->fr||files[j]->fc!=files[0]->fc|| + files[j]->lr!=files[0]->lr||files[j]->lc!=files[0]->lc) + {fprintf(stderr,"Size of file %s doesn't match.\n",argv[i]); + exit(1); + } + } + } + files_count=j; + if (files_count%2) { + tuple_size=(3+files_count); + } else { + tuple_size=(2+files_count); + } + table=malloc(65536*tuple_size*sizeof(short int)); + if (!table) { fprintf(stderr,"Not enough memory to allocate %d records\n",65536); + exit(1); + } + limit=65536; + delta=1024; + count=0; + rows=files[0]->lr-files[0]->fr; + install_progress_indicator(verbose?show_percent:check_int); + for(i=files[0]->fr,k=1;ilr;i++,k++) + { for(j=files[0]->fc;jlc;j++) + do_cell(j,i); + if (EndLineProc) if ((*EndLineProc)(j,k,rows)) break; + + } + if (verbose) {fprintf(stderr,"\r \rdone\n");} + print_table(); + free(table); + + for(i=0;i +# define __USE_BSD +# include +# include +# include +# include +# include +# include "outtable.h" +int + useOffsite=0, + areaInCells=0, + verbose=0; + int fileCount=0,/* total number of files in record*/ + funcCount=0,/* Number of functions to use */ + openCount=0,/* Number of distinct open files */ + baseFiles=-1;/* number of files which used to find combinations*/ +double zUnit=1.0, + zOffset=0.0, + cellArea=0.0; +char *baseFile=NULL, + delimiter=','; +EPP* fileinfo[MAX_OUTTABLE_FILES]; +EPP_LINK links[MAX_OUTTABLE_FILES]; +unsigned short int *table; +typedef struct record *rec; +int tuple_size, limit, delta, count; +struct FuncItem funcList[MAX_OUTTABLE_FILES]; +struct FileInfo openFiles[MAX_OUTTABLE_FILES]; + +void error(const char *format,...) +{ va_list ap; + va_start(ap,format); + vfprintf(stderr,format,ap); + va_end(format); + exit(1); +} +void help(void) +{ struct FuncInfo *f; + char sep=' '; + printf("Usage: outtable [-%%][-u][-c][-d char][-b file][-z value][-Z value] files.." + "-function file(s)...\n"); + printf("Where function are:\n"); + for(f=funcTable;f->func;f++){ + printf("%c-%s %s",sep,f->name,f->nargs==1?"file":"file file"); + sep=','; + } + printf("\n"); +} +void scanOpt(int *i,int argc, char **argv) +{ + /* parsing options */ + for (*i=1;*iname)&&f->func;f++); + if (f->func) return f; + else return NULL; +} + +void openFile(char *name) { +int i; +struct FileInfo *f; +char Name[1024]; +strcpy(Name,default_ext(name,".epp")); +for (i=0,f=openFiles;iname);i++,f++); + if (i<=openCount) { + fileinfo[fileCount++]=f->epp; + } else { + + f->epp=open_epp(Name); + f->name=strdup(Name); + openCount++; + if (!f->epp) { + error("Couldn't open file %s\n",name); + } + } +} + + +void parseArgs(int i, int argc, char **argv) { + struct FuncInfo *func; + int j; + while (ifunc; + funcList[funcCount].index=fileCount; + funcList[funcCount].data=malloc(func->datasize); + /* Note, that definition of combinations finished */ + if (baseFiles<0) baseFiles=fileCount; + for (j=0;jnargs;j++) { + if (i==argc) error("Not enough args for function -%s\n",func->name); + openFile(argv[i++]); + } + } else { + if (baseFiles>=0) + error("Files to define combinations should precede functions\n"); + openFile(argv[i++]); + } + } +} + +int compare(struct record *r1, struct record *r2) +{int i; + for (i=0;iclasses[i]>r2->classes[i]) return 1; + else + if (r1->classes[i]classes[i]) return -1; + } + return 0; + +} +/* Searches table for record which contains classes, specified + in record key. if found, returns non-zero and places index of it + into index. If not, returns zero and places index, where to insert + record into index */ +int search(struct record *key,int *index) +{int l=0,h=count-1,i,c; + while(l<=h) + { i=(l+h)>>1; + c=compare((struct record *)(table+(tuple_size)*i),key); + if (c<0) l=i+1; + else + { h=i-1; + if (!c) { *index=i;return 1;} + } + } + *index=l; + return 0; +} +/* Inserts given record into table at position index. + Fills count field of inserted record by 1 + */ +void insert(struct record *key,int index) +{ int i;long int *l; + if (count==limit) + { + table=realloc(table,(limit+=delta)*(tuple_size)*sizeof(short int)); + if (!table) + error("Couldn't realloc table. Table limit is %d\n",limit); + + } + + for(i=count;i>index;i--) + memcpy(table+(i)*(tuple_size),table+(i-1)*(tuple_size), + (tuple_size)*sizeof(short int)); + l=(long int *)(table+index*(tuple_size)); + *l=1L; + memcpy(table+index*tuple_size+2,key->classes,fileCount*sizeof(short int)); + count++; +} +/* + adds pixel into table, i.e. if record with such combination of classes + already exists, increments its count. Otherwise inserts new record. + */ +void add_pixel(struct record *key) +{int index;long int *l; + if (search(key,&index)) + { + l=((long int *)(table+index*(tuple_size))); + (*l)++; + } + else insert(key,index); +} + +/* + Processes cell - forms record and adds it to table + */ +void do_cell(int x,int y) +{ int k; + struct record r; + unsigned short int *c=r.classes; + for(k=0;koffsite&&!useOffsite) return; + } + add_pixel(&r); +} +/* + * Print combinations along with cell areas + * + */ + void print_table(void) +{ + int i,j; + unsigned short *t; + for(i=0,t=table;iclasses[j],delimiter); + if (areaInCells) + printf("%ld\n",((struct record *)t)->count); + else + printf("%0.8g\n",((struct record *)t)->count*cellArea); + } +} +/* + * Compute functions and print results + * + * + */ +void init_functions(void) +{ int i; + struct FuncItem *f; + for(i=0,f=funcList;ifunc(FuncInit,f->data,NULL,f->index); + } +} +void print_row(struct record *row) +{ int j; + struct FuncItem *f; + /* first, print away all things defining a combination */ + for(j=0;jclasses[j],delimiter); + /* second, compute all functions and print away results */ + for(j=0,f=funcList;jfunc(FuncResult,f->data,row,f->index), + j==funcCount-1?'\n':delimiter); +} + +void process_table(void) +{ int i,j; + unsigned short *t; + struct record *prev=NULL; + struct FuncItem *f; + /* reset all functions persistend data */ + init_functions(); + fileCount=baseFiles;/* for compare to compare only files, + defining combinations*/ + for(i=0,t=table;ifunc(FuncIterate,f->data,(struct record *)t,f->index); + } + prev=(struct record *)t; + } + print_row(prev); +} +/* + * main program + */ +int main(int argc, char **argv) +{int i,j,k,rows; + EPP *base; + scanOpt(&i, argc, argv); + parseArgs(i, argc, argv); + if (!openCount) { + error("No files specified\n"); + } + /* Find out base file */ + if (!baseFile) { + base=fileinfo[0]; + } else { + int saveCount=fileCount; + openFile(baseFile); + base=fileinfo[saveCount]; + fileCount=saveCount; + } + + /* Determine cell area */ + if (areaInCells) { + cellArea=1.0; + } else { + cellArea=base->cell_area; + } + /* establish coordinate links */ + for (i=0;ilr-base->fr; + install_progress_indicator(verbose?show_percent:check_int); + for(i=base->fr,k=1;base->lr;i++,k++) + { for(j=base->fc;jlc;j++) + do_cell(j,i); + if (EndLineProc) if ((*EndLineProc)(j,k,rows)) { + clear_progress(1); + exit(1); + } + + } + clear_progress(0); + if (funcCount) { + /* there are some functions. Process them */ + process_table(); + } else { + print_table(); + } + free(table); + for(i=0;i + +#define MAX_OUTTABLE_FILES 32 +/* This structure is used to keep information about + combination of classes. count is count of cells already found, + classes are classes. Really each of these structures occupies + less then sizeof(struct record) bytes, becouse count of files is + usially less than 32 */ +struct record { + long int count; + unsigned short int classes[MAX_OUTTABLE_FILES]; + }; +/* data which outtable functions need to keep between calls */ +typedef void* FuncData; + +/* Action which function should take */ +typedef enum { + FuncInit, /* Initialize FuncData */ + FuncIterate,/* Collect data from given record, return non-zero on failure */ + FuncResult /* Return computed value */ +} FuncAction; + +/* Type for all data processing functions */ +typedef double (*OuttableFunc)(FuncAction action,/* what to do */ + FuncData data, /* pointer to persistent data */ + struct record *record, /*record to process */ + int index); /* number of file in record to cope with */ + +/* Type for record in functuon-table */ + +struct FuncInfo { + char name[16]; /* how function is named in command-line */ + OuttableFunc func; /* actual function to perform operation */ + int nargs; /* number of file arguments */ + int datasize; /* How many bytes to allocate for FuncData */ +}; + +struct FuncItem { + OuttableFunc func; + FuncData data; + int index; + }; + +struct FileInfo { + char *name; + EPP *epp; + }; + +extern struct FileInfo openFiles[MAX_OUTTABLE_FILES]; +extern struct FuncInfo funcTable[]; +extern EPP* fileinfo[MAX_OUTTABLE_FILES]; +extern struct FuncItem funcList[MAX_OUTTABLE_FILES]; +extern double cellArea, zUnit, zOffset; +#endif diff --git a/epu/outtable_func.c b/epu/outtable_func.c new file mode 100644 index 0000000..f92872e --- /dev/null +++ b/epu/outtable_func.c @@ -0,0 +1,467 @@ +#include "outtable.h" +#include +#include +/* Data structures for functions */ +typedef struct n_info { + int count; + int value; + } n_info; +/* Sum of the all cells in combination */ +double OuttableSum(FuncAction action, FuncData data, struct record *record, + int index) +{ struct n_info *info=(struct n_info *)data; + switch (action) { + case FuncInit: + info->value=0; + info->count=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite) { + info->value+=record->classes[index]*record->count; + info->count+=record->count; + } + return 0; + case FuncResult: + return zUnit*info->value+zOffset*info->count; + + } + return 0; +} + +/* Count of the non-offsite cells for given file in combination */ +double OuttableCount(FuncAction action, FuncData data, struct record *record, + int index) +{ int *sum=(int *)data; + switch (action) { + case FuncInit: + *sum=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite) + *sum+=record->count; + return 0; + case FuncResult: + return *sum*cellArea; + + } + return 0; +} +/* Average of the all cells in combination */ +struct avg_info { + long sum; + int count; + }; +double OuttableAvg(FuncAction action, FuncData data, struct record *record, + int index) +{ struct avg_info *info=(struct avg_info *)data; + switch (action) { + case FuncInit: + info->sum=0; + info->count=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite) { + info->sum+=record->classes[index]*record->count; + info->count+=record->count; + } + return 0; + case FuncResult: + if (info->count) + return (zUnit*info->sum/info->count)+zOffset; + else return 0; + + } + return 0; +} +/* Minimal cell value in combination */ +double OuttableMin(FuncAction action, FuncData data, struct record *record, + int index) +{ int *min=(int *)data; + switch (action) { + case FuncInit: + *min=65536; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite && + record->classes[index]<*min) + *min=record->classes[index]; + return 0; + case FuncResult: + return *min*zUnit+zOffset; + + } + return 0; +} + +/* Count of cell with minimal value in combination */ +double OuttableNMin(FuncAction action, FuncData data, struct record *record, + int index) +{ struct n_info *info=(n_info *)data; + switch (action) { + case FuncInit: + info->value=65536; + info->count=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite && + record->classes[index]value) { + info->value=record->classes[index]; + info->count=record->count; + } + return 0; + case FuncResult: + return info->count*cellArea; + + } + return 0; +} + +/* Maximal cell value in combination */ +double OuttableMax(FuncAction action, FuncData data, struct record *record, + int index) +{ int *max=(int *)data; + switch (action) { + case FuncInit: + *max=-1; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite && + record->classes[index]>*max) + *max=record->classes[index]; + return 0; + case FuncResult: + return *max*zUnit+zOffset; + + } + return 0; +} + +/* Count of cell with maximal value in combination */ +double OuttableNMax(FuncAction action, FuncData data, struct record *record, + int index) +{ struct n_info *info=(n_info *)data; + switch (action) { + case FuncInit: + info->value=-1; + info->count=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite && + record->classes[index]>info->value) { + info->value=record->classes[index]; + info->count=record->count; + } + return 0; + case FuncResult: + return info->count*cellArea; + + } + return 0; +} +/* Count of cells with most frequent value in combination */ +double OuttableNMode(FuncAction action, FuncData data, struct record *record, + int index) +{ int *max=(int *)data; + switch (action) { + case FuncInit: + *max=-1; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite && + record->count>*max) + *max=record->count; + return 0; + case FuncResult: + return *max*cellArea; + + } + return 0; +} + +/* Most frequent cell value in combination */ +double OuttableMode(FuncAction action, FuncData data, struct record *record, + int index) +{ struct n_info *info=(n_info *)data; + switch (action) { + case FuncInit: + info->value=-1; + info->count=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite && + record->count>info->count) { + info->value=record->classes[index]; + info->count=record->count; + } + return 0; + case FuncResult: + return info->value*zUnit+zOffset; + + } + return 0; +} +/* Count of cells with rarest value in combination */ +double OuttableNFewest(FuncAction action, FuncData data, struct record *record, + int index) +{ int *min=(int *)data; + switch (action) { + case FuncInit: + *min=INT_MAX; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite && + record->count<*min) + *min=record->count; + return 0; + case FuncResult: + return *min*cellArea; + + } + return 0; +} + +/* Rarest cell value in combination */ +double OuttableFewest(FuncAction action, FuncData data, struct record *record, + int index) +{ struct n_info *info=(n_info *)data; + switch (action) { + case FuncInit: + info->value=0; + info->count=INT_MAX; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite && + record->countcount) { + info->value=record->classes[index]; + info->count=record->count; + } + return 0; + case FuncResult: + return info->value*zUnit+zOffset; + + } + return 0; +} +/* Range of classes in cell */ +typedef struct r_info { + int max,min; + } r_info; +double OuttableRange(FuncAction action, FuncData data, struct record *record, + int index) +{ struct r_info *info=(r_info *)data; + switch (action) { + case FuncInit: + info->max=0; + info->min=INT_MAX; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite) { + if (record->classes[index]min) + info->min=record->classes[index]; + if (record->classes[index]>info->max) + info->max=record->classes[index]; + } + return 0; + case FuncResult: + return (info->max-info->min)*zUnit; + + } + return 0; +} + +/* count of distinct classes. Note that function can be called more than once + for each distinct class (if there are more functions), so we need to + keep track on found classes in bit table */ +#define BIT_TABLE_LENGTH (8192/sizeof(int)) +struct c_info { + int found; + int bittable[BIT_TABLE_LENGTH]; + }; +double OuttableClasses(FuncAction action, FuncData data, struct record *record, + int index) +{ struct c_info *info=(struct c_info*) data; + int i,mask; + switch (action) { + case FuncInit: + info->found=0; + for (i=0;ibittable[i]=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite) { + i=record->classes[index]/(sizeof(int)*8); + mask=1<classes[index]%(sizeof(int)*8); + if (!(info->bittable[i]&mask)) { + info->found++; + info->bittable[i]|=mask; + } + } + return 0; + case FuncResult: + return info->found; + + } + return 0; +} +/* Bitwise OR of all values. Why Pete Olson was so proud of this + function adding it in EPPL ver 2.1? */ +double OuttableOr(FuncAction action, FuncData data, struct record *record, + int index) +{ int *res=(int *)data; + switch (action) { + case FuncInit: + *res=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite) + *res|=record->classes[index]; + return 0; + case FuncResult: + return *res; + + } + return 0; +} + +/* Bitwise And of all values in combination */ +double OuttableAnd(FuncAction action, FuncData data, struct record *record, + int index) +{ int *res=(int *)data; + switch (action) { + case FuncInit: + *res=65535; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite) + *res&=record->classes[index]; + return 0; + case FuncResult: + return *res; + + } + return 0; +} + +/* Standard deviation of all values in combination, biased */ +struct var_info { + double sum; + double sumsq; + int count; + }; +double OuttableStd(FuncAction action, FuncData data, struct record *record, + int index) +{ struct var_info *info=(struct var_info *)data; + switch (action) { + case FuncInit: + info->count=0; + info->sum=0; + info->sumsq=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite) { + info->count +=record->count; + info->sum +=record->count*record->classes[index]; + info->sumsq +=record->count*record->classes[index]*record-> + classes[index]; + } + return 0; + case FuncResult: + if (info->count<2) return 0; + return sqrt((info->sumsq-(info->sum*info->sum/info->count))/ + (info->count))*zUnit; + + } + return 0; +} +/*Variance of cell values, biased*/ +double OuttableVar(FuncAction action, FuncData data, struct record *record, + int index) +{ struct var_info *info=(struct var_info *)data; + switch (action) { + case FuncInit: + info->count=0; + info->sum=0; + info->sumsq=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite) { + info->count +=record->count; + info->sum +=record->count*record->classes[index]; + info->sumsq +=record->count*record->classes[index]*record-> + classes[index]; + } + return 0; + case FuncResult: + if (info->count<2) return 0; + return ((info->sumsq-(info->sum*info->sum/info->count))/ + (info->count-1))*zUnit*zUnit; + + } + return 0; +} + +/* correlation of cell values in files index and index+1, multiplied by 100 */ +typedef struct cov_info { + double sumx; + double sumy; + double sumxy; + double sumxsq; + double sumysq; + int count; + } cov_info; +double OuttableCorr(FuncAction action, FuncData data, struct record *record, + int index) +{ struct cov_info *info=(struct cov_info *)data; + switch (action) { + case FuncInit: + info->count=0; + info->sumx=0; + info->sumxsq=0; + info->sumy=0; + info->sumysq=0; + info->sumxy=0; + return 0; + case FuncIterate: + if (record->classes[index]!=fileinfo[index]->offsite&& + record->classes[index+1]!=fileinfo[index+1]->offsite) { + info->count +=record->count; + info->sumx +=record->count*record->classes[index]; + info->sumxsq +=record->count*record->classes[index]*record-> + classes[index]; + info->sumy +=record->count*record->classes[index+1]; + info->sumysq +=record->count*record->classes[index+1]*record-> + classes[index+1]; + info->sumxy +=record->count*record->classes[index]* + record->classes[index+1]; + } + return 0; + case FuncResult: + if (info->count<2) return 0; + return (info->sumxy-(info->sumx*info->sumy/info->count))/ + sqrt((info->sumxsq-(info->sumx*info->sumx/info->count))* + (info->sumysq-(info->sumy*info->sumy/info->count))); + + } + return 0; +} + +struct FuncInfo funcTable[]={ +{"sum",OuttableSum,1,sizeof(int)}, +{"cnt",OuttableCount,1,sizeof(int)}, +{"avg",OuttableAvg,1,sizeof(struct avg_info)}, +{"min",OuttableMin,1,sizeof(int)}, +{"nmin",OuttableNMin,1,sizeof(struct n_info)}, +{"max",OuttableMax,1,sizeof(int)}, +{"nmax",OuttableNMax,1,sizeof(struct n_info)}, +{"mode",OuttableMode,1,sizeof(struct n_info)}, +{"nmode",OuttableNMode,1,sizeof(int)}, +{"fewest",OuttableFewest,1,sizeof(struct n_info)}, +{"nfewest",OuttableNFewest,1,sizeof(int)}, +{"range",OuttableRange,1,sizeof(struct r_info)}, +{"classes",OuttableClasses,1,sizeof(struct c_info)}, +{"or",OuttableOr,1,sizeof(int)}, +{"and",OuttableAnd,1,sizeof(int)}, +{"std",OuttableStd,1,sizeof(struct var_info)}, +{"var",OuttableVar,1,sizeof(struct var_info)}, +{"corr",OuttableCorr,2,sizeof(struct cov_info)}, +{"",NULL,0,0}, +}; diff --git a/epu/points.tab b/epu/points.tab new file mode 100644 index 0000000..9b5fe55 --- /dev/null +++ b/epu/points.tab @@ -0,0 +1,262 @@ + 1, 456.8, 0.2 + 2, 1865.6, 1127.4 + 3, 1951.6, 1298.6 + 4, 1784, 1268.6 + 5, 1928.4, 1276.2 + 6, 1892.8, 1268.2 + 7, 1980, 1268.2 + 8, 1980.8, 1267.8 + 9, 1887.2, 1264.2 + 10, 1983.6, 1266.6 + 11, 961.2, 1242.6 + 12, 976, 1229 + 13, 980.8, 1236.2 + 14, 1028, 1228.2 + 15, 1015.2, 1221.4 + 16, 1020.4, 1223.8 + 17, 1006, 1212.6 + 18, 966.8, 1220.2 + 19, 998.4, 1217.8 + 20, 1008.8, 1218.6 + 21, 1023.6, 1217.4 + 22, 1015.6, 1217 + 23, 1044.8, 1213.4 + 24, 990.4, 1213.8 + 25, 967.2, 1213.4 + 26, 982.4, 1211.4 + 27, 1002.4, 1210.2 + 28, 1016, 1212.2 + 29, 1016.8, 1210.6 + 30, 1025.6, 1204.2 + 31, 990.8, 1205 + 32, 1003.2, 1198.2 + 33, 995.2, 1198.6 + 34, 1018.8, 1195.8 + 35, 1040.4, 1191.8 + 36, 998, 1197.4 + 37, 1792.4, 1187.4 + 38, 1004.8, 1185.4 + 39, 1978.4, 1167.8 + 40, 1990.4, 1167.4 + 41, 1990, 1167 + 42, 1928, 1165 + 43, 1111.2, 1160.2 + 44, 1926.4, 1159.8 + 45, 632.8, 1087.4 + 46, 1168.8, 1153.8 + 47, 1188.8, 1135.8 + 48, 1772, 1149 + 49, 1987.6, 1145 + 50, 1988, 1143.8 + 51, 1983.6, 1141.4 + 52, 656, 1138.6 + 53, 1172, 1132.2 + 54, 1179.2, 1129.4 + 55, 1174.4, 1119.4 + 56, 1197.2, 1103 + 57, 1178, 1123 + 58, 1554.8, 1112.2 + 59, 501.6, 1013 + 60, 1203.6, 1117.4 + 61, 1202.4, 1115 + 62, 1200.8, 1113 + 63, 1176.8, 1111 + 64, 1176.8, 1107.8 + 65, 1233.2, 1080.6 + 66, 1486.8, 1074.6 + 67, 1952, 1023 + 68, 1210, 1100.2 + 69, 1519.6, 755.8 + 70, 228, 1064.2 + 71, 840, 1032.2 + 72, 1230.4, 1090.6 + 73, 1230, 1089.8 + 74, 219.2, 1083.8 + 75, 232, 1082.6 + 76, 1739.6, 1078.6 + 77, 590, 1077 + 78, 1995.6, 1075.8 + 79, 1254.8, 1074.2 + 80, 887.2, 1073.4 + 81, 1260, 1071 + 82, 891.6, 1071.8 + 83, 1465.2, 1064.2 + 84, 1180.8, 913.8 + 85, 870.4, 1057 + 86, 891.2, 1057.4 + 87, 891.6, 1057 + 88, 1516.4, 1051 + 89, 582, 1054.2 + 90, 444, 977 + 91, 1531.6, 1044.6 + 92, 668.8, 1051.8 + 93, 667.6, 1050.6 + 94, 1145.6, 1049.8 + 95, 878, 1047.8 + 96, 1140.4, 1045.8 + 97, 416.8, 1045.4 + 98, 416.4, 1045 + 99, 874, 1042.6 + 100, 869.2, 1041.4 + 101, 1189.6, 1039.4 + 102, 1252.8, 1041.4 + 103, 870, 1041 + 104, 1575.6, 1032.6 + 105, 1588.8, 1025.8 + 106, 445.2, 1014.2 + 107, 337.6, 989.4 + 108, 1524, 1032.2 + 109, 1485.2, 1029.8 + 110, 788.8, 921.8 + 111, 573.2, 936.6 + 112, 2006.4, 1025.4 + 113, 1818, 861 + 114, 828.8, 1020.2 + 115, 1082.8, 1011 + 116, 1305.2, 1011.8 + 117, 1172, 1009.4 + 118, 753.2, 999.4 + 119, 1184.8, 1008.2 + 120, 1921.2, 1007.8 + 121, 582, 1006.6 + 122, 1183.6, 1006.6 + 123, 579.2, 1005.4 + 124, 386.4, 971.8 + 125, 978.4, 985.4 + 126, 832.8, 986.6 + 127, 1110.4, 983.4 + 128, 647.2, 982.2 + 129, 966, 749.4 + 130, 1430.4, 981 + 131, 363.2, 979.8 + 132, 1019.6, 975 + 133, 1312.4, 971.4 + 134, 470.4, 930.2 + 135, 1542.8, 969.4 + 136, 846.4, 961.4 + 137, 1005.6, 966.2 + 138, 400.4, 911.4 + 139, 1022, 964.6 + 140, 782, 964.2 + 141, 783.6, 963.8 + 142, 1115.6, 963.8 + 143, 1454, 963.8 + 144, 1365.2, 960.6 + 145, 1515.2, 960.2 + 146, 1516.8, 958.6 + 147, 1041.6, 949 + 148, 313.2, 915.8 + 149, 1026.4, 942.2 + 150, 1992, 941 + 151, 696.8, 841 + 152, 1488.8, 933.4 + 153, 2123.2, 919.4 + 154, 2116, 915.8 + 155, 442.4, 882.6 + 156, 2092.4, 903.4 + 157, 282, 870.6 + 158, 379.6, 868.6 + 159, 2032, 786.6 + 160, 319.6, 869.4 + 161, 492.4, 841.8 + 162, 415.6, 823 + 163, 447.6, 833.4 + 164, 339.6, 831.4 + 165, 302, 835.4 + 166, 550.4, 777.4 + 167, 271.2, 821 + 168, 804.4, 717.4 + 169, 1196.8, 724.2 + 170, 888.8, 822.6 + 171, 379.2, 801.8 + 172, 358.8, 824.2 + 173, 446, 782.2 + 174, 1112.8, 478.2 + 175, 1832.4, 475.4 + 176, 325.2, 791.8 + 177, 272, 780.6 + 178, 992.4, 807.8 + 179, 626.8, 756.2 + 180, 304.8, 750.6 + 181, 353.2, 755 + 182, 408.4, 769 + 183, 503.2, 756.6 + 184, 615.6, 704.2 + 185, 1838.4, 783.8 + 186, 406, 720.2 + 187, 697.2, 663 + 188, 474.8, 751.4 + 189, 569.2, 722.2 + 190, 505.6, 717 + 191, 444.4, 712.6 + 192, 402, 661.4 + 193, 2057.2, 733 + 194, 320, 671 + 195, 236, 669.8 + 196, 183.2, 669.4 + 197, 204.4, 703.8 + 198, 2094.4, 682.2 + 199, 141.6, 698.6 + 200, 142, 698.2 + 201, 2091.6, 695.8 + 202, 462.4, 662.2 + 203, 1284, 463 + 204, 550.4, 635.4 + 205, 436.8, 685.4 + 206, 437.6, 685.4 + 207, 170.8, 639.4 + 208, 492, 614.2 + 209, 2100, 654.2 + 210, 758, 597.8 + 211, 212.8, 604.2 + 212, 638.4, 610.6 + 213, 266.8, 591 + 214, 958.4, 557.4 + 215, 302.4, 558.6 + 216, 151.2, 635.4 + 217, 2105.2, 633.4 + 218, 2106.4, 631 + 219, 683.2, 580.2 + 220, 1936.4, 521.8 + 221, 165.6, 595.4 + 222, 804.8, 520.6 + 223, 1867.6, 606.2 + 224, 1879.6, 599.8 + 225, 1880.8, 598.6 + 226, 1882, 598.6 + 227, 2111.6, 598.2 + 228, 2112.8, 597 + 229, 181.6, 568.6 + 230, 2113.2, 575.4 + 231, 1850.8, 572.6 + 232, 1689.2, 458.6 + 233, 1910, 565 + 234, 213.6, 491 + 235, 1708.8, 559.8 + 236, 188.8, 542.6 + 237, 1501.6, 401.8 + 238, 212.4, 530.2 + 239, 889.6, 483.4 + 240, 281.6, 543.8 + 241, 2104.8, 519 + 242, 1412.4, 445 + 243, 244.4, 509.4 + 244, 2090.4, 478.6 + 245, 1010, 455.8 + 246, 783.2, 483.4 + 247, 1340.4, 377.8 + 248, 1056.8, 391 + 249, 947.6, 387 + 250, 2076, 438.6 + 251, 2003.6, 441 + 252, 1877.2, 347 + 253, 2095.6, 434.6 + 254, 1785.2, 381.8 + 255, 1278.8, 381 + 256, 1143.6, 336.6 + 257, 986, 333 + 258, 1018, 362.2 + 259, 1468.4, 339 + 260, 1288.8, 349 + 261, 1290.8, 346.2 + 262, 1024, 344.6 diff --git a/epu/project b/epu/project new file mode 100755 index 0000000000000000000000000000000000000000..efd5d60d5b3ba9f49f1a213d9fc6054d533ff5e6 GIT binary patch literal 237951 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 z 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 z32 +#include +#include +#include +#include +#include +#include +#include +#include +PJ *in_proj=NULL,*out_proj=NULL; +int positive_west=0;/* Whether to adjust west hemisphere coords to range + 180-360 from range -180-0 */ +EPP *infile,*outfile; +/* This function does perform actual projection conversion + It computes long/lat data from current cell and then computes + cell on input map to get value from */ +int project_cell(int col, int row, int value) { + UV out,ll,in; + int in_row,in_col; + out.u=alt_xc(outfile,col); + out.v=alt_yc(outfile,row); + if (out_proj) { + ll=pj_inv(out,out_proj); + } else { + if (positive_west&&out.u>180) { + out.u-=360.0; + } + ll.u=out.u*DEG_TO_RAD; + ll.v=out.v*DEG_TO_RAD; + + } + if (ll.u == HUGE_VAL || ll.v == HUGE_VAL) { + return value; + } + if (in_proj) { + in=pj_fwd(ll,in_proj); + } else { + in.u=ll.u*RAD_TO_DEG; + if (positive_west && in.u<0) { + in.u+=360.0; + } + in.v=ll.v*RAD_TO_DEG; + } + in_row=epp_row(infile,in.v); + in_col=epp_col(infile,in.u); + return epp_get(infile,in_col,in_row); +} + +void help(exitcode) { + printf("Usage: project [-%%] {-b basefile|-c cellsize -l xl,yb,xr,yt} [-i source_proj]\n\t" + "[-p target_proj] -o outfile -O offsite {-r rows_to_cache|-x [tmpdir]} file\n" + "Projection definition can be either file name or list of comma separated\n" + "name=value pairs. If either input or output projection omitted, it is assumed\n" + "to be geographic coords\n"); + exit(exitcode); +} +PJ* get_projection(const char *source); +void expand_epp(EPP *epp,const char *tempdir,int verbose); +void check_hemisphere(EPP *epp); +int main(int argc,char **argv) { +struct option long_options[]={ + {"help",0,0,1}, + {"version",0,0,2}, + {"verbose",0,0,'%'}, + {"base-file",1,0,'b'}, + {"cell-size",1,0,'c'}, + {"source-projection",1,0,'i'}, + {"output-file",1,0,'o'}, + {"target-projection",1,0,'p'}, + {"offsite",1,0,'O'}, + {"cache-rows",1,0,'r'}, + {"expand",2,0,'x'}, + {"limits",1,0,'l'} + }; +char outname[1024]="project.out.epp"; +char tmpdir[1024]="/tmp"; +char *basefilename=NULL,*errptr; +int limits_flag=0,result,offsite_flag=0,offsite=0,cache_size=0,expand_flag=0; +double xright=0,xleft=0,ybottom=0,ytop=0,cellsize = 0; +int c,index,verbose=0; + while ((c=getopt_long(argc,argv,"c:i:o:p:O:r:x::l:b:%",long_options,&index)) + !=-1) { + switch (c) { + case 2: show_version("project","$Revision: 1.1 $"); + case '%': verbose = 1; break; + case 'b' : if (cellsize !=0 || limits_flag) { + fprintf(stderr,"basefile cannot be combined with" + "explicit coordinate parameters\n"); + exit(1); + } + if (basefilename) { + fprintf(stderr,"Duplicate basefile specification\n"); + exit(1); + } + basefilename=strdup(default_ext(optarg,".epp")); + break; + case 'c' : if (basefilename) { + fprintf(stderr,"cannot use cell size and" + "basefile at the same time\n"); + exit(1); + } + cellsize=strtod(optarg,&errptr); + if (*errptr || cellsize<=0) { + fprintf(stderr,"invalid cellsize %s\n",optarg); + exit(1); + } + break; + case 'i' : in_proj=get_projection(optarg); + if (!in_proj) exit(1); + break; + case 'l' : if (basefilename) { + fprintf(stderr,"Cannot use both basefile" + "and limits\n"); + exit(1); + } + if (limits_flag) { + fprintf(stderr,"Duplicate limit specification\n"); + exit(1); + } + xleft = strtod(optarg,&errptr); + while (strchr(",;\n \t",*errptr)) errptr++; + if (!*errptr) { + fprintf(stderr,"Invalid limits"); + exit(1); + } + ybottom = strtod(errptr,&errptr); + while (strchr(",;\n \t",*errptr)) errptr++; + if (!*errptr) { + fprintf(stderr,"Invalid limits"); + exit(1); + } + xright = strtod(errptr,&errptr); + while (strchr(",;\n \t",*errptr)) errptr++; + if (!*errptr) { + fprintf(stderr,"Invalid limits"); + exit(1); + } + ytop = strtod(errptr,&errptr); + if (*errptr) { + fprintf(stderr,"Invalid limits"); + exit(1); + } + limits_flag=1; + break; + case 'p' : out_proj=get_projection(optarg); + if (!out_proj) exit(1); + if (!out_proj->inv) { + fprintf (stderr,"Cannot project - inverse " + "transformation for output projection" + "unavailable\n"); + exit(1); + } + break; + case 'o' : strncpy(outname,default_ext(optarg,".epp"),1023); + outname[1023]=0; + break; + case 'O' : offsite = strtol(optarg,&errptr,0); + if (*errptr || offsite<0 || offsite>65535) { + fprintf(stderr,"Invalid offsite value %s\n",optarg); + exit(1); + } + offsite_flag=1; + break; + case 'r' : cache_size = strtol(optarg,&errptr,0); + if (*errptr || cache_size<0 || cache_size>30000) { + fprintf(stderr,"Invalid cache size:%s\n",optarg); + exit(1); + } + break; + case 'x' : expand_flag=1; + if (optarg) { + strncpy(tmpdir,optarg,1023); + tmpdir[1023]=0; + } + break; + default: { + help(c==1?0:1); + } + } + } + if (cache_size && expand_flag) { + fprintf(stderr,"cannot use cache and expanding to temp dir" + "simulateously\n"); + exit(1); + } + if (!in_proj) { + if (!out_proj) { + fprintf(stderr,"Neither input nor output projection specified\n"); + exit(1); + } else { + fprintf(stderr,"input projection is not specified, assuming latlong\n"); + } + } else if (!out_proj) { + fprintf(stderr,"Output projection is not specified, assuming latlong\n"); + } + if (optind>=argc) { + fprintf(stderr,"No input file specified\n"); + exit(1); + } + + infile=open_epp(default_ext(argv[optind],".epp")); + if (!infile) { + perror("open input file"); + exit(2); + } + if (!in_proj) { + check_hemisphere(infile); + } + if (cache_size) { + set_epp_cache(infile,cache_size); + } + if (!offsite_flag) { + offsite = infile->offsite; + } + Create16bit=infile->kind==16; + if (basefilename) { + EPP *basefile; + basefile=open_epp(basefilename); + if (!basefile) { + perror("open base file"); + exit(2); + } + outfile=creat_epp_as(outname,basefile); + if (!outfile) { + perror("opening output file\n"); + exit(1); + } + outfile->offsite=offsite; + close_epp(basefile); + } else { + int rows;int cols; + if (!limits_flag || cellsize==0) { + fprintf(stderr,"output file geometry is not specified\n"); + exit(2); + } + rows=ceil(fabs(ytop-ybottom)/cellsize); + cols=ceil(fabs(xright-xleft)/cellsize); + if (ybottomrow=malloc(1); + munmap(infile->cache,infile->width*(infile->lr-infile->fr)* + sizeof(unsigned short)); + close(infile->cache_size); + } + close_epp(infile); + return(0); +} + +PJ* get_projection(const char *source) { + char *work_area,*token,**args; + int argc,limit=16; + PJ *pj; + if (!strchr(source,'=')) { + FILE *f=fopen(default_ext(source,".prj"),"r"); + int size; + if (!f) { + perror(default_ext(source,".prj")); + exit(2); + } + fseek(f,0,SEEK_END); + size = ftell(f); + fseek(f,0,SEEK_SET); + work_area=malloc(size+1); + if(fread(work_area,1,size,f)!=size) { + perror(default_ext(source,"prj")); + exit(2); + } + work_area[size]=0; + fclose(f); + } else { + work_area = strdup(source); + } + args=calloc(limit,sizeof(char *)); + argc=0; + token=strtok(work_area,",;\n \r\t"); + do { + args[argc++]=token; + if (argc>=limit) { + args=realloc(args,(limit+=16)*(sizeof(char *))); + } + } while ((token = strtok(NULL,",;\n \r\t"))); + pj = pj_init(argc,args); + free(work_area); + free(args); + if (!pj) { fprintf(stderr,"Invalid projection definition: %s\n", + source); + exit(2); + } + return pj; + } + void position_mmap(EPP *epp,int row) { + epp->row=((unsigned short*) epp->cache)+(epp->width)*(row-epp->fr); + epp->currentline=row; +} +void expand_epp(EPP *epp,const char* tmpdir, int verbose) { + int fd,i,k,n,row_size; + char tempname[1048]="/tmp"; + if (tmpdir && *tmpdir) { + strcpy(tempname,tmpdir); + } + strcat(tempname,"/eppXXXXXX"); + /* We use mkstemp rather than POSIX tmpfile here, becouse we need + * to have control over place where file is created. I don't expect + * that everybody have few gigabytes free in /tmp for unpacking large + * map + */ + fd=mkstemp(tempname); + unlink(tempname); + /*file has mode 0666, so it is better to not show it to anyone*/ + if (verbose) { + fprintf(stderr,"unpacking...\n"); + install_progress_indicator(show_percent); + } else { + install_progress_indicator(check_int); + } + n=epp->lr - epp->fr; + row_size=epp->width*sizeof(unsigned short); + for (i=epp->fr,k=1;ilr;i++,k++) { + epp_get(epp,epp->fc,i); + if (write(fd,epp->row,row_size)!=row_size) { + fprintf(stderr,"Not enough space for temporary file\n"); + exit(2); + } + if(EndLineProc(i,k,n)) { + clear_progress(1); + exit(2); + } + } + clear_progress(0); + free(epp->row); + lseek(fd,0,SEEK_SET); + epp->cache=mmap(NULL,row_size*n,PROT_READ,MAP_SHARED,fd,0); + if (epp->cache==MAP_FAILED) { + perror("mmap"); + exit(2); + } + epp->position=position_mmap; + infile->cache_size=fd; +} + +void check_hemisphere(EPP *epp) { + if (epp->XLeft>=0 && epp->XRight>=180) { + fprintf(stderr,"Western hemisphere coords would be adjusted\n"); + positive_west=1; + } +} diff --git a/epu/reclass1.c b/epu/reclass1.c new file mode 100644 index 0000000..d344e7d --- /dev/null +++ b/epu/reclass1.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include "epp.h" +#include "eppl_ut.h" +#include "reclass.h" +#define required_argument 1 + FILE *input_stream; + short int *table; + EPP *infile; +int reclass_getc() +{ return fgetc(input_stream); +} +int get_cell(int col,int row,int value) +{ return table[epp_get(infile,col,row)]; +} +int main(int argc,char **argv) +{ char outname[256]="reclass.out.epp"; + char filename[256]; + + struct option long_options[]={ + {"help",0,0,1}, + {"version",0,0,2}, + {"verbose",0,0,'%'}, + {"file",required_argument,0,'f'}, + {"output-file",required_argument,0,'o'}, + {NULL,0,0,0} }; + int c; + int index,verbose=0; + EPP *outfile; + input_stream=stdin; + + while ((c=getopt_long(argc,argv,"%f:o:",long_options,&index))!=-1) + { switch(c) + { case 2:/* version */show_version("reclass","$Revision: 1.1 $"); + case '%':verbose=1;break; + case 'o':strcpy(outname,default_ext(optarg,".epp")); + case 'f':if((input_stream=fopen(optarg,"r"))==NULL) + {fprintf(stderr,"Cannot open reclass file %s\n",optarg); + return 1; + } else break; + case 1:/*help*/ + case '?': + default: + printf("Usage %s [--help] [--version] [-v] [-f reclass_file]\n" + "[-o output_file] file_to_reclass\n",argv[0]); + return c==1?0:2; + } + } + if (argc==optind) + { fprintf(stderr,"No input files specified\n"); + return 2; + } + if (argc>=optind+2) + { fprintf(stderr,"Too many input files\n"); + return 2; + } + + infile=open_epp(default_ext(argv[optind],".epp")); + if (!infile) { fprintf(stderr,"Cannot open input file\n"); + return 1; + } + Create16bit=1; + outfile=creat_epp_as(outname,infile); + if (!outfile){ fprintf(stderr,"Cannot create output file\n"); + return 1; + } + if (input_stream==stdin&&isatty(0)) + { + printf("Enter reclass statements. Press ^D to end.\n"); + interactive_parser=1; + } + /* init reclass table */ + if (!(table=make_reclass_table(infile,reclass_getc))) + { unlink(outname);return 1;} + if (table[infile->offsite]!=infile->offsite) + outfile->offsite=table[infile->offsite]; + install_progress_indicator(verbose?show_percent:check_int); + for_each_cell(outfile,get_cell); + + close_epp(infile); + if (outfile->max<255){ + fast_convert_to_8bit(outfile,strcat(strcpy(filename,outname),".8bit")); + unlink(outname); + rename(filename,outname); + } + else + close_epp(outfile); + clear_progress(0); + return 0; +} diff --git a/epu/tag2epp.c b/epu/tag2epp.c new file mode 100644 index 0000000..ee7caf9 --- /dev/null +++ b/epu/tag2epp.c @@ -0,0 +1,32 @@ +/* + * converts tag file to epp file + */ + + + + + +int main(int argc,char **argv) +{char output_file[1024]="clip.out.epp"; + struct option long_options[]= +{ + {"help",0,0,1}, + {"version",0,0,2}, + {"linear",0,0,'l'}, /* óÞÉÔÁÔØ, ÞÔÏ ÔÜÇ ÓÕÔØ ×ÅÝÅÓÔ×ÅÎÎÏÅ ÞÉÓÌÏ É ÉÓÐÏÌØÚÏ×ÁÔØ + ÌÉÎÅÊÎÕÀ ÆÕÎËÃÉÀ ÄÌÑ ÐÒÅÏÂÒÁÚÏ×ÁÎÉÑ ÅÇÏ × ËÌÁÓÓ */ + {"max",1,0,'x'}, /* ÚÁÄÁÔØ ÍÁËÓÉÍÁÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÔÅËÓÔÁ ÔÜÇÁ Ñ×ÎÏ*/ + {"min",1,0,'m'}, /* ÚÁÄÁÔØ ÍÉÎÉÍÁÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÔÅËÓÔÁ ÔÜÇÁ Ñ×ÎÏ*/ + {"range",1,0,'r'}, /* õËÁÚÁÔØ ËÏÌÉÞÅÓÔ×Ï ËÌÁÓÓÏ×, ËÏÔÏÒÏÅ ÚÁÄÅÊÓÔ×Ï×ÁÔØ*/ + {"8-but",0,0,'8'}, /* ÜË×É×ÁÌÅÎÔ --range=255 */ + {"offsite",1,0,'O'}. /* ÚÁÄÁÔØ offsite. ðÏ ÕÍÏÌÞÁÎÉÀ 0 */ + {"base",1,0,'b'}, /*æÁÊÌ, ÏÔËÕÄÁ ÓÌÉÚÁÔØ ËÏÏÒÄÉÎÁÔÎÕÀ ÓÉÓÔÅÍÕ É ÒÁÚÍÅÒ ÑÞÅÊËÉ*/ + {"direct",0,0,'D'}, /*óÞÉÔÁÔØ ÞÔÏ ÔÅËÓÔ ÔÜÇÁ ÃÅÌÏÅ ÞÉÓÌÏ É ÐÉÓÁÔØ ÅÇÏ × ÆÁÊÌ*/ + {"delimiter",1,0,d}, /* òÁÚÄÅÌÉÔÅÌØ ÐÏÌÅÊ ×Ï ×ÈÏÄÎÏÍ ÆÁÊÌÅ*/ + {"verbose",0,0,'%'}, + {"cell-size",1,0,'c'} /* òÁÚÍÅÒ ÑÞÅÊËÉ. ïÞÅÎØ ÐÏÌÅÚÅÎ, ÅÓÌÉ -b ÎÅ ÚÁÄÁÎ */ + {"output-file",1,0,'o'}, + {NULL,0,0,0}}; + int index,c;char *endptr; + int x1=32767,y1=32767,x2=-32767,y2=-32767, + result,verbose=0; + while ((c=getopt_long(argc,argv,"m:%o:",long_options,&index))!=-1) diff --git a/epu/window.c b/epu/window.c new file mode 100644 index 0000000..e544139 --- /dev/null +++ b/epu/window.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include "epp.h" +#include "eppl_ut.h" +EPP *old,*new; +int recalc=0; +int copy_cell(int col,int row,int value) +{ return epp_get(old,col,row); +} +void help(int exitcode) +{ printf("Usage window [-a%%] input_file fr lr fc lc [output_file]\n" + "coordinates are given in rows/cols unless -a option specified\n"); + exit(exitcode); +} +void error(char *msg) +{ fprintf(stderr,"%s\n",msg); + exit(1); +} +int get_coord_alt(char *param,int (*convert)(EPP *,double)) +{ double tmp; + char *endptr; + tmp=strtod(param,&endptr); + if (*endptr) error("Invalid coordinate"); + return convert(old,tmp); +} +int get_coord_int(char *param,int (*convert)(EPP *,double)) +{ int tmp; + char *endptr; + tmp=strtol(param,&endptr,0); + if (*endptr) error("Invalid coordinate"); + return tmp; +} + +int main(int argc,char **argv) +{char outname[1024]="window.out.epp"; + int (*get_coord)(char *,int (*)(EPP *,double))=get_coord_int; + int x1,y1,x2,y2; + int c,index,nonopt=1,verbose=0,result; + for(index=1;index=y2) error("Negative number of rows"); + if (!recalc) x2++; + if (x1>=x2) error("Negative number of columns"); + Create16bit=old->kind==16; + if(!(new=creat_epp(outname,x1,y1,x2-1,y2-1, + alt_x(old,x1),alt_y(old,y1),alt_x(old,x2),alt_y(old,y2), + 100,0,old->offsite))) error("Cannot create output file"); + install_progress_indicator(verbose?show_percent:check_int); + result=clear_progress(for_each_cell(new,copy_cell)); + close_epp(old); + + close_epp(new); + if (result) unlink(outname); + return -result; +} diff --git a/fgis.rc b/fgis.rc new file mode 100644 index 0000000..d432c19 --- /dev/null +++ b/fgis.rc @@ -0,0 +1,30 @@ +lappend auto_path $fGIS_HOME/tcl +array set fgis_font { +1 -cronyx-times-medium-r-normal--10-100-75-75-p-54-koi8-r +1b -cronyx-times-bold-r-normal--10-100-75-75-p-54-koi8-r +2 -cronyx-times-medium-r-normal--12-120-75-75-p-64-koi8-r +2b -cronyx-times-bold-r-normal--12-120-75-75-p-64-koi8-r +3 -cronyx-times-medium-r-normal--14-100-100-100-p-54-koi8-r +3b -cronyx-times-bold-r-normal--14-100-100-100-p-54-koi8-r +4 -cronyx-times-medium-r-normal--18-180-75-75-p-94-koi8-r +4b -cronyx-times-bold-r-normal--18-180-75-75-p-94-koi8-r +} +array set fgis_fontmap [list \ +$fgis_font(1) {Times-Roman 10}\ +$fgis_font(2) {Times-Roman 12}\ +$fgis_font(3) {Times-Roman 14}\ +$fgis_font(4) {Times-Roman 18}\ +$fgis_font(1b) {Times-Bold 10}\ +$fgis_font(2b) {Times-Bold 12}\ +$fgis_font(3b) {Times-Bold 14}\ +$fgis_font(4b) {Times-Bold 18}] +array set fgis { +printer lp +printcmd /usr/bin/lpr +orient n +print_colormode color +shift_factor 0.75 +undefined_legend "Not defined" +coordformat "X=%0.8g Y=%0.8g" +} +if [file exists ~/.fgisrc] {source ~/.fgisrc} diff --git a/include/Makefile b/include/Makefile new file mode 100644 index 0000000..2539d3c --- /dev/null +++ b/include/Makefile @@ -0,0 +1,14 @@ +RCS/%,v : % + ci -u $< +SRC=\ +RCS/clr.h,v\ +RCS/defpal.h,v\ +RCS/dgt.h,v\ +RCS/epp.h,v\ +RCS/epp_err.h,v\ +RCS/eppl.h,v\ +RCS/eppl_ut.h,v\ +RCS/reclass.h,v + +rcs: ${SRC} + diff --git a/include/clr.h b/include/clr.h new file mode 100644 index 0000000..a0ee660 --- /dev/null +++ b/include/clr.h @@ -0,0 +1,6 @@ + +typedef int *PALETTE; +PALETTE default_palette; +PALETTE read_palette(FILE *f); +char *ppm_pixel(PALETTE palette,int index); + diff --git a/include/defpal.h b/include/defpal.h new file mode 100644 index 0000000..c677e75 --- /dev/null +++ b/include/defpal.h @@ -0,0 +1,256 @@ +0x000000, +0xff0000, +0x00ff00, +0xa5a5ff, +0xffff00, +0xff00ff, +0x00ffff, +0xa5a5a5, +0xffa500, +0xa55000, +0x00a500, +0x0000ff, +0xa5a500, +0xa500a5, +0x00a5a5, +0xdadada, +0x959595, +0x006060, +0x008989, +0x00adad, +0x00d6d6, +0x00ffff, +0x18cefa, +0x30a9fa, +0x4891fa, +0x6081fa, +0x7d7dff, +0x5d005d, +0x850085, +0xad00ad, +0xd600d6, +0xff00ff, +0xfa18e6, +0xfa30d2, +0xfa48c6, +0xfa60be, +0xff7dbe, +0x000030, +0x000060, +0x000095, +0x0000ca, +0x0000ff, +0x2410ea, +0x4420da, +0x5d34c6, +0x7144b6, +0x5454a1, +0x303000, +0x606000, +0x959500, +0xcaca00, +0xffff00, +0xeaea10, +0xdada20, +0xc6c634, +0xb6b644, +0xa1a154, +0x003000, +0x006000, +0x009500, +0x00ca00, +0x00ff00, +0x10e610, +0x24d224, +0x3cbe3c, +0x4ca94c, +0x649564, +0x300000, +0x600000, +0x950000, +0xca0000, +0xff0000, +0xe61010, +0xd22424, +0xbe3c3c, +0xa94c4c, +0x956464, +0x3cbebe, +0x3ca1be, +0x3c85be, +0x3c69be, +0x3c48be, +0x483cbe, +0x693cbe, +0x853cbe, +0xa13cbe, +0xbe3cbe, +0xbe3ca1, +0xbe3c89, +0xbe3c71, +0xbe3c58, +0xbe3c40, +0xbe543c, +0xbe713c, +0xbe893c, +0xbea13c, +0xbebe3c, +0xa1be3c, +0x69be3c, +0x3cbe48, +0x3cbe81, +0x3cbebe, +0x602800, +0x953c00, +0xca5000, +0xff6900, +0xff8530, +0x141414, +0x303030, +0x484848, +0x646464, +0x7d7d7d, +0x959595, +0xadadad, +0xc6c6c6, +0xe2e2e2, +0xfafafa, +0x007dff, +0x00ffff, +0xbe7d00, +0x00d603, +0xa500a5, +0xb16400, +0xd69548, +0xffa5a5, +0xffca95, +0x00caff, +0x00ffca, +0x606060, +0xff3c3c, +0xffa550, +0x5050ff, +0x0050ff, +0xff5000, +0xbe3c00, +0xbe1414, +0x000000, +0xdaffda, +0xffff00, +0xff00ff, +0xa5a5a5, +0xff7d00, +0xff0000, +0x7dff00, +0x007d00, +0x50b100, +0x0000ff, +0x007dff, +0x00ffff, +0xbe7d00, +0x00d600, +0xa500a5, +0xb16400, +0xd69548, +0xffa5a5, +0xffca95, +0x00caff, +0x00ffca, +0x606060, +0xff3c3c, +0xffa550, +0x5050ff, +0x0050ff, +0xff5000, +0xbe3c03, +0xbe1414, +0x000003, +0xdaeaff, +0xffff00, +0xff00ff, +0xa5a5a5, +0xff7d00, +0xff0000, +0x7dff00, +0x007d00, +0x50b100, +0x0000ff, +0x007dff, +0x00ffff, +0xbe7d00, +0x00d600, +0xa500a5, +0xb16400, +0xd69548, +0xffa5a5, +0xffca95, +0x00caff, +0x00ffca, +0x606060, +0xff3c3c, +0xffa550, +0x5050ff, +0x0050ff, +0xff5000, +0xbe3c03, +0xbe1414, +0x000000, +0xffdada, +0xffff00, +0xff00ff, +0xa5a5a5, +0xff7d00, +0xff0000, +0x7dff00, +0x007d00, +0x50b100, +0x0000ff, +0x007dff, +0x00ffff, +0xbe7d00, +0x00d603, +0xa500a5, +0xb16400, +0xd69548, +0xffa5a5, +0xffca95, +0x00caff, +0x00ffca, +0x606060, +0xff3c3c, +0xffa550, +0x5050ff, +0xbe3c00, +0xbe1414, +0x000000, +0xffdaff, +0xffff00, +0xff00ff, +0xa5a5a5, +0xff7d00, +0xff0000, +0x7dff00, +0x007d00, +0x50b100, +0x0000ff, +0x007dff, +0x00ffff, +0xbe7d00, +0x00d600, +0xa500a5, +0xb16400, +0xd69548, +0xffa5a5, +0xffca95, +0x00caff, +0x00ffca, +0x606060, +0xff3c3c, +0xffa550, +0x5050ff, +0x0050ff, +0xff5000, +0xbe3c00, +0xbe1414, +0x000000, +0xffffff, diff --git a/include/dgt.h b/include/dgt.h new file mode 100644 index 0000000..c7d454a --- /dev/null +++ b/include/dgt.h @@ -0,0 +1,164 @@ +#ifndef DGT_H +#define DGT_H +# include +#ifndef EPPL_H +# include "eppl.h" +#endif +#ifndef EPP_ERR_H +# include "epp_err.h" +#endif +#define MAX_LINE_LEN 500 +typedef struct POINT { short int x,y; } POINT; +typedef struct DGT_ITEM { long int ID; + short int x1,y1,x2,y2; + short int npoints; + POINT s[MAX_LINE_LEN]; + } DGT_ITEM; +struct ITEM_AS_POINT {long int ID; + POINT p; + }; +typedef struct DGT { double XLeft,YBottom,XRight,YTop; + int mode; + int item_no; + unsigned char projection; + DGT_ITEM* buffer; + int limit; + void* F; + int eof; + int modified; + int (*next_item)(struct DGT* buffer); + void (*rewind) (struct DGT *d); + void (*dispose) (void *f); + int (*cmp_item)(DGT_ITEM* i1,DGT_ITEM* i2); + } DGT; +#define KEEP_OLD_VALUE -32768 + +DGT* open_dgt(char *filename); +/*opens existing file, given by name*/ +DGT* fopen_dgt(FILE *f); +/* open existing file given by file variable */ +DGT* creat_dgt(char *filename,double x_left,double y_bottom, + double x_right,double y_top, unsigned char proj); +/* creates file with given limits with given name */ +DGT* fcreat_dgt(FILE *f ,double x_left,double y_bottom, + double x_right,double y_top,unsigned char proj); +/* creates dgt file with given limits in given stream */ +DGT* mcreat_dgt(double x_left,double y_bottom, + double x_right,double y_top, unsigned char proj); +/* creates empty dgt in memory with given limits*/ +DGT* creat_dgt_as(char *filename,DGT* pattern); +DGT* fcreat_dgt_as(FILE *f,DGT *pattern); +DGT* mcreat_dgt_as(DGT *pattern); +/* creates file, with limits as in given file */ + +int load_dgt(DGT* dgt); +/* loads file opened for reading into memory */ +void save_dgt(DGT* dgt,FILE *f); +/* saves loaded file*/ +void close_dgt(DGT* dgt); +/* Destroys DGT object */ +void reset_dgt(DGT* dgt); +/* rewinds dgt file for first item, reopens for reading,if nessecary */ +DGT_ITEM* dgt_get(DGT* dgt); +/* allocates current item in memory and returns pointer to it*/ +void dgt_put(DGT *dgt, DGT_ITEM* item); +/* inserts item in writable file*/ +void dgt_replace(DGT *dgt, int index, DGT_ITEM *item); +/* replaces item number index with given item (memory files only*/ +DGT_ITEM* dgt_item_ptr(DGT *dgt, int index); +/* returns pointer to specified item without copiing it*/ +#define dgt_next(dgt) ((dgt)->next_item(dgt)) +/* flushes current item buffer */ +void dgt_seek(DGT *dgt,int index); +/* makes item with given number current (for memory files only)*/ +void chk_mask(DGT_ITEM* item); +/*set correct values of bounding rectangle*/ +void dgt_sort(DGT *dgt,int (*compare_func)(DGT_ITEM *i1,DGT_ITEM *i2)); + +void for_each_line(DGT *dgt,void (*item_proc)(DGT *dgt),DGT *outstream); +void for_each_point(DGT *dgt,void (*item_proc)(DGT *dgt),DGT *outstream); +/* Applies given item_proc to each item of given type in file. If outstream + not NULL, + copies all items (inclding those, which are not a subject of item_proc + to outstream */ +void for_each_item(DGT *dgt,void (*item_proc)(DGT *dgt)); +/* Applies given item_proc to each item in file. If items to be copied + to other stream, item_proc has to do it itself */ +/* coordinate recalculation */ + + +int dgt_x(DGT* dgt,double x); +int dgt_y(DGT* dgt,double y); + +double real_x(DGT* dgt,int x); +double real_y(DGT* dgt,int y); +double real_dx(DGT* dgt,int dx); +double real_dy(DGT* dgt,int dy); +double dgt_dist(DGT* dgt,int x1,int y1,int x2,int y2); +double dgt_pdist(DGT* dgt,POINT p1,POINT p2); +long int sq_dist(DGT* dgt,int x1,int y1,int x2,int y2); +long int sq_pdist(DGT* dgt,POINT p1,POINT p2); +long int sq_const(DGT* dgt,double dist); +/* item modification */ +#define dgt_touch(x) ((x)->modified=1); +void item_set_id(DGT_ITEM *item,long int newID); +#define dgt_set_id(x,ID) ((x)->modified=1,item_set_id((x)->buffer,ID)) +void dgt_set_point(DGT *dgt,int x,int y); +int dgt_add_node(DGT *dgt,int x,int y); +int dgt_ins_node(DGT *dgt,int index,int x,int y); +int item_mv_node(DGT_ITEM *item,int index,int x,int y); +#define dgt_mv_node(d,index,x,y) ((d)->modified=1,item_mv_node((d)->buffer,index,x,y)) +int dgt_rm_node(DGT *dgt,int index); +int dgt_split(DGT *dgt,int index); +int dgt_cut_segment(DGT *dgt,int index); +/* item utilities */ +DGT_ITEM* alloc_item(DGT_ITEM* item); +/* allocates new copy of item */ +/* Macros for access current item */ +#define dgt_item(x) (((DGT *)(x))->buffer) +/* returns pointer to current item */ +#define dgt_line_len(x) (((DGT *)(x))->buffer->npoints) +/* returns lile length (number of points) in current item*/ + +/* following macros provide a read/write access to current item */ +#define dgt_id(x) (((DGT *)(x))->buffer->ID) +/* ID of current item */ +#define dgt_node(x,i) (((DGT *)(x))->buffer->s[i]) + +/* node #i (0 - (line_len-1)) */ +#define dgt_nx(d,i) (((DGT *)(d))->buffer->s[i].x) +#define dgt_ny(d,i) (((DGT *)(d))->buffer->s[i].y) +#define dgt_xl(x) (((DGT *)(x))->buffer->x1) +/* left limit of bounding rectangle */ +#define dgt_xr(x) (((DGT *)(x))->buffer->x2) +/* right limit of bounding rectangle */ +#define dgt_yb(x) (((DGT *)(x))->buffer->y1) +/* bottom limit of bounding rectangle */ +#define dgt_yt(x) (((DGT *)(x))->buffer->y1) +/* top limit of bounding rectangle */ +#define dgt_pointx(x) (((DGT *)(x))->buffer->x1) +/* X of label point (if current object is label point)*/ +#define dgt_pointy(x) (((DGT *)(x))->buffer->y1) +/* Y of label point (if current object is label point)*/ +#define dgt_is_line(x) (((DGT *)(x))->buffer->npoints) +/* non-zero if current item is line */ +#define dgt_is_point(x) (!(((DGT *)(x))->buffer->npoints)) +/* non-zero if current item is point */ +#define dgt_point(x) (((((struct ITEM_AS_POINT *)(((DGT *)(x))->buffer)))->p)) +#define dgt_eof(x) (((DGT *)(x))->eof) +/*macros for access item, given by pointer*/ +#define item_id(x) ((x)->ID) +#define item_node(x,i) ((x)->s[i]) +#define item_xn(d,i) ((d)->s[i].x) +#define item_yn(d,i) ((d)->s[i].y) +#define item_xl(x) ((x)->x1) +#define item_xr(x) ((x)->x2) +#define item_yb(x) ((x)->y1) +#define item_yt(x) ((x)->y2) +#define point_x(x) ((x)->x1) +#define point_y(x) ((x)->y1) +#define item_len(x) ((x)->npoints) +#define item_point(x) (((struct ITEM_AS_POINT *)(x))->p) + +#endif + diff --git a/include/epp.h b/include/epp.h new file mode 100644 index 0000000..0479d6d --- /dev/null +++ b/include/epp.h @@ -0,0 +1,148 @@ +/* Epp file access definition */ +# ifndef EPP_H +# define EPP_H +# include +#ifndef EPPL_H +# include "eppl.h" +#endif +#ifndef EPP_ERR_H +# include "epp_err.h" +#endif +/* this structure defines internal representation of open EPP file */ +typedef struct EPP { int fr,lr,fc,lc; + double XLeft,YBottom,XRight,YTop; + double cell_area; + int offsite; + int mode; + unsigned short *widthtable, *row; + int kind; + FILE *F; + int min,max; + int width; + int currentline; + long filepos; + int cache_size; + void *cache; + int *counttable; + unsigned char *packed_buffer; + void (*position)(struct EPP* epp,int row); + int modified; + } EPP; +/*this structure used for simulatenouis operations on files with + different cell size*/ +typedef struct { int ax,bx,cx, + ay,by,cy; + } LINK_BUFFER,*EPP_LINK; + +EPP *open_epp(char *pathname); +EPP *fopen_epp(FILE *f); +/* opens existing EPP file */ +EPP *creat_epp(char *pathname,int first_col,int first_row,int last_col, + int last_row, double AXLeft,double AYTop, double AXRight, + double AYBottom, int scale, int base, int offsite); +EPP *fcreat_epp(FILE *f,int first_col,int first_row,int last_col, + int last_row, double AXLeft,double AYTop, double AXRight, + double AYBottom, int scale, int base, int offsite); + +/* creating epp file from scratch. All fields which are not defined as + parameters, are filled by default values. Kind depends of global variable + Create16bit */ +extern int Create16bit; /* if non-zero, all created EPP files would be 16 bit*/ +int set_epp_cache(EPP* epp,int lines); +/* set cache to lines lines. to keep accessed lines in memory. + affects only MAP_INPUT files*/ +EPP* load_epp(char *filename); +/* loads EPP file given by name into memory. Keeps open file for saving*/ +EPP* fload_epp(FILE *f); +/* loads EPP from given file. */ +int load_new_epp(EPP *f); +/* fills write-only file with offsite and reopens it for read-write */ +int save_epp(EPP* epp); +/* flushes file, loaded into memory + If file isn't modified, does nothing. + */ + +#define touch_epp(epp) ((epp)->mode|=MAP_MODIFIED) +/* marks file as modified to ensure that it would be actually written + by save_epp */ + +int save_epp_as(EPP* epp,char *newname); +/* saves loaded epp under new filename, making new stream default for this epp*/ +int fsave_epp_as(EPP* epp,FILE *f); +/* saves loaded epp into new stream, making it default */ +int epp_expand(EPP *epp); +/* converts loaded epp into file with greater depth */ +EPP *creat_epp_as(char *pathname,EPP *pattern); +EPP *fcreat_epp_as(FILE *f,EPP *pattern); +/* creates new epp file, copiing a most header fields from given file */ +void fast_convert_to_8bit(EPP *source,char *filename); +/* given a 16-bit epp file open for writing, writes a 8-bit epp file + containing low bytes from all pixels of source files. Closes both files + after that */ +void get_epp_header(EPP* epp, EPPHEADER *h); +/* reads header of EPP file */ +void change_epp_header(EPP* epp,EPPHEADER h); +/* changes several fields of EPP file */ +void setcomment(EPP *epp,char *comment); +/* change comment of epp file, which was open by creat_epp or creat_epp_as */ + +char *getcomment(EPP *epp); +/* returns comment of EPP file (address of static buffer,which would be + overriden by next call */ +int shift_epp(EPP *epp,int new_fr,int new_fc); +/* shifts row and col numbers to make fr and fc equial to fr and fc. + returns non-zero on success, zero, if some of boundaries hit signed short + limits */ + +typedef int (*EPP_ITER_PROC)(int col,int row,int value); + +int for_each_cell(EPP *epp, EPP_ITER_PROC action); +/* performs given operation for each non-offsite cell of existing EPP file + (terminated if action returns non-zero, + or performs operation for each cell of created EPP file, filling cell + by value, returned by action. value parameter in this case always containt + offsite of epp */ +long count_cells(EPP *epp, EPP_ITER_PROC condition); +/* calls condition for each non-offsite cell in existing epp file, returns + count of cells, for which condition was non-zero */ +extern int (*EndLineProc)(int row,int seqno,int total); +/* if not NULL, this function called from for_each_cell and count_cells + after processing of each line. If it returns non-zero, processing + terminated */ + +void reset_epp(EPP *epp); +/* reopens epp file for reading. if file was in create mode, fills all non-filled +lines by offsite */ + +unsigned short int *epp_getline(EPP *epp,int x,int y); +/* returns pointer to array of integer, which represents line y of raster, + starting from col x. NULL if x is within boundares of epp */ +void close_epp(EPP *epp); +/*********** coordinate recalculation **********/ +int epp_row(EPP *epp,double y);/* returns row by given alternate y */ +int epp_col(EPP *epp,double x);/* returns col for given alternate x */ +double alt_x(EPP *epp,int col);/* returns alternate x for given col */ +double alt_y(EPP *epp,int row);/* returns alternate y for given row */ +double alt_xc(EPP *epp,int col);/* returns alternate x for given col */ +double alt_yc(EPP *epp,int row);/* returns alternate y for given row */ +/**** this was private in pascal version ********/ +void get_row(EPP *epp);/* reads and unpacks row of epp file */ +void put_row(EPP *epp);/* packs and writes row */ +/********* compatibility of files *************/ +int compare_cell_size(EPP *f1,EPP *f2); +int is_aligned(EPP *f1,EPP *f2); +EPP_LINK link_epp(EPP *base,EPP *overlay); +int linked_row(EPP_LINK link,int row); +int linked_col(EPP_LINK link,int col); +# endif diff --git a/include/epp_err.h b/include/epp_err.h new file mode 100644 index 0000000..d53537a --- /dev/null +++ b/include/epp_err.h @@ -0,0 +1,26 @@ +#ifndef EPP_ERR_H +#define EPP_ERR_H +extern int map_error; /* after each operation contains error code */ +# define ME_POINT_OUTSIDE 1 +/* given coorndates are outside given epp file */ +# define ME_INVALID_MODE 2 +/* operation is non allowed for this mode */ +# define ME_READ_ERROR 3 +/* something wrong with reading file */ +# define ME_WRITE_ERROR 4 +/* disk full or something wrong writing file */ +# define ME_INVALID_PUT 5 +/* epp_put above current line */ +# define ME_OUT_OF_MEMORY 6 +# define ME_ACCESS_DENIED 7 +# define ME_NO_FILE 8 +# define ME_INVALID_FILE 9 +# define ME_CREATE_ERROR 10 +/* Return values for dgt item modification function */ +# define DGT_SUCCESS 0 +# define DGT_LINE_TOO_LONG 1 +# define DGT_ZERO_SEGMENT 2 +# define DGT_INVALID_NODE 3 +# define DGT_LINE_TOO_SHORT 4 +# define DGT_BAD_SPLIT_POINT 5 +#endif diff --git a/include/eppl.h b/include/eppl.h new file mode 100644 index 0000000..cd9fbb9 --- /dev/null +++ b/include/eppl.h @@ -0,0 +1,74 @@ +/**********************************************************************/ +/* Common include file for epp and dgt file access */ +/**********************************************************************/ +#ifndef EPPL_H +# define EPPL_H + +/* attempt to make epp.c portable to machines with non-intel CPU */ +# define LSB_FIRST +/* if defined, get_row and put_row thinks, that least significant byte + is first in int variable */ + +/* Area unit definition */ +# define AREA_NO_UNIT 0 +# define AREA_SQ_FOOT 1 +# define AREA_SQ_METER 2 +# define AREA_SQ_KM 3 +# define AREA_SQ_MILE 4 +# define AREA_HECTARE 5 +# define AREA_ACRE 6 + +/* Coordinate system definition */ +# define COORD_NONE 0 +# define COORD_UTM 1 +# define COORD_STPLANE 2 +# define COORD_LL 3 + +/* values for mode field of EPP */ +# define MAP_INPUT 1 +# define MAP_OUTPUT 2 +# define MAP_LOADED 4 +# define MAP_CACHED 8 +# define MAP_MODIFIED 128 +/* this structure defines 128-byte header of EPP file. + it assumes that all numeric types are in Intel format + short - 16-bit, lsb first, + long 32-bit, lsb first + double - 64-bit IEEE conforming */ +typedef struct EPPHEADER { short int fr,lr,fc,lc;/* last and first row/column */ + double fry,lry,fcx,lcx;/*corresponding alternative + coordinates*/ + short int kind;/* 8 or 16 bit file */ + short int base,scale; + unsigned short int offsite; /* blank class */ + double sfact; /* cell area */ + long access_ptr; /* file offset of width table */ + unsigned short minclass, maxclass; /* class limits. unused in + 8-bit files */ + char area_unit; + char coord_sys; + char Reserved[6]; + char date[16], time[8];/* ASCII date and time */ + char comment[32]; } EPPHEADER; +typedef struct DGTHEADER {double xleft,ybottom,xright,ytop; + long maxpt,maxline; + short kind; + char coord_sys; + char reserved[85]; + } DGTHEADER; + +#ifndef LSB_FIRST + + short swapshort(short x); + long swaplong(long x); + double swapdouble(double x); +#else +# define swapshort(x) (x) +# define swaplong(x) (x) +# define swapdouble(x) (x) +#endif + +#endif + +/* Here is the end of this file */ + diff --git a/include/eppl_ut.h b/include/eppl_ut.h new file mode 100644 index 0000000..f5db53e --- /dev/null +++ b/include/eppl_ut.h @@ -0,0 +1,19 @@ +#ifndef EPPL_UT_H +#define EPPL_UT_H +#include +#include +#include +#define LIBDIR "/usr/local/lib/fgis/" +FILE *lookup_file(const char *name,const char *suffix,const char *dir); +/* éÝÅÔ ÆÁÊÌ ÓÎÁÞÁÌÁ × ÔÅËÕÝÅÊ ÄÉÒÅËÔÏÒÉÉ, ÐÏÔÏÍ × ÄÉÒÅËÔÏÒÉÉ + dir × ÔÅËÕÝÅÊ ÄÉÒÅËÔÏÒÉÉ, ÐÏÔÏÍ × /usr/local/lib/fgis/$dir */ +char *default_ext(const char *filename,const char *ext); +char *force_ext(const char *filename,const char *ext); +char *last_ext(const char *name); +int show_progress(int row,int seqno,int total); +int check_int(int row,int seqno, int total); +int show_percent(int row,int seqno,int total); +void install_progress_indicator(int (*)(int,int,int)); +int clear_progress(int success); +void show_version(char *name,char *RCS_ID); +#endif diff --git a/include/getopt.h b/include/getopt.h new file mode 100644 index 0000000..d751c6b --- /dev/null +++ b/include/getopt.h @@ -0,0 +1,132 @@ +/* Declarations for getopt. + Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if __STDC__ +#if defined(__GNU_LIBRARY__) +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* not __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* not __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/include/reclass.h b/include/reclass.h new file mode 100644 index 0000000..4043c87 --- /dev/null +++ b/include/reclass.h @@ -0,0 +1,30 @@ +#ifndef RECLASS_H +#define RECLASS_H + +#include + +typedef unsigned short int * RECLASS; +/* */ +extern int interactive_parser; +RECLASS create_reclass_table(int size); +RECLASS parse_statements(int size,RECLASS src,int (*recl_getc)()); +RECLASS make_reclass_table(EPP *infile,int (*recl_getc)()); +/* óÏÚÄÁÅÔ ÇÌÏÂÁÌØÎÕÀ ÔÁÂÌÉÃÕ ÒÅËÌÁÓÓÁ ÄÌÑ ÆÁÊÌÁ infile. + ïÐÅÒÁÔÏÒÙ ÒÅËÌÁÓÓÁ ÞÉÔÁÀÔÓÑ Ó ÐÏÍÏÝØÀ ÆÕÎËÃÉÉ recl_getc, ËÏÔÏÒÁÑ + ÚÁ ÏÄÉÎ ÒÁÚ ×ÏÚ×ÒÁÝÁÅÔ ÏÄÉÎ ÓÉÍ×ÏÌ. +*/ +RECLASS wrapped_reclass(EPP *infile,int white); + + + +/* óÏÚÄÁÅÔ ÒÅËÌÁÓÓ ÐÏ ÕÍÏÌÞÁÎÉÀ (offsite=white,0=0, ÏÓÔÁÌØÎÙÅ (c-1)%(white-1)+1;*/ +#define epp_table_size(epp) ((epp)->max>(epp)->offsite?(epp)->max:(epp)->offsite) + +#define default_reclass(epp) create_reclass_table(epp_table_size(epp)) + + +/* ÐÒÉÓ×ÏÊÔÅ ÜÔÏÊ ÐÅÒÅÍÅÎÎÏÊ ÎÅÎÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ, ÅÓÌÉ ××ÏÄ + ÏÐÅÒÁÔÏÒÏ× reclass ÐÒÏÉÓÈÏÄÉÔ Ó ËÌÁ×ÉÁÔÕÒÙ É ÐÏÌØÚÏ×ÁÔÅÌØ ÍÏÖÅÔ, + ÐÏÌÕÞÉ× ÓÏÏÂÝÅÎÉÅ Ï ÏÛÉÂËÅ ÐÅÒÅ××ÅÓÔÉ ÓÔÒÏËÕ ÚÁÎÏ×Ï*/ + +#endif diff --git a/include/regex.h b/include/regex.h new file mode 100644 index 0000000..a495005 --- /dev/null +++ b/include/regex.h @@ -0,0 +1,490 @@ +/* Definitions for data structures and routines for the regular + expression library, version 0.12. + + Copyright (C) 1985, 89, 90, 91, 92, 1993 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 2, 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef __REGEXP_LIBRARY_H__ +#define __REGEXP_LIBRARY_H__ + +/* POSIX says that must be included (by the caller) before + . */ + +#ifdef VMS +/* VMS doesn't have `size_t' in , even though POSIX says it + should be there. */ +#include +#endif + + +/* The following bits are used to determine the regexp syntax we + recognize. The set/not-set meanings are chosen so that Emacs syntax + remains the value 0. The bits are given in alphabetical order, and + the definitions shifted by one from the previous bit; thus, when we + add or remove a bit, only one other definition need change. */ +typedef unsigned reg_syntax_t; + +/* If this bit is not set, then \ inside a bracket expression is literal. + If set, then such a \ quotes the following character. */ +#define RE_BACKSLASH_ESCAPE_IN_LISTS (1) + +/* If this bit is not set, then + and ? are operators, and \+ and \? are + literals. + If set, then \+ and \? are operators and + and ? are literals. */ +#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) + +/* If this bit is set, then character classes are supported. They are: + [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], + [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. + If not set, then character classes are not supported. */ +#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) + +/* If this bit is set, then ^ and $ are always anchors (outside bracket + expressions, of course). + If this bit is not set, then it depends: + ^ is an anchor if it is at the beginning of a regular + expression or after an open-group or an alternation operator; + $ is an anchor if it is at the end of a regular expression, or + before a close-group or an alternation operator. + + This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because + POSIX draft 11.2 says that * etc. in leading positions is undefined. + We already implemented a previous draft which made those constructs + invalid, though, so we haven't changed the code back. */ +#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) + +/* If this bit is set, then special characters are always special + regardless of where they are in the pattern. + If this bit is not set, then special characters are special only in + some contexts; otherwise they are ordinary. Specifically, + * + ? and intervals are only special when not after the beginning, + open-group, or alternation operator. */ +#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) + +/* If this bit is set, then *, +, ?, and { cannot be first in an re or + immediately after an alternation or begin-group operator. */ +#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) + +/* If this bit is set, then . matches newline. + If not set, then it doesn't. */ +#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) + +/* If this bit is set, then . doesn't match NUL. + If not set, then it does. */ +#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) + +/* If this bit is set, nonmatching lists [^...] do not match newline. + If not set, they do. */ +#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) + +/* If this bit is set, either \{...\} or {...} defines an + interval, depending on RE_NO_BK_BRACES. + If not set, \{, \}, {, and } are literals. */ +#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) + +/* If this bit is set, +, ? and | aren't recognized as operators. + If not set, they are. */ +#define RE_LIMITED_OPS (RE_INTERVALS << 1) + +/* If this bit is set, newline is an alternation operator. + If not set, newline is literal. */ +#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) + +/* If this bit is set, then `{...}' defines an interval, and \{ and \} + are literals. + If not set, then `\{...\}' defines an interval. */ +#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) + +/* If this bit is set, (...) defines a group, and \( and \) are literals. + If not set, \(...\) defines a group, and ( and ) are literals. */ +#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) + +/* If this bit is set, then \ matches . + If not set, then \ is a back-reference. */ +#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) + +/* If this bit is set, then | is an alternation operator, and \| is literal. + If not set, then \| is an alternation operator, and | is literal. */ +#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) + +/* If this bit is set, then an ending range point collating higher + than the starting range point, as in [z-a], is invalid. + If not set, then when ending range point collates higher than the + starting range point, the range is ignored. */ +#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) + +/* If this bit is set, then an unmatched ) is ordinary. + If not set, then an unmatched ) is invalid. */ +#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) + +/* This global variable defines the particular regexp syntax to use (for + some interfaces). When a regexp is compiled, the syntax used is + stored in the pattern buffer, so changing this does not affect + already-compiled regexps. */ +extern reg_syntax_t re_syntax_options; + +/* Define combinations of the above bits for the standard possibilities. + (The [[[ comments delimit what gets put into the Texinfo file, so + don't delete them!) */ +/* [[[begin syntaxes]]] */ +#define RE_SYNTAX_EMACS 0 + +#define RE_SYNTAX_AWK \ + (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ + | RE_UNMATCHED_RIGHT_PAREN_ORD) + +#define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS) + +#define RE_SYNTAX_GREP \ + (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ + | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ + | RE_NEWLINE_ALT) + +#define RE_SYNTAX_EGREP \ + (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ + | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ + | RE_NO_BK_VBAR) + +#define RE_SYNTAX_POSIX_EGREP \ + (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES) + +/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ +#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC + +#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC + +/* Syntax bits common to both basic and extended POSIX regex syntax. */ +#define _RE_SYNTAX_POSIX_COMMON \ + (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ + | RE_INTERVALS | RE_NO_EMPTY_RANGES) + +#define RE_SYNTAX_POSIX_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) + +/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes + RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this + isn't minimal, since other operators, such as \`, aren't disabled. */ +#define RE_SYNTAX_POSIX_MINIMAL_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) + +#define RE_SYNTAX_POSIX_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS + replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */ +#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) +/* [[[end syntaxes]]] */ + +/* Maximum number of duplicates an interval can allow. Some systems + (erroneously) define this in other header files, but we want our + value, so remove any previous define. */ +#ifdef RE_DUP_MAX +#undef RE_DUP_MAX +#endif +#define RE_DUP_MAX ((1 << 15) - 1) + + +/* POSIX `cflags' bits (i.e., information for `regcomp'). */ + +/* If this bit is set, then use extended regular expression syntax. + If not set, then use basic regular expression syntax. */ +#define REG_EXTENDED 1 + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define REG_ICASE (REG_EXTENDED << 1) + +/* If this bit is set, then anchors do not match at newline + characters in the string. + If not set, then anchors do match at newlines. */ +#define REG_NEWLINE (REG_ICASE << 1) + +/* If this bit is set, then report only success or fail in regexec. + If not set, then returns differ between not matching and errors. */ +#define REG_NOSUB (REG_NEWLINE << 1) + + +/* POSIX `eflags' bits (i.e., information for regexec). */ + +/* If this bit is set, then the beginning-of-line operator doesn't match + the beginning of the string (presumably because it's not the + beginning of a line). + If not set, then the beginning-of-line operator does match the + beginning of the string. */ +#define REG_NOTBOL 1 + +/* Like REG_NOTBOL, except for the end-of-line. */ +#define REG_NOTEOL (1 << 1) + + +/* If any error codes are removed, changed, or added, update the + `re_error_msg' table in regex.c. */ +typedef enum +{ + REG_NOERROR = 0, /* Success. */ + REG_NOMATCH, /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ + REG_BADPAT, /* Invalid pattern. */ + REG_ECOLLATE, /* Not implemented. */ + REG_ECTYPE, /* Invalid character class name. */ + REG_EESCAPE, /* Trailing backslash. */ + REG_ESUBREG, /* Invalid back reference. */ + REG_EBRACK, /* Unmatched left bracket. */ + REG_EPAREN, /* Parenthesis imbalance. */ + REG_EBRACE, /* Unmatched \{. */ + REG_BADBR, /* Invalid contents of \{\}. */ + REG_ERANGE, /* Invalid range end. */ + REG_ESPACE, /* Ran out of memory. */ + REG_BADRPT, /* No preceding re for repetition op. */ + + /* Error codes we've added. */ + REG_EEND, /* Premature end. */ + REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ + REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ +} reg_errcode_t; + +/* This data structure represents a compiled pattern. Before calling + the pattern compiler, the fields `buffer', `allocated', `fastmap', + `translate', and `no_sub' can be set. After the pattern has been + compiled, the `re_nsub' field is available. All other fields are + private to the regex routines. */ + +struct re_pattern_buffer +{ +/* [[[begin pattern_buffer]]] */ + /* Space that holds the compiled pattern. It is declared as + `unsigned char *' because its elements are + sometimes used as array indexes. */ + unsigned char *buffer; + + /* Number of bytes to which `buffer' points. */ + unsigned long allocated; + + /* Number of bytes actually used in `buffer'. */ + unsigned long used; + + /* Syntax setting with which the pattern was compiled. */ + reg_syntax_t syntax; + + /* Pointer to a fastmap, if any, otherwise zero. re_search uses + the fastmap, if there is one, to skip over impossible + starting points for matches. */ + char *fastmap; + + /* Either a translate table to apply to all characters before + comparing them, or zero for no translation. The translation + is applied to a pattern when it is compiled and to a string + when it is matched. */ + char *translate; + + /* Number of subexpressions found by the compiler. */ + size_t re_nsub; + + /* Zero if this pattern cannot match the empty string, one else. + Well, in truth it's used only in `re_search_2', to see + whether or not we should use the fastmap, so we don't set + this absolutely perfectly; see `re_compile_fastmap' (the + `duplicate' case). */ + unsigned can_be_null : 1; + + /* If REGS_UNALLOCATED, allocate space in the `regs' structure + for `max (RE_NREGS, re_nsub + 1)' groups. + If REGS_REALLOCATE, reallocate space if necessary. + If REGS_FIXED, use what's there. */ +#define REGS_UNALLOCATED 0 +#define REGS_REALLOCATE 1 +#define REGS_FIXED 2 + unsigned regs_allocated : 2; + + /* Set to zero when `regex_compile' compiles a pattern; set to one + by `re_compile_fastmap' if it updates the fastmap. */ + unsigned fastmap_accurate : 1; + + /* If set, `re_match_2' does not return information about + subexpressions. */ + unsigned no_sub : 1; + + /* If set, a beginning-of-line anchor doesn't match at the + beginning of the string. */ + unsigned not_bol : 1; + + /* Similarly for an end-of-line anchor. */ + unsigned not_eol : 1; + + /* If true, an anchor at a newline matches. */ + unsigned newline_anchor : 1; + +/* [[[end pattern_buffer]]] */ +}; + +typedef struct re_pattern_buffer regex_t; + + +/* search.c (search_buffer) in Emacs needs this one opcode value. It is + defined both in `regex.c' and here. */ +#define RE_EXACTN_VALUE 1 + +/* Type for byte offsets within the string. POSIX mandates this. */ +typedef int regoff_t; + + +/* This is the structure we store register match data in. See + regex.texinfo for a full description of what registers match. */ +struct re_registers +{ + unsigned num_regs; + regoff_t *start; + regoff_t *end; +}; + + +/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, + `re_match_2' returns information about at least this many registers + the first time a `regs' structure is passed. */ +#ifndef RE_NREGS +#define RE_NREGS 30 +#endif + + +/* POSIX specification for registers. Aside from the different names than + `re_registers', POSIX uses an array of structures, instead of a + structure of arrays. */ +typedef struct +{ + regoff_t rm_so; /* Byte offset from string's start to substring's start. */ + regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ +} regmatch_t; + +/* Declarations for routines. */ + +/* To avoid duplicating every routine declaration -- once with a + prototype (if we are ANSI), and once without (if we aren't) -- we + use the following macro to declare argument types. This + unfortunately clutters up the declarations a bit, but I think it's + worth it. */ + +#if __STDC__ + +#define _RE_ARGS(args) args + +#else /* not __STDC__ */ + +#define _RE_ARGS(args) () + +#endif /* not __STDC__ */ + +/* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the `re_syntax_options' variable. */ +extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); + +/* Compile the regular expression PATTERN, with length LENGTH + and syntax given by the global `re_syntax_options', into the buffer + BUFFER. Return NULL if successful, and an error string if not. */ +extern const char *re_compile_pattern + _RE_ARGS ((const char *pattern, int length, + struct re_pattern_buffer *buffer)); + + +/* Compile a fastmap for the compiled pattern in BUFFER; used to + accelerate searches. Return 0 if successful and -2 if was an + internal error. */ +extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); + + +/* Search in the string STRING (with length LENGTH) for the pattern + compiled into BUFFER. Start searching at position START, for RANGE + characters. Return the starting position of the match, -1 for no + match, or -2 for an internal error. Also return register + information in REGS (if REGS and BUFFER->no_sub are nonzero). */ +extern int re_search + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, int range, struct re_registers *regs)); + + +/* Like `re_search', but search in the concatenation of STRING1 and + STRING2. Also, stop searching at index START + STOP. */ +extern int re_search_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, int range, struct re_registers *regs, int stop)); + + +/* Like `re_search', but return how many characters in STRING the regexp + in BUFFER matched, starting at position START. */ +extern int re_match + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, struct re_registers *regs)); + + +/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ +extern int re_match_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, struct re_registers *regs, int stop)); + + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using BUFFER and REGS will use this memory + for recording register information. STARTS and ENDS must be + allocated with malloc, and must each be at least `NUM_REGS * sizeof + (regoff_t)' bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ +extern void re_set_registers + _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, + unsigned num_regs, regoff_t *starts, regoff_t *ends)); + +/* 4.2 bsd compatibility. */ +extern char *re_comp _RE_ARGS ((const char *)); +extern int re_exec _RE_ARGS ((const char *)); + +/* POSIX compatibility. */ +extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags)); +extern int regexec + _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags)); +extern size_t regerror + _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf, + size_t errbuf_size)); +extern void regfree _RE_ARGS ((regex_t *preg)); + +#endif /* not __REGEXP_LIBRARY_H__ */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..c4d0739 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,64 @@ +CC=gcc +CFLAGS=-g -fPIC -O2 -Wall -ansi -pedantic -I ../include +LIB_OBJS=\ +byteorder.o\ +dgt_dist.o\ +dgt_input.o\ +dgt_iter.o\ +dgt_output.o\ +epp_cache.o\ +epp_input.o\ +epp_iter.o\ +epp_loaded.o\ +epp_output.o\ +file_utils.o\ +lookup.o\ +overlay.o\ +reclass.tab.o +RCS=\ +RCS/byteorder.c,v\ +RCS/clr.c,v\ +RCS/dgt_dist.c,v\ +RCS/dgt_input.c,v\ +RCS/dgt_iter.c,v\ +RCS/dgt_output.c,v\ +RCS/epp_cache.c,v\ +RCS/epp_input.c,v\ +RCS/epp_iter.c,v\ +RCS/epp_loaded.c,v\ +RCS/epp_output.c,v\ +RCS/file_utils.c,v\ +RCS/lookup.c,v\ +RCS/overlay.c,v\ +RCS/reclass.y,v +SRC=\ +byteorder.c\ +clr.c\ +dgt_dist.c\ +dgt_input.c\ +dgt_iter.c\ +dgt_output.c\ +epp_cache.c\ +epp_input.c\ +epp_iter.c\ +epp_loaded.c\ +epp_output.c\ +file_utils.c\ +lookup.c\ +overlay.c\ +reclass.y +RCS/%,v : % + ci $< +libepp.a:${LIB_OBJS} + ar r libepp.a ${LIB_OBJS} +libepp.so:${LIB_OBJS} + gcc -shared ${LIB_OBJS} -o libepp.so -lm +reclass.tab.c:reclass.y + bison reclass.y +clean: + rm *.o + rm reclass.tab.c +distclean: clean + rm libepp.a +rcs: ${RCS} + diff --git a/lib/TODO.lib b/lib/TODO.lib new file mode 100644 index 0000000..8650f71 --- /dev/null +++ b/lib/TODO.lib @@ -0,0 +1,16 @@ +æÕÎËÃÉÑ epp_expand(epp) - ÐÒÅ×ÒÁÝÁÅÔ ÚÁÇÒÕÖÅÎÎÙÊ × ÐÁÍÑÔØ 8-ÂÉÔÎÙÊ + ÒÁÓÔÒ × 16-ÂÉÔÎÙÊ. + (á ÍÏÖÅÔ ÂÙÔØ ÓÔÏÉÔ ×ÓÅÇÄÁ ËÏÎ×ÅÒÔÉÒÏ×ÁÔØ ÒÁÓÔÒ ÐÒÉ ÚÁÇÒÕÚËÅ + É ×ÏÚÍÏÖÎÏ ÐÒÉ ÓÏÈÒÁÎÅÎÉÉ ËÏÎ×ÅÒÔÉÒÏ×ÁÔØ ÏÂÒÁÔÎÏ) + + õÓÌÏ×ÉÑ ËÏÎ×ÅÒÔÉÒÏ×ÁÎÉÑ + if ((max<=255&&offsite<=255)||(max<255&&offsite==65535)|| + (max<=255&&offsite==65535&&counttable(255)==0)) + +ïÂÒÁÂÁÔÙ×ÁÔØ ÏÛÉÂËÕ, ÅÓÌÉ ÄÌÉÎÁ ÕÐÁËÏ×ÁÎÎÏÊ ÓÔÒÏËÉ >65535 ÂÁÊÔ + +æÕÎËÃÉÑ epp_putline(EPP *epp,int x1,int x2,int y,int value) + +÷×ÅÓÔÉ ÇÌÏÂÁÌØÎÙÊ ÆÌÁÇ ÉÚÍÅÎÅÎÉÑ ÆÁÊÌÁ + +ðÅÒÅÉÍÅÎÏ×ÁÔØ ÐÏÌÅ modified × row_modified ÄÌÑ ÑÓÎÏÓÔÉ. diff --git a/lib/byteorder.c b/lib/byteorder.c new file mode 100644 index 0000000..5e78fc4 --- /dev/null +++ b/lib/byteorder.c @@ -0,0 +1,18 @@ +short swapshort(short x) +{ return (signed short) (((unsigned short) x)>>8)|(((unsigned short) x)<<8); +} +long swaplong(long x) +{ +#define ulx ((unsigned long) x) +return (signed long) (((ulx & 0xFF000000)>>24)|((ulx &0xFF0000)>>8)|((ulx & 0xFF00)<<8)|((ulx & 0xFF)<<24)); +} +union doubleconv {double d; + unsigned char b[8]; + }; +double swapdouble(double x) +{ union doubleconv tmp1,tmp2; + int i,j; + tmp1.d=x; + for (i=0,j=7;i<8;tmp2.b[j--]=tmp1.b[i++]); + return tmp2.d; + } diff --git a/lib/clr.c b/lib/clr.c new file mode 100644 index 0000000..ac92d49 --- /dev/null +++ b/lib/clr.c @@ -0,0 +1,52 @@ +#include +#include +#include "eppl_ut.h" +#include +#include +int defarray[]={ +#include "defpal.h" +}; +PALETTE default_palette=defarray; +PALETTE read_palette(FILE *f) +/* þÉÔÁÅÔ ÐÁÌÉÔÒÕ ÉÚ ÆÁÊÌÁ × ÆÏÒÍÁÔÅ EPPL7 */ +{ PALETTE pal; + int index,r,g,b; + pal=memcpy(malloc(256*sizeof(long int)),default_palette,256*sizeof(long int)); + do { + if (fscanf(f,"%d %d %d %d\n",&index,&r,&g,&b)!=4) break; + if (index>255) continue; + pal[index]=(r*255/1000)<<16|(g*255/1000)<<8|(b*255/1000); + } while (!feof(f)); + return pal; +} + +char *ppm_pixel(PALETTE palette,int index) +{ int value; + static char buffer[24]; + if(index>=0&&index<255) + value=palette[index]; + else value=palette[255]; + sprintf(buffer,"%d %d %d ",value>>16,(value>>8)&0xFF,value & 0xFF); + return buffer; +} + +char *Xcolor_string(PALETTE palette,int index) +{ int value; + static char buffer[24]; + if(index>=0&&index<255) + value=palette[index]; else value=palette[255]; + sprintf(buffer,"#%06x",value); + return buffer; +} +XColor Xcolor_struct(PALETTE palette,int index) +{ int value; + XColor buffer; + if (index>=0&&index<255) + value=palette[index]; else value=palette[255]; + buffer.red=value>>16; + buffer.green=(value>>8)&0xFF; + buffer.blue=value&0xFF; + buffer.flags=DoRed|DoGreen|DoBlue; + return buffer; +} + diff --git a/lib/dgt_dist.c b/lib/dgt_dist.c new file mode 100644 index 0000000..5b955f8 --- /dev/null +++ b/lib/dgt_dist.c @@ -0,0 +1,21 @@ +#include +#include "dgt.h" + +double real_dx(DGT *dgt,int dx) +{ return (dgt->XRight-dgt->XLeft)*dx/65535; +} + +double real_dy(DGT *dgt,int dy) +{ return (dgt->YTop-dgt->YBottom)*dy/65535; +} +double dgt_dist(DGT *dgt,int x1,int y1,int x2,int y2) +{ + return hypot(real_dx(dgt,x1-x2),real_dy(dgt,y1-y2)); +} +double dgt_pdist(DGT *dgt,POINT p1,POINT p2) +{ + return hypot(real_dx(dgt,p1.x-p2.x),real_dy(dgt,p1.y-p2.y)); +} +double dgt_atan2(DGT *dgt,int dx,int dy) +{ return atan2(dy/(dgt->XRight-dgt->XLeft),dx/(dgt->YTop-dgt->YBottom)); +} diff --git a/lib/dgt_input.c b/lib/dgt_input.c new file mode 100644 index 0000000..9528623 --- /dev/null +++ b/lib/dgt_input.c @@ -0,0 +1,112 @@ +#include +#include +#include "dgt.h" +int read_item(DGT* dgt) +/* read next item of dgt file opened for reading */ +{ int to_skip=0; +#ifndef LSB_FIRST + DGT_ITEM tmp; +#endif +#ifdef LSB_FIRST + if(fread(dgt->buffer,1,14,(FILE *)dgt->F)!=14) return 1; +#else + if(fread(&tmp,1,14,(FILE *)(dgt->F))!=14) return 1; + dgt->buffer->ID=swaplong(tmp.ID); + swab(&(tmp.x1),&(dgt->buffer->x1),10); +#endif + if (dgt->buffer->npoints) + { if(dgt->buffer->npoints>MAX_LINE_LEN) {to_skip=(dgt->buffer->npoints-MAX_LINE_LEN)*4; + dgt->buffer->npoints=MAX_LINE_LEN;} +#ifdef LSB_FIRST + if (fread(&(dgt->buffer->s),4,dgt->buffer->npoints, + (FILE *)dgt->F)!=dgt->buffer->npoints) + { map_error = ME_READ_ERROR; return 1;} +#else + if(fread(&(tmp.s),4,dgt->buffer->npoints, + (FILE *)dgt->F)!=dgt->buffer->npoints) + {map_error=ME_READ_ERROR;return 1;} + swab(&(tmp.s),&(dgt->buffer->s),dgt->buffer->npoints*4); +#endif + if (to_skip) fseek((FILE*)dgt->F,to_skip,SEEK_CUR); + } + dgt->item_no++; + return dgt->eof=(dgt->buffer->ID==0&&dgt->buffer->npoints==0); + +} +void go_first(DGT *dgt) +{ + fseek((FILE *)dgt->F,128L,SEEK_SET); + dgt->item_no=0; + dgt->eof=dgt->next_item(dgt); +} + +DGT* open_dgt(char *filename) +/*opens existing file, given by name*/ +{FILE *f; + if (!(f=fopen(filename,"r"))) + return NULL; + return fopen_dgt(f); +} +typedef void (*close_func)(void *f); +DGT* fopen_dgt(FILE *f) +/* open existing file given by file variable */ +{ DGT* tmp; + DGTHEADER h; + if(!(tmp=malloc(sizeof(DGT)))) {map_error=ME_OUT_OF_MEMORY;return NULL;} + if(fread(&h,1,sizeof(h),f)!=sizeof(h)) {map_error=ME_READ_ERROR;free(tmp);return NULL;} + if(!(tmp->buffer=malloc(sizeof(DGT_ITEM)))) {map_error=ME_OUT_OF_MEMORY;free(tmp);return NULL;} + tmp->XLeft=swapdouble(h.xleft); + tmp->XRight=swapdouble(h.xright); + tmp->YTop=swapdouble(h.ytop); + tmp->YBottom=swapdouble(h.ybottom); + tmp->projection=h.coord_sys; + tmp->mode=MAP_INPUT; + tmp->item_no=0; + tmp->next_item=read_item; + tmp->rewind=go_first; + tmp->F=f; + tmp->dispose=(close_func)fclose; + tmp->cmp_item=NULL; + tmp->next_item(tmp); + return tmp; +} +void close_dgt(DGT* dgt) +/* Destroys DGT object */ +{ dgt->rewind(dgt); + dgt->dispose(dgt->F); + free(dgt->buffer); + free(dgt); +} +DGT_ITEM* dgt_get(DGT* dgt) +/* allocates current item in memory and returns pointer to it*/ +{ DGT_ITEM* item; + if (!(dgt->mode&MAP_INPUT)) {map_error=ME_INVALID_MODE;return NULL;} + if (!dgt->eof) {item= alloc_item(dgt->buffer);dgt->next_item(dgt);return item;} + else return NULL; +} +int dgt_x(DGT* dgt,double x) +{ +return ((x-dgt->XLeft)/(dgt->XRight-dgt->XLeft)*65535)-32767; +} +int dgt_y(DGT* dgt,double y) +{ +return ((y-dgt->YBottom)/(dgt->YTop-dgt->YBottom)*65535)-32767; +} +double real_x(DGT* dgt,int x) +{ return (x+32767)/65535.0*(dgt->XRight-dgt->XLeft)+dgt->XLeft; +} +double real_y(DGT* dgt,int y) +{ +return (y+32767)/65535.0*(dgt->YTop-dgt->YBottom)+dgt->YBottom; +} + +DGT_ITEM* alloc_item(DGT_ITEM *item) +{DGT_ITEM* new_item; + new_item=malloc(14+item->npoints*4); + return memcpy(new_item,item,14+item->npoints*4); +} +void reset_dgt(DGT* dgt) +/* rewinds dgt file for first item, reopens for reading,if nessecary */ +{ dgt->rewind(dgt); + dgt->eof=dgt->next_item(dgt); +} diff --git a/lib/dgt_iter.c b/lib/dgt_iter.c new file mode 100644 index 0000000..997e002 --- /dev/null +++ b/lib/dgt_iter.c @@ -0,0 +1,27 @@ +#include "dgt.h" +void for_each_line(DGT *dgt,void (*item_proc)(DGT *dgt),DGT *outstream) +{ reset_dgt(dgt); + while(!dgt_eof(dgt)) + { if (dgt_is_line(dgt)) + item_proc(dgt); + if (outstream) dgt_put(outstream,dgt->buffer); + dgt_next(dgt); + } +} +void for_each_point(DGT *dgt,void (*item_proc)(DGT *dgt),DGT *outstream) +{ reset_dgt(dgt); + while(!dgt_eof(dgt)) + { if (dgt_is_point(dgt)) + item_proc(dgt); + if (outstream) dgt_put(outstream,dgt->buffer); + dgt_next(dgt); + } +} +void for_each_item(DGT *dgt,void (*item_proc)(DGT *dgt)) +{ reset_dgt(dgt); + while(!dgt_eof(dgt)) + { + item_proc(dgt); + dgt_next(dgt); + } +} diff --git a/lib/dgt_output.c b/lib/dgt_output.c new file mode 100644 index 0000000..ffc426f --- /dev/null +++ b/lib/dgt_output.c @@ -0,0 +1,211 @@ +#include +#include +#include +#include "dgt.h" +typedef void (*close_func)(void *f); + + +DGT* creat_dgt(char *filename,double x_left,double y_bottom, + double x_right,double y_top, unsigned char proj) +/* creates file with given limits with given name */ +{FILE *f; + f=fopen(filename,"w+"); + if (!f) return NULL; + return fcreat_dgt(f,x_left,y_bottom,x_right,y_top,proj); +} +int write_header(FILE *f ,double x_left,double y_bottom, + double x_right,double y_top,unsigned char proj) +{ DGTHEADER h; + memset(&h,0,sizeof(h)); + h.xleft=swapdouble(x_left); + h.ybottom=swapdouble(y_bottom); + h.xright=swapdouble(x_right); + h.ytop=swapdouble(y_top); + h.coord_sys=proj; + return ( fwrite(&h,1,128,f)==128); +} +int write_buf(DGT *dgt) +{ +#ifdef LSB_FIRST +chk_mask(dgt->buffer); +dgt->modified=0;dgt->item_no++; +return fwrite(dgt->buffer,1,14+4*dgt->buffer->npoints,(FILE *)dgt->F)== + 14+4*dgt->buffer->npoints; +#else +DGT_ITEM tmp; +chk_mask(dgt->buffer); +tmp.ID=swaplong(dgt->buffer->ID); +swab(&(dgt->buffer->x1),&(tmp.x1),10+4*dgt->buffer->npoints); +dgt->modified=0;dgt->item_no++; +return fwrite(&tmp,14+4*dgt->buffer->npoints,1,(FILE *)dgt->F)== + 14+4*dgt->buffer->npoints; +#endif +} +void write_eof(DGT* dgt) +{short int eof_marker[7]={0,0,0,0,0,0,0}; + if (dgt->modified) write_buf(dgt); + fwrite(&eof_marker,14,1,(FILE *)dgt->F); +} +DGT* fcreat_dgt(FILE *f ,double x_left,double y_bottom, + double x_right,double y_top,unsigned char proj) +/* creates dgt file with given limits in given stream */ +{ DGT* tmp; + if (!write_header(f,x_left,y_bottom,x_right,y_top,proj)) { map_error=ME_WRITE_ERROR; return NULL;} + if (!(tmp=malloc(sizeof(DGT)))) {map_error=ME_OUT_OF_MEMORY;return NULL;} + tmp->XLeft=x_left; + tmp->YBottom=y_bottom; + tmp->XRight=x_right; + tmp->YTop=y_top; + tmp->mode=MAP_OUTPUT; + tmp->item_no=0; + tmp->projection=proj; + tmp->F=f; + tmp->eof=1; + tmp->modified=0; + tmp->next_item=write_buf; + tmp->rewind=write_eof; + tmp->dispose=(close_func) fclose; + tmp->buffer=malloc(sizeof(DGT_ITEM)); + return tmp; +} +DGT* creat_dgt_as(char *filename,DGT* pattern) +{return creat_dgt(filename,pattern->XLeft,pattern->YBottom,pattern->XRight, + pattern->YTop,pattern->projection); +} +DGT* fcreat_dgt_as(FILE *f,DGT *pattern) +{return fcreat_dgt(f,pattern->XLeft,pattern->YBottom,pattern->XRight, + pattern->YTop,pattern->projection); +} +void chk_mask(DGT_ITEM* item) +/*set correct values of bounding rectangle*/ +{int i,x1,y1,x2,y2; + POINT* p; + + if (!item->npoints) return; + x1=32767; + y1=32767; + x2=-32767; + y2=-32767; + for(i=0,p=item->s;inpoints;i++,p++) + { if(p->xx; + if(p->x>x2) x2=p->x; + if(p->yy; + if(p->y>y2) y2=p->y; + } + item->x1=x1; + item->y1=y1; + item->x2=x2; + item->y2=y2; +} +void dgt_put(DGT *dgt, DGT_ITEM* item) +/* inserts item in writable file*/ +{ if (!dgt->mode&MAP_OUTPUT) {map_error=ME_INVALID_MODE;} + if (dgt->modified) dgt->next_item(dgt); + memcpy(dgt->buffer,item,14+4*item->npoints); + dgt->modified=1; + dgt->next_item(dgt); +} +void item_set_id(DGT_ITEM *item,long int newID) +{item->ID=newID?newID:1; +} +void dgt_set_point(DGT *dgt,int x,int y) +{ dgt->modified=1; + dgt->buffer->npoints=0; + if (x!=KEEP_OLD_VALUE) dgt->buffer->x1=x; + if (y!=KEEP_OLD_VALUE) dgt->buffer->y1=y; +} +int dgt_add_node(DGT* dgt,int x,int y) +{ DGT_ITEM *buf=dgt->buffer; + POINT *p=dgt->buffer->s+dgt->buffer->npoints-1; + + if (buf->npoints==MAX_LINE_LEN) return DGT_LINE_TOO_LONG; + if (buf->npoints==0||p->x!=x||p->y!=y) + { p++; + p->x=x;p->y=y; + buf->npoints++; + dgt->modified=1; + return 0; + } else return DGT_ZERO_SEGMENT; +} +int dgt_ins_node(DGT *dgt,int index,int x,int y) +{ DGT_ITEM *buf=dgt->buffer; + if (index<0) return 3; + if (buf->npoints==MAX_LINE_LEN) return DGT_LINE_TOO_LONG; + if (index>=buf->npoints) + if (index==buf->npoints) return dgt_add_node(dgt,x,y); + else return DGT_INVALID_NODE; + if ((index==0||buf->s[index-1].x!=x||buf->s[index-1].y!=y) + &&(buf->s[index].x!=x||buf->s[index].y!=y)) + {int i; POINT *s,*s1; + s=buf->s+buf->npoints; + s1=s-1; + for(i=buf->npoints;i>index;i--,*(s--)=*(s1--)); + s->x=x; + s->y=y; + buf->npoints++; + dgt->modified=1; + return 0; + } + else + return DGT_ZERO_SEGMENT; + +} + +int item_mv_node(DGT_ITEM *item,int index,int x,int y) +{ POINT *s=item->s+index,*s1; + if (index>=item->npoints||index<0) return DGT_INVALID_NODE; + + if (x==KEEP_OLD_VALUE) x=s->x; + if (y==KEEP_OLD_VALUE) y=s->y; + if (index>0) {s1=s-1;if (s1->x==x&&s1->y==y) return DGT_ZERO_SEGMENT;} + if (indexnpoints-1) + { s1=s+1;if (s1->x==x&&s1->y==y) return DGT_ZERO_SEGMENT;} + s->x=x; + s->y=y; + return 0; +} +int dgt_rm_node(DGT *dgt,int index) +{ DGT_ITEM *buf=dgt->buffer;int i;POINT *s,*s1,*s2; + if (buf->npoints==2) return DGT_LINE_TOO_SHORT; + if (index<0||index>=buf->npoints) return DGT_INVALID_NODE; + s=buf->s+index; + s1=s+1;s2=s-1; + if(!index&&indexnpoints-1&&s1->x==s2->x&&s1->y==s2->y) + return DGT_ZERO_SEGMENT; + for(i=index+1;inpoints;i++,*(s++)=*(s1++)); + dgt->modified=1; + return 0; +} +int dgt_split(DGT *dgt,int index) +{DGT_ITEM new_line,*buf=dgt->buffer; + POINT *s,*s1; + int i; + if (index<=0||index>=buf->npoints-1) return DGT_BAD_SPLIT_POINT; + s=buf->s+index; + s1=new_line.s; + for(i=index;inpoints;i++,*(s1++)=*(s++)); + new_line.npoints=buf->npoints-index; + buf->npoints=index+1; + dgt_next(dgt); + memcpy(buf,&new_line,14+4*new_line.npoints); + dgt->modified=1; + return 0; +} + +int dgt_cut_segment(DGT *dgt,int index) +{ POINT *s,*s1; + DGT_ITEM new_line,*buf=dgt->buffer; + int i; + if (index<=1||index>=buf->npoints-1) return DGT_BAD_SPLIT_POINT; + s=buf->s+index; + s1=new_line.s; + for(i=index;inpoints;i++,*(s1++)=*(s++)); + new_line.npoints=buf->npoints-index; + buf->npoints=index; + dgt_next(dgt); + memcpy(buf,&new_line,14+4*new_line.npoints); + dgt->modified=1; + return 0; +} + + diff --git a/lib/epp_cache.c b/lib/epp_cache.c new file mode 100644 index 0000000..fb2c7f6 --- /dev/null +++ b/lib/epp_cache.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include "epp.h" +#define BAD_ROW -32769 +int search_cache(EPP *epp,int row); +void position_input(EPP *epp,int row); +void position_cached(EPP *epp, int row)/* makes given line current */ +{ + if (row==epp->currentline) return; + if (!search_cache(epp,row)) + { position_input(epp,row); + } +} +typedef struct CACHE_REC { int row_no; + unsigned short *row_ptr;} cache_rec; +int search_cache(EPP *epp,int row) +{ cache_rec* c;unsigned short int *rp; + int i; + for(c=epp->cache,i=0;icache_size && c->row_no!=BAD_ROW&&c->row_no!=row; + i++) c++; + if (i==epp->cache_size) { + /* Cache is full and row not found. Discard last row */ + c--; + } + rp=c->row_ptr; + i=epp->currentline; + epp->currentline=c->row_no; + /* move all rows one forward */ + for(;c!=epp->cache;c--) *c=*(c-1); + c=epp->cache;/* may be this is not nessecary*/ + c->row_no=i; + c->row_ptr=epp->row; + epp->row=rp; + return epp->currentline==row; +} +void free_cache(EPP *epp) +{ int i;cache_rec *c; + for (i=0,c=epp->cache;icache_size;i++,c++) + free(c->row_ptr); + if (epp->cache) free(epp->cache); + epp->cache=NULL; + epp->cache_size=0; +} +int set_epp_cache(EPP *epp,int lines) +{ int i; cache_rec* c; + if (!(epp->mode&MAP_INPUT)||(epp->mode&MAP_LOADED)) + { map_error = ME_INVALID_MODE; + return 0; + } + free_cache(epp); + /* this is really assignment inside condition*/ + if (lines) + {if (!(epp->cache=calloc(lines, sizeof(cache_rec)))) + { return 0; } + for (i=0,c=epp->cache;irow_ptr=calloc(epp->width+1,sizeof(short)); + c->row_no=-32768; + } + epp->cache_size=lines; + epp->position=position_cached; + } + else epp->position=position_input; + return 1; +} + diff --git a/lib/epp_input.c b/lib/epp_input.c new file mode 100644 index 0000000..4dee819 --- /dev/null +++ b/lib/epp_input.c @@ -0,0 +1,274 @@ +# include "epp.h" +# include +# include +# include +# include +# include "epp_private.h" +int map_error=0; /* after each operation contains error code */ +EPP *open_epp(char *pathname) +/* opens existing EPP file */ +{ + FILE *f; + f=fopen(pathname,"rb"); + if (f==NULL) {map_error=ME_NO_FILE;return NULL;} + return fopen_epp(f); +} + + + +EPP *fopen_epp(FILE* f) +{ + EPPHEADER h; + EPP *epp; +#ifndef LSB_FIRST + short *file_width_table; +#endif + fseek(f,0,SEEK_SET); + if (fread(&h,1,128,f)<128) {fclose(f);map_error=ME_INVALID_FILE;return NULL;}; + + if ((swapshort(h.kind)!=8)&&(swapshort(h.kind)!=16)) {fclose(f);map_error=ME_INVALID_FILE;return NULL;} + epp=malloc(sizeof(EPP)); + if (NULL==epp) { fclose(f);map_error=ME_OUT_OF_MEMORY;return NULL;} + epp->XLeft=swapdouble(h.fcx); + epp->XRight=swapdouble(h.lcx); + epp->YTop=swapdouble(h.fry); + epp->YBottom=swapdouble(h.lry); + epp->fr=swapshort(h.fr); + epp->fc=swapshort(h.fc); + epp->lc=swapshort(h.lc)+1; + epp->lr=swapshort(h.lr)+1; + epp->min=swapshort(h.minclass); + epp->max=swapshort(h.maxclass); + epp->offsite=swapshort(h.offsite); + epp->kind=swapshort(h.kind); + if (epp->kind==8&&(epp->min>255||epp->max>255||epp->min>epp->max)) + {epp->min=0;epp->max=255;} + epp->mode=MAP_INPUT; + epp->position=position_input; + epp->cell_area=swapdouble(h.sfact); + epp->width=(epp->lc-epp->fc+1); + if ((epp->row=calloc(epp->width+1,sizeof(short)))==NULL) + {fclose(f);free(epp);map_error=ME_OUT_OF_MEMORY;return NULL;} + if(( h.access_ptr!=0)&&(h.access_ptr!=0x20202020)) +#ifdef LSB_FIRST + { if((epp->widthtable = calloc(epp->lr-epp->fr,sizeof(short)))==NULL) + {fclose(f);free(epp);map_error=ME_OUT_OF_MEMORY;return NULL;} + fseek(f,128*h.access_ptr,SEEK_SET); + fread(epp->widthtable,epp->lr-epp->fr,sizeof(short),f); + } +#else + { if((epp->widthtable = calloc(epp->lr-epp->fr,sizeof(short)))==NULL || + ( file_width_table = calloc(epp->lr-epp->fr,sizeof(short)))==NULL ) + {fclose(f);free(epp);map_error=ME_OUT_OF_MEMORY;return NULL;} + fseek(f,128*swaplong(h.access_ptr),SEEK_SET); + fread(file_width_table,epp->lr-epp->fr,sizeof(short),f); + swab(file_width_table,epp->widthtable,(epp->lr-epp->fr)*sizeof(short)); + free(file_width_table); + } +#endif + else epp->widthtable=NULL; + if ((epp->packed_buffer=malloc(epp->width*4/3))==NULL) + { free(epp->row);if (epp->widthtable!=NULL) free(epp->widthtable); + fclose(f);free(epp);map_error=ME_OUT_OF_MEMORY;return NULL;} + epp->F=f; + epp->filepos=128; + fseek(f,128,SEEK_SET); + epp->currentline=epp->fr-1; + epp->cache_size=0; + epp->cache=NULL; + return epp; +} +void get_epp_header(EPP* epp, EPPHEADER *h) +/* reads header of EPP file */ +{ +#ifndef LSB_FIRST + EPPHEADER file_header; +#endif + fseek(epp->F,0L,SEEK_SET); +#ifdef LSB_FIRST + fread(h,1,128,epp->F); +#else + fread(&file_header,1,128,epp->F); + swab(&file_header,h,64); + memcpy(&(h->area_unit),&(file_header.area_unit),64); + h->fry=swapdouble(file_header.fry); + h->lry=swapdouble(file_header.lry); + h->fcx=swapdouble(file_header.fcx); + h->lcx=swapdouble(file_header.lcx); + h->sfact=swapdouble(file_header.sfact); + h->access_ptr=swaplong(file_header.access_ptr); +#endif + fseek(epp->F,epp->filepos,SEEK_SET); +} + +char *getcomment(EPP *epp) +/* returns comment of EPP file (address of static buffer,which would be + overriden by next call */ +{static char cmt[33]; + char *endptr; + EPPHEADER h; + get_epp_header(epp,&h); + strncpy(cmt,h.comment,32); + cmt[32]='\0'; + for(endptr=cmt+31;endptr>=cmt&&*endptr==' ';endptr--); + *(++endptr)='\0'; + return cmt; +} + +unsigned short int *epp_getline(EPP *epp,int x,int y) +/* returns pointer to array of integer, which represents line y of raster, + starting from col x. NULL if xmode&MAP_INPUT)){map_error=ME_INVALID_MODE; return NULL;} + if (epp->currentline!=y) + { epp->position(epp,y); + if (map_error) return NULL; + } + return epp->row+(x-epp->fc); +} + +int epp_get(EPP *epp,int x,int y) +/* returns value of given cell, offsite if cell is outside file boundaries */ +{ map_error=0; + if (!(epp->mode&MAP_INPUT)){map_error=ME_INVALID_MODE; return epp->offsite;} + if (!epp_contains(epp,x,y)) {map_error=ME_POINT_OUTSIDE; return epp->offsite;} + if (epp->currentline!=y) + { + epp->position(epp,y); + if (map_error) return epp->offsite; + } + return epp->row[x-epp->fc]; +} +int epp_contains(EPP *epp,int x,int y) +/* returns non-zero if is within boundares of epp */ +{ + return (xlc)&&(x>=epp->fc)&&(ylr)&&(y>=epp->fr); +} +void close_epp(EPP *epp) +{ + if (epp->mode==MAP_OUTPUT) update_header(epp); + if (epp->mode&MAP_CACHED) free_cache(epp); + if (epp->mode&MAP_LOADED) + { char **row=epp->cache; + int i; + for(i=epp->fr;ilr;i++,row++) free(*row); + free(epp->cache); + } + free(epp->packed_buffer); + fclose(epp->F); + free(epp->row); + if (epp->widthtable!=NULL) free (epp->widthtable); + free(epp); +} +/*********** coordinate recalculation **********/ +int epp_row(EPP *epp,double y)/* returns row by given alternate y */ +{ + return floor((y-epp->YTop)/(epp->YBottom-epp->YTop)*(epp->lr-epp->fr))+epp->fr; + +} +int epp_col(EPP *epp,double x)/* returns col for given alternate x */ +{ +return floor((x-epp->XLeft)/(epp->XRight-epp->XLeft)*(epp->lc-epp->fc))+epp->fc; +} +double alt_x(EPP *epp,int col)/* returns alternate x for given col */ +{ +return (epp->XRight-epp->XLeft)*(col-epp->fc)/(epp->lc-epp->fc)+epp->XLeft; +} +double alt_y(EPP *epp,int row)/* returns alternate y for given row */ +{ +return (epp->YBottom-epp->YTop)*(row-epp->fr)/(epp->lr-epp->fr)+epp->YTop; +} +double alt_xc(EPP *epp,int col)/* returns alternate x for given col */ +{ +return (epp->XRight-epp->XLeft)*(col-epp->fc+0.5)/(epp->lc-epp->fc)+epp->XLeft; +} +double alt_yc(EPP *epp,int row)/* returns alternate y for given row */ +{ +return (epp->YBottom-epp->YTop)*(row-epp->fr+0.5)/(epp->lr-epp->fr)+epp->YTop; +} +/**** this was private in pascal version ********/ +void position_input(EPP *epp,int row) +{ int i,offset; + if (epp->currentline==row) return; + if (epp->currentline+1!=row) + { + if (epp->widthtable==NULL) + { + if (row>epp->currentline) + for(i=epp->currentline+1;i<=row;i++) get_row(epp); + else + { fseek(epp->F,128L,SEEK_SET); + epp->filepos=128; + epp->currentline=epp->fr-1; + for(i=epp->fr;ifr;offset+=epp->widthtable[i++]); + fseek(epp->F,offset,SEEK_SET); + epp->filepos=offset; + epp->currentline=--row; + } + } + get_row(epp); + + } + +void unpack_row(unsigned char *row,int *bufpos,EPP *epp) +{register unsigned char a,c,*r,*src; + int i,k; + i=0; + r=row; + src=epp->packed_buffer+(*bufpos); + do { + c=*(src++); + if (c) + { + a=*(src++); + if (c+i>epp->width) c=epp->width-i+1; + for(k=0;kepp->width) c=epp->width-i+1; + for(k=0;kwidth-1)); + *bufpos=src-(epp->packed_buffer); +} +int unpack_buffer(EPP *epp) +{ unsigned short *r; + int i; + int bufpos=0; + if (epp->kind==8) + for(i=0,r=epp->row;iwidth;*(r++)=0,i++); +#ifdef LSB_FIRST + unpack_row((unsigned char *)epp->row,&bufpos,epp); + if (epp->kind==16) + unpack_row(((unsigned char *)epp->row)+1,&bufpos,epp); +#else + unpack_row(((unsigned char *)epp->row)+1,&bufpos,epp); + if (epp->kind==16) + unpack_row((unsigned char *)epp->row,&bufpos,epp); +#endif + return bufpos; +} +void get_row(EPP *epp)/* reads and unpacks row of epp file */ +{ + + if (!(epp->mode & MAP_INPUT)) {map_error=ME_INVALID_MODE;return; } + epp->currentline++; + fread(epp->packed_buffer,epp->widthtable? + epp->widthtable[epp->currentline-epp->fr]:epp->width*4/3,1,epp->F); + epp->filepos+=unpack_buffer(epp); + if (!epp->widthtable) + { + fseek(epp->F,epp->filepos,SEEK_SET); + } +} diff --git a/lib/epp_iter.c b/lib/epp_iter.c new file mode 100644 index 0000000..5cc769f --- /dev/null +++ b/lib/epp_iter.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include "epp_private.h" +int (*EndLineProc)(int row,int seqno,int total); +int for_each_cell(EPP *epp, EPP_ITER_PROC action) +/* performs given operation for each non-offsite cell of existing EPP file + (terminated if action returns non-zero, + or performs operation for each cell of created EPP file, filling cell + by value, returned by action. value parameter in this case always containt + offsite of epp */ +{ int i,j,k,l,rowcount,offsite; + rowcount=epp->lr-epp->fr; + offsite=epp->offsite; + if (epp->mode&MAP_INPUT) + { reset_epp(epp); + for(i=epp->fr,l=1;ilr;i++,l++) + { epp->position(epp,i); + for(k=0,j=epp->fc;jlc;k++,j++) + if (epp->row[k]!=epp->offsite) if ((*action)(j,i,epp->row[k])) return -2; + if (EndLineProc!=NULL) + { + if ((*EndLineProc)(i,l,rowcount)) return -1; + } + } + } + else + { + if (epp->currentline>epp->fr) {map_error=ME_INVALID_PUT;} + for (i=epp->fr,l=1;ilr;i++,l++) + { for(k=0,j=epp->fc;jlc;k++,j++) + epp_put(epp,j,i,(*action)(j,i,offsite)); + if (EndLineProc!=NULL) + { + if ((*EndLineProc)(i,l,rowcount)) return -1; + } + } + } + return 0; +} +long count_cells(EPP *epp, EPP_ITER_PROC condition) +/* calls condition for each non-offsite cell in existing epp file, returns + count of cells, for which condition was non-zero */ +{ int i,j,k,l,rowcount; + long count=0; + rowcount=epp->lr-epp->fr; + if (epp->mode&MAP_OUTPUT) + {map_error=ME_INVALID_MODE; return 0L;} + reset_epp(epp); + for(i=epp->fr,l=1;ilr;i++,l++) + { get_row(epp); + for(k=0,j=epp->fc;jlc;k++,j++) + if (epp->row[k]!=epp->offsite) + { + if ((*condition)(j,i,epp->row[k])) count++; + } + if (EndLineProc!=NULL) + { + if ((*EndLineProc)(i,l,rowcount)) return -1; + } + } + return count; +} + diff --git a/lib/epp_loaded.c b/lib/epp_loaded.c new file mode 100644 index 0000000..48f3747 --- /dev/null +++ b/lib/epp_loaded.c @@ -0,0 +1,327 @@ +#include +#include +#include +#include +#include "epp_private.h" +#define row_buffer ((unsigned char **)epp->cache) + + + +/* + * Opens file in read-write mode and loads raster into memory + * Returns pointer to newly created structure or NULL on error + */ + +EPP *load_epp(char *filename) +{ + FILE *f; + f=fopen(filename,"rb+"); + if (!f) { + map_error=ME_NO_FILE; + return NULL; + } + return fload_epp(f); +} + +/* + * Reads file from given stream into memory. Returns 0 if Ok, -1 if + * something wrong + */ + +int do_load_epp(EPP *epp) +{ char **row,**rr; + int i,j,k,nrows; + unsigned short *width; + unsigned short *new_widthtable=NULL; /* if we have to create widthtable + on the fly, we would keep it here */ + int *counttab; + unsigned short int *pixel; + int oldpos; + + if(!epp->widthtable) { + new_widthtable=calloc(epp->lr-epp->fr,sizeof(short int)); + + } + /* + If we want to have read-write access, we should have read access + first. Switching from write-only to read-write access requires + reset_epp + */ + if(!(epp->mode&MAP_INPUT)) { + map_error=ME_INVALID_MODE; + return -1; + } + /* + We use pointer where cache is otherwise kept + */ + if (epp->mode&MAP_CACHED) { + free_cache(epp); + } + /* + Create array of pointers to file rows + */ + if ((epp->cache=calloc(epp->lr-epp->fr,sizeof(char *)))==NULL) { + map_error=ME_OUT_OF_MEMORY;return -1; + } + /* + Allocate table of frequencies. + */ + /* Note, count of pixels with value==offsite not stored here! */ + epp->counttable=calloc(1<kind,sizeof(int)); + counttab=epp->counttable; + if (epp->counttable==NULL) { + map_error=ME_OUT_OF_MEMORY; + return -1; + } + /* + Allocate and read + */ + /* We are assuming that file is fresh from fopen_epp or reset_epp */ + nrows=epp->lr-epp->fr; + if (epp->widthtable) { + width=epp->widthtable; + } else { + width=new_widthtable; + } + for(row=epp->cache,i=epp->fr,k=1;ilr;width++,i++,row++,k++) + { if((*row=malloc(*width))==NULL) + { for(rr=epp->cache;rrcache); + free(epp->counttable); + map_error=ME_OUT_OF_MEMORY; + return 0; + } + if (EndLineProc) (*EndLineProc)(i,k,nrows); + oldpos=epp->filepos; + get_row(epp); + if (new_widthtable) { + *width=epp->filepos-oldpos; + } + memcpy(*row,epp->packed_buffer,*width); + for (j=epp->fc,pixel=epp->row;jlc;j++,pixel++) { + counttab[*pixel]++; + } + } + /* find out what is actual maximum minimum of file */ + for (i=(1<kind)-1;i>0&&(counttab[i]==0||i==epp->offsite);i--); + epp->max=i; + for (i=0;imax&&(counttab[i]==0||i==epp->offsite);i++); + epp->min=i; + fseek(epp->F,128L,SEEK_SET); + epp->filepos=128; + epp->currentline=epp->fr-1; + epp->modified=0; + epp->mode=MAP_INPUT|MAP_OUTPUT|MAP_LOADED; + epp->position=position_loaded; + return 0; +} +/* + * Recieves stream and loads epp-file from it + * + */ +EPP *fload_epp(FILE *f) +{ EPP *epp; + epp=fopen_epp(f); + if (!epp) { + fclose(f); + return NULL; + } + /* do_load return non-zero on error */ + if (do_load_epp(epp)) { + close_epp(epp); + return NULL; + } + return epp; +} + +int load_new_epp(EPP *epp) +{ + if (epp->mode!=MAP_OUTPUT) { + map_error=ME_INVALID_MODE; + return -1; + } + reset_epp(epp); + if (do_load_epp(epp)) { + close_epp(epp); + return -1; + } + return 0; +} + +void save_row(EPP *epp) +{ int oldsize,newsize,l=epp->currentline-epp->fr; + + if (!epp->modified) return; + + epp->mode|=MAP_MODIFIED; + oldsize=epp->widthtable[l]; + newsize=pack_buffer(epp); + if (oldsize != newsize) { + free(row_buffer[l]); + row_buffer[l]=malloc(newsize); + epp->widthtable[l]=newsize; + } + memcpy(row_buffer[l],epp->packed_buffer,newsize); + epp->modified=0; +} +/* + * Writes loaded file back. Uses stream stored in F field. + * Returns 0 on success, -1 on failure + * Calls EndLineProc after saving each row. + */ + +int save_epp(EPP *epp) +{ + char **row; + unsigned short *width; + int i,k,nrows; + if (!(epp->mode&MAP_LOADED)) { + map_error=ME_INVALID_MODE; + return -1; + } + save_row(epp); + /* If file wasn't modified, don't save. See touch_epp macro in epp.h */ + if (!(epp->mode&MAP_MODIFIED)) { + map_error=0; + return 0; + } + fseek(epp->F,128L,SEEK_SET); + epp->filepos=128; + nrows=epp->lr-epp->fr; + map_error=ME_WRITE_ERROR; + for(i=epp->fr,row=epp->cache,width=epp->widthtable,k=1; + ilr; row++,width++,i++,k++) { + if (EndLineProc) (*EndLineProc)(i,k,nrows); + if (fwrite(*row,1,*width,epp->F)!=*width) + return -1; + epp->filepos+=*width; + } + epp->currentline=epp->lr; + update_header(epp); + epp->position(epp,epp->fr); + map_error=0; + return 0; +} +/* + * Writes epp file to given stream and makes this stream default + * Copies header by hand and then calls save_epp + * + */ +int fsave_epp_as(EPP *epp,FILE *f) +{ EPPHEADER h; + + fread(&h,128,1,epp->F); + fclose(epp->F); + epp->F=f; + fseek(f,0L,SEEK_SET); + if (fwrite(&h,128,1,f)!=128) return 1; + touch_epp(epp); + return save_epp(epp); +} +/* + * Wrapper around fsave_epp_as, which opens stream to pass there + * + */ + +int save_epp_as(EPP *epp,char *newname) +{FILE *f; + f=fopen(newname,"w+"); + if (!f) return 1; + return fsave_epp_as(epp,f); +} +/* + * position_loaded - sets current line of epp to given row. + * To be stored in position field of EPP structure. + * Takes care of saving row, if modified and unpacks neccesary row + * temporary substituting pointer to it into packed_buffer field. + */ +void position_loaded(EPP *epp,int row) +{ + unsigned char *tmp; /* to keep packed buffer */ + + if (row==epp->currentline) return; + save_row(epp); /* save row does nothing if row isn't modified */ + tmp=epp->packed_buffer; + epp->packed_buffer=row_buffer[row-epp->fr]; + unpack_buffer(epp); + epp->modified=0; + epp->packed_buffer=tmp; + epp->currentline=row; + map_error=0; +} +/* + * epp_expand - converts loaded 8-bit file into 16-bit one + * by appending packed string of zeros to each row + * return 0 on succes -1 of failure. + * errors: + * ME_INVALID_MODE - file is not loaded + * ME_INVALID_FILE - file already have maximum depth + * ME_OUT_OF_MEMORY - no comments + */ + +int epp_expand (EPP *epp) +{ unsigned char *tail; /* here prepaired packed tail is kept*/ + /* ATTENCTION, packtail is VERY poisoneuos fish*/ + int tail_length; + unsigned char *byteptr, + **row;/* pointer to pointer to current packed row */ + int i; + unsigned short *width; /* pointer to current element of widthtable */ + EPPHEADER h; + /* check if passed file is suitable for expanding */ + if (!(epp->mode&MAP_LOADED)) { + map_error=ME_INVALID_MODE; + return -1; + } + if (epp->kind==16) { + /* nowhere to expand */ + map_error=ME_INVALID_FILE; + return -1; + } + + /* any error, which occurs further, should be ME_OUT_OF_MEMORY*/ + map_error=ME_OUT_OF_MEMORY; + + /* prepare packed tail */ + tail_length=((epp->lc-epp->fc+254)/255)*2; + tail=malloc(tail_length); + if (!tail) return -1; + for (i=epp->lc-epp->fc,byteptr=tail;i>0;i-=255) { + int count=i>255?255:i; + *(byteptr++)=count; + *(byteptr++)=0; + } + /* reallocate rows */ + + for (i=epp->fc,width=epp->widthtable,row=row_buffer; + ilc;i++,row++,width++) { + unsigned char *tmp=realloc(*row,*width+tail_length); + if (!tmp) { + /* realloc fails, trying to restore status quo */ + for (i--,width--;i>=epp->fc;i--,width--) + *width-=tail_length; + return -1; + } + /* fill newly allocated memory */ + memcpy(tmp+*width,tail,tail_length); + /* store new row ptr and new width */ + *row=tmp; + *width+=tail_length; + /* Width overflow is not checked, becouse packed string of zeros + couldn't overflow even most lengthly 8-bit row */ + } + /* fix epp->kind value */ + epp->kind+=8; + /* and write it to disk immediately, becouse no one cares about + updating this field in header, but this function */ + fseek(epp->F,0,SEEK_SET); + fread(&h,128,1,epp->F); + /* read errors are not checked, becouse thay are quite improbable */ + h.kind=swapshort(epp->kind); + fseek(epp->F,0,SEEK_SET); + fwrite(&h,128,1,epp->F); + /* Now we are ready to exit successifully */ + map_error=0; + return 0; +} + diff --git a/lib/epp_output.c b/lib/epp_output.c new file mode 100644 index 0000000..f99156a --- /dev/null +++ b/lib/epp_output.c @@ -0,0 +1,525 @@ +# define _POSIX_SOURCE +/* I don't know what it means, but otherwise fileno function is not declared + in stdio.h + */ +#include +#include +#include +# define __USE_MISC +/* Even more strange define. It is neccesary to access ftruncate function */ +#include +# undef __USE_MISC +#include +# include +# include +# include "epp_private.h" +int Create16bit=0; /* if non-zero, all created EPP files would be 16 bit*/ + +EPP *creat_epp(char *pathname,int first_col,int first_row,int last_col, + int last_row, double AXLeft,double AYTop, double AXRight, + double AYBottom, int scale, int base, int offsite) +/* creating epp file from scratch. All fields which are not defined as + parameters, are filled by default values. Kind depends of global variable + Create16bit */ +{ FILE *f; + f=fopen(pathname,"wb+"); + if (f==NULL) {map_error=ME_CREATE_ERROR;return NULL;} + return fcreat_epp(f,first_col,first_row,last_col,last_row,AXLeft,AYTop, + AXRight,AYBottom,scale,base,offsite); +} + + +EPP *fcreat_epp(FILE* f,int first_col,int first_row,int last_col, + int last_row, double AXLeft,double AYTop, double AXRight, + double AYBottom, int scale, int base, int offsite) + +{ EPPHEADER h; + EPP *epp; + int i; + unsigned short int *r; + memset(&h,128,0); + if ((epp=malloc(sizeof(EPP)))==NULL) {fclose(f);map_error=ME_OUT_OF_MEMORY; + return NULL;} + h.fcx=swapdouble(epp->XLeft=AXLeft); + h.lcx=swapdouble(epp->XRight=AXRight); + h.lry=swapdouble(epp->YBottom=AYBottom); + h.fry=swapdouble(epp->YTop=AYTop); + h.fc=swapshort(epp->fc=first_col); + h.fr=swapshort(epp->fr=first_row); + h.lc=swapshort(epp->lc=last_col);epp->lc++; + h.lr=swapshort(epp->lr=last_row);epp->lr++; + h.scale=swapshort(scale==0?100:scale); + h.base=swapshort(base); + h.offsite=swapshort(epp->offsite=offsite); + epp->width=last_col-first_col+2; + if ((epp->row=calloc(epp->width+1,sizeof(short)))==NULL) + {free(epp);fclose(f);map_error=ME_OUT_OF_MEMORY;return NULL;} + epp->min=65535; + epp->max=0; + for(r=epp->row,i=0;i<=epp->width;*(r++)=offsite,i++); + if((epp->widthtable=calloc(epp->lr-epp->fr,sizeof(short)))==NULL) + {free(epp->row);free(epp);fclose(f);map_error=ME_OUT_OF_MEMORY;return NULL;} + if ((epp->packed_buffer=malloc(epp->width*4/3))==NULL) + { free(epp->row);if (epp->widthtable!=NULL) free(epp->widthtable); + fclose(f);free(epp);map_error=ME_OUT_OF_MEMORY;return NULL;} + epp->F=f; + epp->mode=MAP_OUTPUT; + epp->position=position_output; + h.kind=swapshort(epp->kind=Create16bit?16:8); + h.access_ptr=0; + h.sfact=swapdouble(epp->cell_area=fabs(AXRight-AXLeft)/(last_col-first_col+1)* + fabs(AYBottom-AYTop)/(last_row-first_row+1)); + memset(h.comment,32,' '); + fwrite(&h,128,1,f); + epp->filepos=128; + epp->currentline=epp->fr; + epp->cache_size=0; + epp->cache=NULL; + return epp; +} +EPP *creat_epp_as(char *pathname,EPP *pattern) +{ FILE *f; + f=fopen(pathname,"wb+"); + if (f==NULL) {map_error=ME_CREATE_ERROR;return NULL;} + return fcreat_epp_as(f,pattern); +} +EPP *fcreat_epp_as(FILE *f,EPP *pattern) +/* creates new epp file, copiing a most header fields from given file */ +{ EPPHEADER h; + EPP *epp; + get_epp_header(pattern,&h); + epp=fcreat_epp(f,h.fc,h.fr,h.lc,h.lr, + pattern->XLeft,pattern->YTop,pattern->XRight, + pattern->YBottom,h.scale,h.base,h.offsite); + if (epp!=NULL) + { char cmt[33]; + setcomment(epp,strncpy(cmt,h.comment,32)); + } + return epp; +} +void setcomment(EPP *epp,char *comment) +/* change comment of epp file, which was open by creat_epp or creat_epp_as */ +{ EPPHEADER h; + int i; + if((epp->mode & MAP_OUTPUT) == 0) + { map_error=ME_INVALID_MODE; return; } + fseek(epp->F,0L,SEEK_SET); + fread(&h,128,1,epp->F); + strncpy(h.comment,comment,32); + for(i=strlen(comment);i<32;i++) h.comment[i]=' '; + fseek(epp->F,0L,SEEK_SET); + fwrite(&h,128,1,epp->F); + fseek(epp->F,epp->filepos,SEEK_SET); +} +void change_epp_header(EPP *epp,EPPHEADER h) +{ + EPPHEADER fh; + fseek(epp->F,0L,SEEK_SET); + fread(&fh,128,1,epp->F); + fh.fcx=swapdouble(h.fcx); + fh.lcx=swapdouble(h.lcx); + fh.fry=swapdouble(h.fry); + fh.lry=swapdouble(h.lry); + fh.base=swapshort(h.base); + fh.scale=swapshort(h.scale); + fh.offsite=swapshort(epp->offsite=h.offsite); + fh.sfact=swapdouble(h.sfact); + fh.coord_sys=h.coord_sys; + fh.area_unit=h.area_unit; + memcpy(h.comment,fh.comment,32); + fseek(epp->F,0L,SEEK_SET); + fwrite(&fh,128,1,epp->F); + fseek(epp->F,epp->filepos,SEEK_SET); +} + +int shift_epp(EPP *epp,int new_fr,int new_fc) +{int new_lr,new_lc,result; + EPPHEADER h; + new_lr=epp->lr-epp->fr+new_fr; + new_lc=epp->lc-epp->fc+new_fc; + if ((new_fr<-32767)||(new_fc<-32767)||(new_lc>32768)||(new_lc>32768)) + return 0; + if (epp->mode & MAP_OUTPUT) + { + fseek(epp->F,0,SEEK_SET); + fread(&h,128,1,epp->F); + h.fc=swapshort(epp->fc=new_fc); + h.fr=swapshort(epp->fr=new_fr); + h.lr=swapshort((epp->lr=new_lr)-1); + h.lc=swapshort((epp->lc=new_lc)-1); + fseek(epp->F,0,SEEK_SET); + result=(fwrite(&h,128,1,epp->F)==128); + fseek(epp->F,epp->filepos,SEEK_SET); + } + else result=1; + if (result) + { epp->fr=new_fr; + epp->lr=new_lr; + epp->fc=new_fc; + epp->lc=new_lc; + } + return result; +} + + +void reset_epp(EPP *epp) +/* reopens epp file for reading. if file was in create mode, fills all non-filled +lines by offsite */ +{ if (epp->mode==MAP_OUTPUT) + { update_header(epp); + epp->mode=MAP_INPUT; + fseek(epp->F,128L,SEEK_SET); + epp->filepos=128L; + epp->currentline=epp->fr-1; + epp->position=position_input; + } + else (*epp->position)(epp,epp->fr); +} +/* + * update_header - writes changes into header and writes width table. + * for write-only files also fills all unfilled rows by offsite. + * Modifies following field in file header: + * 1. access_ptr (to point to newly written width table) + * 2. maxclass + * 3. minclass + * 4. offsite (so we can play with its value) + * 5. date and time stamp + */ +void update_header(EPP *epp)/* writes changes into header */ +{ + int i; + unsigned short int *r; + struct tm *t; + int table_offset; +#ifndef LSB_FIRST + short *fwt; +#endif + time_t timesec; + EPPHEADER h; + /* For write-only file fill rest of it by offsite */ + if(epp->mode==MAP_OUTPUT) { + put_row(epp); + for (r=epp->row,i=0;iwidth;*(r++)=epp->offsite,i++); + for (i=epp->currentline;ilr;i++){put_row(epp);} + } + memset(&h,128,0); + /* width table should be aligned to 128 byte boundary */ + if((i=(epp->filepos % 128))) fwrite(&h,128-i,1,epp->F); + table_offset=ftell(epp->F); +#ifdef LSB_FIRST + fwrite(epp->widthtable,epp->lr-epp->fr,sizeof(short),epp->F); +#else + fwt=calloc(epp->lr-epp->fr,sizeof(short)); + swab(epp->widthtable,fwt,epp->lr-epp->fr); + fwrite(fwt,epp->lr-epp->fr,sizeof(short),epp->F); + free(fwt); +#endif + if ((i=(ftell(epp->F)%128))) fwrite(&h,128-i,1,epp->F); + /* I don't know how old software would behave if file size is + not multiplication of 128, so write few bytes of junk */ + if ((i=(ftell(epp->F)%128))) fwrite(&h,128-i,1,epp->F); + /* Truncate file here.*/ + ftruncate(fileno(epp->F),ftell(epp->F)); + /* Now we are ready to write header. */ + fseek(epp->F,0,SEEK_SET); + fread(&h,128,1,epp->F); + h.access_ptr=swaplong(table_offset / 128); + h.offsite=swapshort(epp->offsite); + h.maxclass=swapshort(epp->max); + h.minclass=swapshort(epp->min); + /* correct date/time values */ + time(×ec); + t=localtime(×ec); + sprintf(h.date,"%02d/%02d/%02d",t->tm_mon+1,t->tm_mday,t->tm_year); + for(i=strlen(h.date);i<16;h.date[i++]=' '); + sprintf(h.time,"%02d:%02d:%02d",t->tm_hour,t->tm_min,t->tm_sec); + for(i=strlen(h.time);i<8;h.time[i++]=' '); + fseek(epp->F,0L,SEEK_SET); + fwrite(&h,128,1,epp->F); + epp->filepos=128; + epp->currentline=epp->fr-1; +} +/* + * Perform actual eppl packing algoritm. Fetch each second byte from + * source row, so pack_buffer can call it twice for 16-bit files + * row is row buffer to pack (may be pointer to second byte of actual + * row buffer) bufpos - stores offset in epp->packed_buffer, where to + * start packing. On exit it contains offset of next byte after last packed + */ + +void pack_row(unsigned char *row,int *bufpos,EPP *epp) +{ + register unsigned char c, *dest, *i; + register unsigned char *stop; + register unsigned char *j, *k; + stop=row+((epp->width-1)<<1); + dest=epp->packed_buffer+(*bufpos); + for(i=row;i1) + { *(dest++)=c;*(dest++)=*i; + i=j; + } + else + { for(j=i+2;(j1) + { *(dest++)=0;} + *(dest++)=c; + for (k=i;kpacked_buffer); +} +/* + * Stores content of epp->row into epp->packed_buffer by calling + * pack_row epp->kind/8 times. + * Updates width table. + */ +int pack_buffer(EPP *epp) +{int bufpos=0; + if (!(epp->mode & MAP_OUTPUT)) {map_error=ME_INVALID_MODE; return 0;} +#ifdef LSB_FIRST + /* Intel architecture - first byte of short is LSB. store it first */ + pack_row((unsigned char *)epp->row,&bufpos,epp); + if (epp->kind==16) + pack_row(((unsigned char *)epp->row)+1,&bufpos,epp); +#else + /* Sparc architecture - store second byte of short first, first byte last*/ + pack_row(((unsigned char *)epp->row)+1,&bufpos,epp); + if (epp->kind==16) + pack_row(((unsigned char *)epp->row),&bufpos,epp); +#endif + /* update width table */ + epp->widthtable[epp->currentline-epp->fr]=bufpos; + return bufpos; +} +/* + * Packs and writes row + * + */ +void put_row(EPP *epp) +{ int l; + if (!(epp->mode & MAP_OUTPUT)) { + map_error=ME_INVALID_MODE; + return; + } + l=pack_buffer(epp); + if (fwrite(epp->packed_buffer,1,l,epp->F)!=l) { + map_error=ME_WRITE_ERROR; + return; + } + epp->filepos+=l; + epp->currentline++; +} +/* + * Positions write-only file. To be stored in position field of EPP structure. + * If row > current fills all rows between current and given by offsite. + */ +void position_output(EPP *epp,int row) +{ + unsigned short *r; + int i; + + if (row==epp->currentline) + return; + if (!epp_contains(epp,epp->fc,row)) { + map_error=ME_POINT_OUTSIDE; return; + } + if (rowcurrentline) { + map_error=ME_INVALID_PUT; + return; + } + /* store current row */ + map_error=0; + put_row(epp); + if (map_error) return; + /* fill row buffer with offsite */ + for (r=epp->row,i=epp->fc;ilc;i++,r++)*r=epp->offsite; + while (epp->currentlinemode!=MAP_OUTPUT) { + map_error=ME_INVALID_MODE; + return; + } + reset_epp(source); + fseek(source->F,0L,SEEK_SET); + fread(&h,128,1,source->F); + h.kind=swapshort(8); + if (source->offsite>255&&source->offsite!=65535) { + h.offsite=swapshort(source->offsite & 0xff); + } + dest=fopen(filename,"w+"); + if (!dest) { + map_error=ME_WRITE_ERROR; + return; + } + fwrite(&h,128,1,dest); + nrows=source->lr-source->fr; + for(i=source->fr,j=0;ilr;i++,j++) { + if (EndLineProc) + (*EndLineProc)(i,j+1,nrows); + fread(source->packed_buffer,source->widthtable[j],1,source->F); + bufpos=0; + unpack_row((unsigned char *)source->row,&bufpos,source); + source->widthtable[j]=bufpos; + fwrite(source->packed_buffer,bufpos,1,dest); + } + memset(&h,128,0); + /* This is assignment, not condition */ + if((i=ftell(dest) % 128)) fwrite(&h,128-i,1,dest); + access_ptr=ftell(dest)/128; +#ifdef LSB_FIRST + fwrite(source->widthtable,nrows,2,dest); +#else + swapped_bytes=malloc(nrows*2); + swab(source->widthtable,swapped_bytes,nrows*2); + fwrite(swapped_bytes,nrows,2,dest); +#endif + fseek(dest,0L,SEEK_SET); + fread(&h,128,1,dest); + h.access_ptr=swaplong(access_ptr); + fseek(dest,0L,SEEK_SET); + fwrite(&h,128,1,dest); + fclose(dest); + close_epp(source); +} + +/* fills given cell by value. File must be in create mode. if line is not + current, does nothing if line above current or fills all lines between current + and specified by offsite +*/ +void epp_put(EPP *epp,int x,int y,int value) +{ + unsigned short *pixel; + + if (!(epp->mode&MAP_OUTPUT)){ + map_error=ME_INVALID_MODE; return ; + } + + if (!epp_contains(epp,x,y)) { + map_error=ME_POINT_OUTSIDE; return; + } + + if (epp->currentline!=y) { + (*epp->position)(epp,y); + } + if (epp->counttable) { + /* if we are supporting counting of cell values*/ + pixel=epp->row+(x-epp->fc); + /* # maintain table */ + epp->counttable[*pixel]--; + epp->counttable[value]++; + *pixel=value; + /* # check if maximum or minimum changed */ + if (value>epp->max&&value!=epp->offsite) { + epp->max=value; + } else { + while ((epp->max==epp->offsite||!epp->counttable[epp->max])&& + epp->max) + epp->max--; + } + if (valuemin&&value!=epp->offsite) { + epp->min=value; + } else { + while ((epp->min==epp->offsite||!epp->counttable[epp->min])&& + epp->minmax) + epp->min++; + } + } else { + /* we can only change max/min if value is outside them */ + epp->row[x-epp->fc]=value; + if (value!=epp->offsite) { + if ((unsigned)value>epp->max) epp->max=value; + if ((unsigned)valuemin) epp->min=value; + } + } + epp->modified=1; +} +/* fills range of adjanced cells in same row with same value + In create mode complains, if row is above current. + If any point of specified range is outside physical file limits, + complains and does nothing. +*/ +void epp_putline(EPP *epp,int x1,int x2,int y,int value) +{ + unsigned short *pixel; + int i; + if (!(epp->mode&MAP_OUTPUT)){ + map_error=ME_INVALID_MODE; return ; + } + + map_error=0; + /* Positioning to desired row */ + if (epp->currentline!=y) { + (*epp->position)(epp,y); + } + /* return if row is invalid */ + if (map_error) return; + /* if line exceeds file limits, truncate it */ + if (x1fc) x1=epp->fc; + if (x2>=epp->lc) x2=epp->lc-1; + /* if nothing left, return error */ + if (x1>x2) { + map_error=ME_POINT_OUTSIDE; + return; + } + if (epp->counttable) { + /* if we are supporting counting of cell values*/ + for (pixel=epp->row+(x1-epp->fc),i=x1;i<=x2;i++,pixel++) { + /* # maintain table */ + epp->counttable[*pixel]--; + *pixel=value; + } + epp->counttable[value]+=x2-x1+1; + /* # check if maximum or minimum changed */ + if (value>epp->max&&value!=epp->offsite) { + epp->max=value; + } else { + while ((epp->max==epp->offsite||!epp->counttable[epp->max])&& + epp->max) + epp->max--; + } + if (valuemin&&value!=epp->offsite) { + epp->min=value; + } else { + while ((epp->min==epp->offsite||!epp->counttable[epp->min])&& + epp->minmax) + epp->min++; + } + } else { + /* we can only change max/min if value is outside them */ + for (pixel=epp->row+(x1-epp->fc),i=x1;i<=x2;i++,pixel++) { + *pixel=value; + } + if (value!=epp->offsite) { + if ((unsigned)value>epp->max) epp->max=value; + if ((unsigned)valuemin) epp->min=value; + } + } + epp->modified=1; +} diff --git a/lib/epp_private.h b/lib/epp_private.h new file mode 100644 index 0000000..b21248b --- /dev/null +++ b/lib/epp_private.h @@ -0,0 +1,20 @@ +#ifndef EPP_PRIVATE_H +#define EPP_PRIVATE_H +/* decladed in epp_input.c */ +void position_input(EPP* epp,int row); +void unpack_row(unsigned char *row,int *bufpos,EPP *epp); +int unpack_buffer(EPP *epp); + +/* declared in epp_output.c */ +void position_output(EPP* epp,int row); +void update_header(EPP *epp);/* writes changes into header */ +int pack_buffer(EPP *epp); + +/* declared in epp_cached.c */ +extern void free_cache(EPP *epp); +int search_cache(EPP *epp,int row); +void position_cached(EPP* epp,int row); + +/* declared in epp_loaded.c */ +void position_loaded(EPP *epp,int row); +#endif diff --git a/lib/file_utils.c b/lib/file_utils.c new file mode 100644 index 0000000..0312dac --- /dev/null +++ b/lib/file_utils.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include "epp.h" +char* default_ext(const char *name,const char *ext) +{static char buf [1024]; + strcpy(buf,name); + if (strcmp(buf+strlen(buf)-strlen(ext),ext)) { + struct stat statbuf; + strcat(buf,ext); + if (stat(buf,&statbuf)&&!stat(name,&statbuf)) { + strcpy(buf,name); + } + } + return buf; +} + +char *force_ext(const char *name,const char *ext) +{static char buf [1024]; + char *last_ext; + strcpy(buf,name); + if ((last_ext=strrchr(buf,'.'))&&last_ext>strrchr(buf,'/')) *last_ext='\0'; + return strcat(buf,ext); +} +char *last_ext(const char *name) +{static char buf[128]; + char *extptr; + extptr=strrchr(name,'.'); + if(!extptr) return NULL; + if (strchr(extptr,'/')) return NULL; + return strcpy(buf,extptr); +} + +int signal_recieved; +int show_progress(int row,int seqno,int total) +{ fprintf(stderr,"\rProcessing row %d of %d",seqno,total); + fflush(stderr); + return (signal_recieved); +} +int show_percent(int row,int seqno,int total) +{ static int already_done; + int percent=seqno*1000/total; + if (percent!=already_done) + { fprintf(stderr,"\r%3d.%1d%% complete",percent/10,percent%10); + fflush(stderr); + already_done=percent; + } + return signal_recieved; +} + + +int check_int(int row,int seqno,int total) +{ + return (signal_recieved); +} + +void int_handler(int sig_no) +{ signal_recieved=sig_no; + signal(sig_no,int_handler); +} + +void install_progress_indicator(int (*show_progress)(int,int,int)) +{ signal_recieved=0; + signal(SIGINT,int_handler); + EndLineProc=show_progress; +} + +int clear_progress(int success) +{ if (EndLineProc) + { fprintf(stderr,"\r%s \n",success?"Aborted":"Done"); + signal(SIGINT,SIG_DFL); + } + return success; +} +void show_version(char *name,char *RCS_ID) +{ char ver[25],*version=RCS_ID+1; + for(;*version!='$' && *version!=':';version++); + strcpy(ver,version); + version=strrchr(ver,'$'); + if (version) *version=0; + printf("SoftWeyr %c%s. Version %s\n",toupper(name[0]),name+1,ver); + exit(0); + +} diff --git a/lib/gnu_lib/getopt.c b/lib/gnu_lib/getopt.c new file mode 100644 index 0000000..7a4673b --- /dev/null +++ b/lib/gnu_lib/getopt.c @@ -0,0 +1,757 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + 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 2, 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, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include +#else +#include "config.h" +#endif +#endif + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +/* This tells Alpha OSF/1 not to define a getopt prototype in . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#endif /* GNU C library. */ + +/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a + long-named option. Because this is not POSIX.2 compliant, it is + being phased out. */ +/* #define GETOPT_COMPAT */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = 0; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. + (Supposedly there are some machines where it might get a warning, + but changing this conditional to __STDC__ is too risky.) */ +#ifdef __GNUC__ +#ifdef IN_GCC +#include "gstddef.h" +#else +#include +#endif +extern size_t strlen (const char *); +#endif + +#endif /* GNU C library. */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + int option_index; + + optarg = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + if (optind == 0) + { + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + } + + if (nextchar == NULL || *nextchar == '\0') + { + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Now skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + optind++; + last_nonopt = optind; + } + + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + if (longopts != NULL + && ((argv[optind][0] == '-' + && (argv[optind][1] == '-' || long_only)) +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + )) + { + const struct option *p; + char *s = nextchar; + int exact = 0; + int ambig = 0; + const struct option *pfound = NULL; + int indfound; + + while (*s && *s != '=') + s++; + + /* Test all options for either exact match or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp (p->name, nextchar, s - nextchar)) + { + if (s - nextchar == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*s) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = s + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { +#if 0 + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + argv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); +#endif + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = 0; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { +#if 0 + fprintf (stderr, "%s: option `-%c' requires an argument\n", + argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/lib/gnu_lib/getopt.h b/lib/gnu_lib/getopt.h new file mode 100644 index 0000000..d751c6b --- /dev/null +++ b/lib/gnu_lib/getopt.h @@ -0,0 +1,132 @@ +/* Declarations for getopt. + Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if __STDC__ +#if defined(__GNU_LIBRARY__) +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* not __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* not __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/lib/gnu_lib/getopt1.c b/lib/gnu_lib/getopt1.c new file mode 100644 index 0000000..f784b57 --- /dev/null +++ b/lib/gnu_lib/getopt1.c @@ -0,0 +1,187 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + 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 2, 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, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include +#else +#include "config.h" +#endif +#endif + +#include "getopt.h" + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include +#else +char *getenv (); +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +#include + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == EOF) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/lib/gnu_lib/regex.c b/lib/gnu_lib/regex.c new file mode 100644 index 0000000..81b06ff --- /dev/null +++ b/lib/gnu_lib/regex.c @@ -0,0 +1,5171 @@ +/* Extended regular expression matching and search library, + version 0.12. + (Implements POSIX draft P10003.2/D11.2, except for + internationalization features.) + + Copyright (C) 1993 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 2, 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* AIX requires this to be the first thing in the file. */ +#if defined (_AIX) && !defined (REGEX_MALLOC) + #pragma alloca +#endif + +#define _GNU_SOURCE + +#ifdef HAVE_CONFIG_H +#if defined (CONFIG_BROKETS) +/* We use instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include +#else +#include "config.h" +#endif +#endif + +/* We need this for `regex.h', and perhaps for the Emacs include files. */ +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* The `emacs' switch turns on certain matching commands + that make sense only in Emacs. */ +#ifdef emacs + +#include "lisp.h" +#include "buffer.h" +#include "syntax.h" + +/* Emacs uses `NULL' as a predicate. */ +#undef NULL + +#else /* not emacs */ + +#ifdef STDC_HEADERS +#include +#else +char *malloc (); +char *realloc (); +#endif + + +/* We used to test for `BSTRING' here, but only GCC and Emacs define + `BSTRING', as far as I know, and neither of them use this code. */ +#if HAVE_STRING_H || STDC_HEADERS +#include +#ifndef bcmp +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#endif +#ifndef bcopy +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#endif +#ifndef bzero +#define bzero(s, n) memset ((s), 0, (n)) +#endif +#else +#include +#endif + +/* Define the syntax stuff for \<, \>, etc. */ + +/* This must be nonzero for the wordchar and notwordchar pattern + commands in re_match_2. */ +#ifndef Sword +#define Sword 1 +#endif + +#ifdef SYNTAX_TABLE + +extern char *re_syntax_table; + +#else /* not SYNTAX_TABLE */ + +/* How many characters in the character set. */ +#define CHAR_SET_SIZE 256 + +static char re_syntax_table[CHAR_SET_SIZE]; + +static void +init_syntax_once () +{ + register int c; + static int done = 0; + + if (done) + return; + + bzero (re_syntax_table, sizeof re_syntax_table); + + for (c = 'a'; c <= 'z'; c++) + re_syntax_table[c] = Sword; + + for (c = 'A'; c <= 'Z'; c++) + re_syntax_table[c] = Sword; + + for (c = '0'; c <= '9'; c++) + re_syntax_table[c] = Sword; + + re_syntax_table['_'] = Sword; + + done = 1; +} + +#endif /* not SYNTAX_TABLE */ + +#define SYNTAX(c) re_syntax_table[c] + +#endif /* not emacs */ + +/* Get the interface, including the syntax bits. */ +#include "regex.h" + +/* isalpha etc. are used for the character classes. */ +#include + +/* Jim Meyering writes: + + "... Some ctype macros are valid only for character codes that + isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when + using /bin/cc or gcc but without giving an ansi option). So, all + ctype uses should be through macros like ISPRINT... If + STDC_HEADERS is defined, then autoconf has verified that the ctype + macros don't need to be guarded with references to isascii. ... + Defining isascii to 1 should let any compiler worth its salt + eliminate the && through constant folding." */ +#if ! defined (isascii) || defined (STDC_HEADERS) +#undef isascii +#define isascii(c) 1 +#endif + +#ifdef isblank +#define ISBLANK(c) (isascii (c) && isblank (c)) +#else +#define ISBLANK(c) ((c) == ' ' || (c) == '\t') +#endif +#ifdef isgraph +#define ISGRAPH(c) (isascii (c) && isgraph (c)) +#else +#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c)) +#endif + +#define ISPRINT(c) (isascii (c) && isprint (c)) +#define ISDIGIT(c) (isascii (c) && isdigit (c)) +#define ISALNUM(c) (isascii (c) && isalnum (c)) +#define ISALPHA(c) (isascii (c) && isalpha (c)) +#define ISCNTRL(c) (isascii (c) && iscntrl (c)) +#define ISLOWER(c) (isascii (c) && islower (c)) +#define ISPUNCT(c) (isascii (c) && ispunct (c)) +#define ISSPACE(c) (isascii (c) && isspace (c)) +#define ISUPPER(c) (isascii (c) && isupper (c)) +#define ISXDIGIT(c) (isascii (c) && isxdigit (c)) + +#ifndef NULL +#define NULL 0 +#endif + +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +#undef SIGN_EXTEND_CHAR +#if __STDC__ +#define SIGN_EXTEND_CHAR(c) ((signed char) (c)) +#else /* not __STDC__ */ +/* As in Harbison and Steele. */ +#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) +#endif + +/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we + use `alloca' instead of `malloc'. This is because using malloc in + re_search* or re_match* could cause memory leaks when C-g is used in + Emacs; also, malloc is slower and causes storage fragmentation. On + the other hand, malloc is more portable, and easier to debug. + + Because we sometimes use alloca, some routines have to be macros, + not functions -- `alloca'-allocated space disappears at the end of the + function it is called in. */ + +#ifdef REGEX_MALLOC + +#define REGEX_ALLOCATE malloc +#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) + +#else /* not REGEX_MALLOC */ + +/* Emacs already defines alloca, sometimes. */ +#ifndef alloca + +/* Make alloca work the best possible way. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#if HAVE_ALLOCA_H +#include +#else /* not __GNUC__ or HAVE_ALLOCA_H */ +#ifndef _AIX /* Already did AIX, up at the top. */ +char *alloca (); +#endif /* not _AIX */ +#endif /* not HAVE_ALLOCA_H */ +#endif /* not __GNUC__ */ + +#endif /* not alloca */ + +#define REGEX_ALLOCATE alloca + +/* Assumes a `char *destination' variable. */ +#define REGEX_REALLOCATE(source, osize, nsize) \ + (destination = (char *) alloca (nsize), \ + bcopy (source, destination, osize), \ + destination) + +#endif /* not REGEX_MALLOC */ + + +/* True if `size1' is non-NULL and PTR is pointing anywhere inside + `string1' or just past its end. This works if PTR is NULL, which is + a good thing. */ +#define FIRST_STRING_P(ptr) \ + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) + +/* (Re)Allocate N items of type T using malloc, or fail. */ +#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) +#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +#define RETALLOC_IF(addr, n, t) \ + if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) +#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) + +#define BYTEWIDTH 8 /* In bits. */ + +#define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +typedef char boolean; +#define false 0 +#define true 1 + +/* These are the command codes that appear in compiled regular + expressions. Some opcodes are followed by argument bytes. A + command code can specify any interpretation whatsoever for its + arguments. Zero bytes may appear in the compiled regular expression. + + The value of `exactn' is needed in search.c (search_buffer) in Emacs. + So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of + `exactn' we use here must also be 1. */ + +typedef enum +{ + no_op = 0, + + /* Followed by one byte giving n, then by n literal bytes. */ + exactn = 1, + + /* Matches any (more or less) character. */ + anychar, + + /* Matches any one char belonging to specified set. First + following byte is number of bitmap bytes. Then come bytes + for a bitmap saying which chars are in. Bits in each byte + are ordered low-bit-first. A character is in the set if its + bit is 1. A character too large to have a bit in the map is + automatically not in the set. */ + charset, + + /* Same parameters as charset, but match any character that is + not one of those specified. */ + charset_not, + + /* Start remembering the text that is matched, for storing in a + register. Followed by one byte with the register number, in + the range 0 to one less than the pattern buffer's re_nsub + field. Then followed by one byte with the number of groups + inner to this one. (This last has to be part of the + start_memory only because we need it in the on_failure_jump + of re_match_2.) */ + start_memory, + + /* Stop remembering the text that is matched and store it in a + memory register. Followed by one byte with the register + number, in the range 0 to one less than `re_nsub' in the + pattern buffer, and one byte with the number of inner groups, + just like `start_memory'. (We need the number of inner + groups here because we don't have any easy way of finding the + corresponding start_memory when we're at a stop_memory.) */ + stop_memory, + + /* Match a duplicate of something remembered. Followed by one + byte containing the register number. */ + duplicate, + + /* Fail unless at beginning of line. */ + begline, + + /* Fail unless at end of line. */ + endline, + + /* Succeeds if at beginning of buffer (if emacs) or at beginning + of string to be matched (if not). */ + begbuf, + + /* Analogously, for end of buffer/string. */ + endbuf, + + /* Followed by two byte relative address to which to jump. */ + jump, + + /* Same as jump, but marks the end of an alternative. */ + jump_past_alt, + + /* Followed by two-byte relative address of place to resume at + in case of failure. */ + on_failure_jump, + + /* Like on_failure_jump, but pushes a placeholder instead of the + current string position when executed. */ + on_failure_keep_string_jump, + + /* Throw away latest failure point and then jump to following + two-byte relative address. */ + pop_failure_jump, + + /* Change to pop_failure_jump if know won't have to backtrack to + match; otherwise change to jump. This is used to jump + back to the beginning of a repeat. If what follows this jump + clearly won't match what the repeat does, such that we can be + sure that there is no use backtracking out of repetitions + already matched, then we change it to a pop_failure_jump. + Followed by two-byte address. */ + maybe_pop_jump, + + /* Jump to following two-byte address, and push a dummy failure + point. This failure point will be thrown away if an attempt + is made to use it for a failure. A `+' construct makes this + before the first repeat. Also used as an intermediary kind + of jump when compiling an alternative. */ + dummy_failure_jump, + + /* Push a dummy failure point and continue. Used at the end of + alternatives. */ + push_dummy_failure, + + /* Followed by two-byte relative address and two-byte number n. + After matching N times, jump to the address upon failure. */ + succeed_n, + + /* Followed by two-byte relative address, and two-byte number n. + Jump to the address N times, then fail. */ + jump_n, + + /* Set the following two-byte relative address to the + subsequent two-byte number. The address *includes* the two + bytes of number. */ + set_number_at, + + wordchar, /* Matches any word-constituent character. */ + notwordchar, /* Matches any char that is not a word-constituent. */ + + wordbeg, /* Succeeds if at word beginning. */ + wordend, /* Succeeds if at word end. */ + + wordbound, /* Succeeds if at a word boundary. */ + notwordbound /* Succeeds if not at a word boundary. */ + +#ifdef emacs + ,before_dot, /* Succeeds if before point. */ + at_dot, /* Succeeds if at point. */ + after_dot, /* Succeeds if after point. */ + + /* Matches any character whose syntax is specified. Followed by + a byte which contains a syntax code, e.g., Sword. */ + syntaxspec, + + /* Matches any character whose syntax is not that specified. */ + notsyntaxspec +#endif /* emacs */ +} re_opcode_t; + +/* Common operations on the compiled pattern. */ + +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ + +#define STORE_NUMBER(destination, number) \ + do { \ + (destination)[0] = (number) & 0377; \ + (destination)[1] = (number) >> 8; \ + } while (0) + +/* Same as STORE_NUMBER, except increment DESTINATION to + the byte after where the number is stored. Therefore, DESTINATION + must be an lvalue. */ + +#define STORE_NUMBER_AND_INCR(destination, number) \ + do { \ + STORE_NUMBER (destination, number); \ + (destination) += 2; \ + } while (0) + +/* Put into DESTINATION a number stored in two contiguous bytes starting + at SOURCE. */ + +#define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source) & 0377; \ + (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ + } while (0) + +#ifdef DEBUG +static void +extract_number (dest, source) + int *dest; + unsigned char *source; +{ + int temp = SIGN_EXTEND_CHAR (*(source + 1)); + *dest = *source & 0377; + *dest += temp << 8; +} + +#ifndef EXTRACT_MACROS /* To debug the macros. */ +#undef EXTRACT_NUMBER +#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) +#endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. + SOURCE must be an lvalue. */ + +#define EXTRACT_NUMBER_AND_INCR(destination, source) \ + do { \ + EXTRACT_NUMBER (destination, source); \ + (source) += 2; \ + } while (0) + +#ifdef DEBUG +static void +extract_number_and_incr (destination, source) + int *destination; + unsigned char **source; +{ + extract_number (destination, *source); + *source += 2; +} + +#ifndef EXTRACT_MACROS +#undef EXTRACT_NUMBER_AND_INCR +#define EXTRACT_NUMBER_AND_INCR(dest, src) \ + extract_number_and_incr (&dest, &src) +#endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* If DEBUG is defined, Regex prints many voluminous messages about what + it is doing (if the variable `debug' is nonzero). If linked with the + main program in `iregex.c', you can enter patterns and strings + interactively. And if linked with the main program in `main.c' and + the other test files, you can run the already-written tests. */ + +#ifdef DEBUG + +/* We use standard I/O for debugging. */ +#include + +/* It is useful to test things that ``must'' be true when debugging. */ +#include + +static int debug = 0; + +#define DEBUG_STATEMENT(e) e +#define DEBUG_PRINT1(x) if (debug) printf (x) +#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) +#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) +#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) +#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ + if (debug) print_partial_compiled_pattern (s, e) +#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ + if (debug) print_double_string (w, s1, sz1, s2, sz2) + + +extern void printchar (); + +/* Print the fastmap in human-readable form. */ + +void +print_fastmap (fastmap) + char *fastmap; +{ + unsigned was_a_range = 0; + unsigned i = 0; + + while (i < (1 << BYTEWIDTH)) + { + if (fastmap[i++]) + { + was_a_range = 0; + printchar (i - 1); + while (i < (1 << BYTEWIDTH) && fastmap[i]) + { + was_a_range = 1; + i++; + } + if (was_a_range) + { + printf ("-"); + printchar (i - 1); + } + } + } + putchar ('\n'); +} + + +/* Print a compiled pattern string in human-readable form, starting at + the START pointer into it and ending just before the pointer END. */ + +void +print_partial_compiled_pattern (start, end) + unsigned char *start; + unsigned char *end; +{ + int mcnt, mcnt2; + unsigned char *p = start; + unsigned char *pend = end; + + if (start == NULL) + { + printf ("(null)\n"); + return; + } + + /* Loop over pattern commands. */ + while (p < pend) + { + printf ("%d:\t", p - start); + + switch ((re_opcode_t) *p++) + { + case no_op: + printf ("/no_op"); + break; + + case exactn: + mcnt = *p++; + printf ("/exactn/%d", mcnt); + do + { + putchar ('/'); + printchar (*p++); + } + while (--mcnt); + break; + + case start_memory: + mcnt = *p++; + printf ("/start_memory/%d/%d", mcnt, *p++); + break; + + case stop_memory: + mcnt = *p++; + printf ("/stop_memory/%d/%d", mcnt, *p++); + break; + + case duplicate: + printf ("/duplicate/%d", *p++); + break; + + case anychar: + printf ("/anychar"); + break; + + case charset: + case charset_not: + { + register int c, last = -100; + register int in_range = 0; + + printf ("/charset [%s", + (re_opcode_t) *(p - 1) == charset_not ? "^" : ""); + + assert (p + *p < pend); + + for (c = 0; c < 256; c++) + if (c / 8 < *p + && (p[1 + (c/8)] & (1 << (c % 8)))) + { + /* Are we starting a range? */ + if (last + 1 == c && ! in_range) + { + putchar ('-'); + in_range = 1; + } + /* Have we broken a range? */ + else if (last + 1 != c && in_range) + { + printchar (last); + in_range = 0; + } + + if (! in_range) + printchar (c); + + last = c; + } + + if (in_range) + printchar (last); + + putchar (']'); + + p += 1 + *p; + } + break; + + case begline: + printf ("/begline"); + break; + + case endline: + printf ("/endline"); + break; + + case on_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_jump to %d", p + mcnt - start); + break; + + case on_failure_keep_string_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_keep_string_jump to %d", p + mcnt - start); + break; + + case dummy_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/dummy_failure_jump to %d", p + mcnt - start); + break; + + case push_dummy_failure: + printf ("/push_dummy_failure"); + break; + + case maybe_pop_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/maybe_pop_jump to %d", p + mcnt - start); + break; + + case pop_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/pop_failure_jump to %d", p + mcnt - start); + break; + + case jump_past_alt: + extract_number_and_incr (&mcnt, &p); + printf ("/jump_past_alt to %d", p + mcnt - start); + break; + + case jump: + extract_number_and_incr (&mcnt, &p); + printf ("/jump to %d", p + mcnt - start); + break; + + case succeed_n: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/succeed_n to %d, %d times", p + mcnt - start, mcnt2); + break; + + case jump_n: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/jump_n to %d, %d times", p + mcnt - start, mcnt2); + break; + + case set_number_at: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/set_number_at location %d to %d", p + mcnt - start, mcnt2); + break; + + case wordbound: + printf ("/wordbound"); + break; + + case notwordbound: + printf ("/notwordbound"); + break; + + case wordbeg: + printf ("/wordbeg"); + break; + + case wordend: + printf ("/wordend"); + +#ifdef emacs + case before_dot: + printf ("/before_dot"); + break; + + case at_dot: + printf ("/at_dot"); + break; + + case after_dot: + printf ("/after_dot"); + break; + + case syntaxspec: + printf ("/syntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; + + case notsyntaxspec: + printf ("/notsyntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; +#endif /* emacs */ + + case wordchar: + printf ("/wordchar"); + break; + + case notwordchar: + printf ("/notwordchar"); + break; + + case begbuf: + printf ("/begbuf"); + break; + + case endbuf: + printf ("/endbuf"); + break; + + default: + printf ("?%d", *(p-1)); + } + + putchar ('\n'); + } + + printf ("%d:\tend of pattern.\n", p - start); +} + + +void +print_compiled_pattern (bufp) + struct re_pattern_buffer *bufp; +{ + unsigned char *buffer = bufp->buffer; + + print_partial_compiled_pattern (buffer, buffer + bufp->used); + printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated); + + if (bufp->fastmap_accurate && bufp->fastmap) + { + printf ("fastmap: "); + print_fastmap (bufp->fastmap); + } + + printf ("re_nsub: %d\t", bufp->re_nsub); + printf ("regs_alloc: %d\t", bufp->regs_allocated); + printf ("can_be_null: %d\t", bufp->can_be_null); + printf ("newline_anchor: %d\n", bufp->newline_anchor); + printf ("no_sub: %d\t", bufp->no_sub); + printf ("not_bol: %d\t", bufp->not_bol); + printf ("not_eol: %d\t", bufp->not_eol); + printf ("syntax: %d\n", bufp->syntax); + /* Perhaps we should print the translate table? */ +} + + +void +print_double_string (where, string1, size1, string2, size2) + const char *where; + const char *string1; + const char *string2; + int size1; + int size2; +{ + unsigned this_char; + + if (where == NULL) + printf ("(null)"); + else + { + if (FIRST_STRING_P (where)) + { + for (this_char = where - string1; this_char < size1; this_char++) + printchar (string1[this_char]); + + where = string2; + } + + for (this_char = where - string2; this_char < size2; this_char++) + printchar (string2[this_char]); + } +} + +#else /* not DEBUG */ + +#undef assert +#define assert(e) + +#define DEBUG_STATEMENT(e) +#define DEBUG_PRINT1(x) +#define DEBUG_PRINT2(x1, x2) +#define DEBUG_PRINT3(x1, x2, x3) +#define DEBUG_PRINT4(x1, x2, x3, x4) +#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) +#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) + +#endif /* not DEBUG */ + +/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can + also be assigned to arbitrarily: each pattern buffer stores its own + syntax, so it can be changed between regex compilations. */ +reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS; + + +/* Specify the precise syntax of regexps for compilation. This provides + for compatibility for various utilities which historically have + different, incompatible syntaxes. + + The argument SYNTAX is a bit mask comprised of the various bits + defined in regex.h. We return the old syntax. */ + +reg_syntax_t +re_set_syntax (syntax) + reg_syntax_t syntax; +{ + reg_syntax_t ret = re_syntax_options; + + re_syntax_options = syntax; + return ret; +} + +/* This table gives an error message for each of the error codes listed + in regex.h. Obviously the order here has to be same as there. */ + +static const char *re_error_msg[] = + { NULL, /* REG_NOERROR */ + "No match", /* REG_NOMATCH */ + "Invalid regular expression", /* REG_BADPAT */ + "Invalid collation character", /* REG_ECOLLATE */ + "Invalid character class name", /* REG_ECTYPE */ + "Trailing backslash", /* REG_EESCAPE */ + "Invalid back reference", /* REG_ESUBREG */ + "Unmatched [ or [^", /* REG_EBRACK */ + "Unmatched ( or \\(", /* REG_EPAREN */ + "Unmatched \\{", /* REG_EBRACE */ + "Invalid content of \\{\\}", /* REG_BADBR */ + "Invalid range end", /* REG_ERANGE */ + "Memory exhausted", /* REG_ESPACE */ + "Invalid preceding regular expression", /* REG_BADRPT */ + "Premature end of regular expression", /* REG_EEND */ + "Regular expression too big", /* REG_ESIZE */ + "Unmatched ) or \\)", /* REG_ERPAREN */ + }; + +/* Avoiding alloca during matching, to placate r_alloc. */ + +/* Define MATCH_MAY_ALLOCATE if we need to make sure that the + searching and matching functions should not call alloca. On some + systems, alloca is implemented in terms of malloc, and if we're + using the relocating allocator routines, then malloc could cause a + relocation, which might (if the strings being searched are in the + ralloc heap) shift the data out from underneath the regexp + routines. + + Here's another reason to avoid allocation: Emacs insists on + processing input from X in a signal handler; processing X input may + call malloc; if input arrives while a matching routine is calling + malloc, then we're scrod. But Emacs can't just block input while + calling matching routines; then we don't notice interrupts when + they come in. So, Emacs blocks input around all regexp calls + except the matching calls, which it leaves unprotected, in the + faith that they will not malloc. */ + +/* Normally, this is fine. */ +#define MATCH_MAY_ALLOCATE + +/* But under some circumstances, it's not. */ +#if defined (emacs) || (defined (REL_ALLOC) && defined (C_ALLOCA)) +#undef MATCH_MAY_ALLOCATE +#endif + + +/* Failure stack declarations and macros; both re_compile_fastmap and + re_match_2 use a failure stack. These have to be macros because of + REGEX_ALLOCATE. */ + + +/* Number of failure points for which to initially allocate space + when matching. If this number is exceeded, we allocate more + space, so it is not a hard limit. */ +#ifndef INIT_FAILURE_ALLOC +#define INIT_FAILURE_ALLOC 5 +#endif + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always used MAX_FAILURE_SPACE each time we failed. + This is a variable only so users of regex can assign to it; we never + change it ourselves. */ +int re_max_failures = 2000; + +typedef unsigned char *fail_stack_elt_t; + +typedef struct +{ + fail_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} fail_stack_type; + +#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) +#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) +#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) +#define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail]) + + +/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */ + +#ifdef MATCH_MAY_ALLOCATE +#define INIT_FAIL_STACK() \ + do { \ + fail_stack.stack = (fail_stack_elt_t *) \ + REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ + \ + if (fail_stack.stack == NULL) \ + return -2; \ + \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ + } while (0) +#else +#define INIT_FAIL_STACK() \ + do { \ + fail_stack.avail = 0; \ + } while (0) +#endif + + +/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. + + Return 1 if succeeds, and 0 if either ran out of memory + allocating space for it or it was already too large. + + REGEX_REALLOCATE requires `destination' be declared. */ + +#define DOUBLE_FAIL_STACK(fail_stack) \ + ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ + ? 0 \ + : ((fail_stack).stack = (fail_stack_elt_t *) \ + REGEX_REALLOCATE ((fail_stack).stack, \ + (fail_stack).size * sizeof (fail_stack_elt_t), \ + ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ + \ + (fail_stack).stack == NULL \ + ? 0 \ + : ((fail_stack).size <<= 1, \ + 1))) + + +/* Push PATTERN_OP on FAIL_STACK. + + Return 1 if was able to do so and 0 if ran out of memory allocating + space to do so. */ +#define PUSH_PATTERN_OP(pattern_op, fail_stack) \ + ((FAIL_STACK_FULL () \ + && !DOUBLE_FAIL_STACK (fail_stack)) \ + ? 0 \ + : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \ + 1)) + +/* This pushes an item onto the failure stack. Must be a four-byte + value. Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +#define PUSH_FAILURE_ITEM(item) \ + fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item + +/* The complement operation. Assumes `fail_stack' is nonempty. */ +#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail] + +/* Used to omit pushing failure point id's when we're not debugging. */ +#ifdef DEBUG +#define DEBUG_PUSH PUSH_FAILURE_ITEM +#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM () +#else +#define DEBUG_PUSH(item) +#define DEBUG_POP(item_addr) +#endif + + +/* Push the information about the state we will need + if we ever fail back to it. + + Requires variables fail_stack, regstart, regend, reg_info, and + num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be + declared. + + Does `return FAILURE_CODE' if runs out of memory. */ + +#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ + do { \ + char *destination; \ + /* Must be int, so when we don't save any registers, the arithmetic \ + of 0 + -1 isn't done as unsigned. */ \ + int this_reg; \ + \ + DEBUG_STATEMENT (failure_id++); \ + DEBUG_STATEMENT (nfailure_points_pushed++); \ + DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ + DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ + DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ + \ + DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ + DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ + \ + /* Ensure we have enough space allocated for what we will push. */ \ + while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ + { \ + if (!DOUBLE_FAIL_STACK (fail_stack)) \ + return failure_code; \ + \ + DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ + (fail_stack).size); \ + DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ + } \ + \ + /* Push the info, starting with the registers. */ \ + DEBUG_PRINT1 ("\n"); \ + \ + for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ + this_reg++) \ + { \ + DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ + DEBUG_STATEMENT (num_regs_pushed++); \ + \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + PUSH_FAILURE_ITEM (regstart[this_reg]); \ + \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + PUSH_FAILURE_ITEM (regend[this_reg]); \ + \ + DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ + DEBUG_PRINT2 (" match_null=%d", \ + REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ + DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ + DEBUG_PRINT2 (" matched_something=%d", \ + MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT2 (" ever_matched=%d", \ + EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT1 ("\n"); \ + PUSH_FAILURE_ITEM (reg_info[this_reg].word); \ + } \ + \ + DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ + PUSH_FAILURE_ITEM (lowest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ + PUSH_FAILURE_ITEM (highest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ + PUSH_FAILURE_ITEM (pattern_place); \ + \ + DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ + DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ + size2); \ + DEBUG_PRINT1 ("'\n"); \ + PUSH_FAILURE_ITEM (string_place); \ + \ + DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ + DEBUG_PUSH (failure_id); \ + } while (0) + +/* This is the number of items that are pushed and popped on the stack + for each register. */ +#define NUM_REG_ITEMS 3 + +/* Individual items aside from the registers. */ +#ifdef DEBUG +#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ +#else +#define NUM_NONREG_ITEMS 4 +#endif + +/* We push at most this many items on the stack. */ +#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) + +/* We actually push this many items. */ +#define NUM_FAILURE_ITEMS \ + ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ + + NUM_NONREG_ITEMS) + +/* How many items can still be added to the stack without overflowing it. */ +#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) + + +/* Pops what PUSH_FAIL_STACK pushes. + + We restore into the parameters, all of which should be lvalues: + STR -- the saved data position. + PAT -- the saved pattern position. + LOW_REG, HIGH_REG -- the highest and lowest active registers. + REGSTART, REGEND -- arrays of string positions. + REG_INFO -- array of information about each subexpression. + + Also assumes the variables `fail_stack' and (if debugging), `bufp', + `pend', `string1', `size1', `string2', and `size2'. */ + +#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ +{ \ + DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ + int this_reg; \ + const unsigned char *string_temp; \ + \ + assert (!FAIL_STACK_EMPTY ()); \ + \ + /* Remove failure points and point to how many regs pushed. */ \ + DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ + DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ + DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ + \ + assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ + \ + DEBUG_POP (&failure_id); \ + DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ + \ + /* If the saved string location is NULL, it came from an \ + on_failure_keep_string_jump opcode, and we want to throw away the \ + saved NULL, thus retaining our current position in the string. */ \ + string_temp = POP_FAILURE_ITEM (); \ + if (string_temp != NULL) \ + str = (const char *) string_temp; \ + \ + DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ + DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ + DEBUG_PRINT1 ("'\n"); \ + \ + pat = (unsigned char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ + \ + /* Restore register info. */ \ + high_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ + \ + low_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ + \ + for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ + { \ + DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ + \ + reg_info[this_reg].word = POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ + \ + regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + \ + regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + } \ + \ + DEBUG_STATEMENT (nfailure_points_popped++); \ +} /* POP_FAILURE_POINT */ + + + +/* Structure for per-register (a.k.a. per-group) information. + This must not be longer than one word, because we push this value + onto the failure stack. Other register information, such as the + starting and ending positions (which are addresses), and the list of + inner groups (which is a bits list) are maintained in separate + variables. + + We are making a (strictly speaking) nonportable assumption here: that + the compiler will pack our bit fields into something that fits into + the type of `word', i.e., is something that fits into one item on the + failure stack. */ +typedef union +{ + fail_stack_elt_t word; + struct + { + /* This field is one if this group can match the empty string, + zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ +#define MATCH_NULL_UNSET_VALUE 3 + unsigned match_null_string_p : 2; + unsigned is_active : 1; + unsigned matched_something : 1; + unsigned ever_matched_something : 1; + } bits; +} register_info_type; + +#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) +#define IS_ACTIVE(R) ((R).bits.is_active) +#define MATCHED_SOMETHING(R) ((R).bits.matched_something) +#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) + + +/* Call this when have matched a real character; it sets `matched' flags + for the subexpressions which we are currently inside. Also records + that those subexprs have matched. */ +#define SET_REGS_MATCHED() \ + do \ + { \ + unsigned r; \ + for (r = lowest_active_reg; r <= highest_active_reg; r++) \ + { \ + MATCHED_SOMETHING (reg_info[r]) \ + = EVER_MATCHED_SOMETHING (reg_info[r]) \ + = 1; \ + } \ + } \ + while (0) + + +/* Registers are set to a sentinel when they haven't yet matched. */ +#define REG_UNSET_VALUE ((char *) -1) +#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) + + + +/* How do we implement a missing MATCH_MAY_ALLOCATE? + We make the fail stack a global thing, and then grow it to + re_max_failures when we compile. */ +#ifndef MATCH_MAY_ALLOCATE +static fail_stack_type fail_stack; + +static const char ** regstart, ** regend; +static const char ** old_regstart, ** old_regend; +static const char **best_regstart, **best_regend; +static register_info_type *reg_info; +static const char **reg_dummy; +static register_info_type *reg_info_dummy; +#endif + + +/* Subroutine declarations and macros for regex_compile. */ + +static void store_op1 (), store_op2 (); +static void insert_op1 (), insert_op2 (); +static boolean at_begline_loc_p (), at_endline_loc_p (); +static boolean group_in_compile_stack (); +static reg_errcode_t compile_range (); + +/* Fetch the next character in the uncompiled pattern---translating it + if necessary. Also cast from a signed character in the constant + string passed to us by the user to an unsigned char that we can use + as an array index (in, e.g., `translate'). */ +#define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + if (translate) c = translate[c]; \ + } while (0) + +/* Fetch the next character in the uncompiled pattern, with no + translation. */ +#define PATFETCH_RAW(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + } while (0) + +/* Go backwards one character in the pattern. */ +#define PATUNFETCH p-- + + +/* If `translate' is non-null, return translate[D], else just D. We + cast the subscript to translate because some data is declared as + `char *', to avoid warnings when a string constant is passed. But + when we use a character as a subscript we must make it unsigned. */ +#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d)) + + +/* Macros for outputting the compiled pattern into `buffer'. */ + +/* If the buffer isn't allocated when it comes in, use this. */ +#define INIT_BUF_SIZE 32 + +/* Make sure we have at least N more bytes of space in buffer. */ +#define GET_BUFFER_SPACE(n) \ + while (b - bufp->buffer + (n) > bufp->allocated) \ + EXTEND_BUFFER () + +/* Make sure we have one more byte of buffer space and then add C to it. */ +#define BUF_PUSH(c) \ + do { \ + GET_BUFFER_SPACE (1); \ + *b++ = (unsigned char) (c); \ + } while (0) + + +/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ +#define BUF_PUSH_2(c1, c2) \ + do { \ + GET_BUFFER_SPACE (2); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + } while (0) + + +/* As with BUF_PUSH_2, except for three bytes. */ +#define BUF_PUSH_3(c1, c2, c3) \ + do { \ + GET_BUFFER_SPACE (3); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + *b++ = (unsigned char) (c3); \ + } while (0) + + +/* Store a jump with opcode OP at LOC to location TO. We store a + relative address offset by the three bytes the jump itself occupies. */ +#define STORE_JUMP(op, loc, to) \ + store_op1 (op, loc, (to) - (loc) - 3) + +/* Likewise, for a two-argument jump. */ +#define STORE_JUMP2(op, loc, to, arg) \ + store_op2 (op, loc, (to) - (loc) - 3, arg) + +/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP(op, loc, to) \ + insert_op1 (op, loc, (to) - (loc) - 3, b) + +/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP2(op, loc, to, arg) \ + insert_op2 (op, loc, (to) - (loc) - 3, arg, b) + + +/* This is not an arbitrary limit: the arguments which represent offsets + into the pattern are two bytes long. So if 2^16 bytes turns out to + be too small, many things would have to change. */ +#define MAX_BUF_SIZE (1L << 16) + + +/* Extend the buffer by twice its current size via realloc and + reset the pointers that pointed into the old block to point to the + correct places in the new one. If extending the buffer results in it + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ +#define EXTEND_BUFFER() \ + do { \ + unsigned char *old_buffer = bufp->buffer; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\ + if (bufp->buffer == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != bufp->buffer) \ + { \ + b = (b - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (fixup_alt_jump) \ + fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } \ + } while (0) + + +/* Since we have one byte reserved for the register number argument to + {start,stop}_memory, the maximum number of groups we can report + things about is what fits in that byte. */ +#define MAX_REGNUM 255 + +/* But patterns can have more than `MAX_REGNUM' registers. We just + ignore the excess. */ +typedef unsigned regnum_t; + + +/* Macros for the compile stack. */ + +/* Since offsets can go either forwards or backwards, this type needs to + be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ +typedef int pattern_offset_t; + +typedef struct +{ + pattern_offset_t begalt_offset; + pattern_offset_t fixup_alt_jump; + pattern_offset_t inner_group_offset; + pattern_offset_t laststart_offset; + regnum_t regnum; +} compile_stack_elt_t; + + +typedef struct +{ + compile_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} compile_stack_type; + + +#define INIT_COMPILE_STACK_SIZE 32 + +#define COMPILE_STACK_EMPTY (compile_stack.avail == 0) +#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) + +/* The next available element. */ +#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) + + +/* Set the bit for character C in a list. */ +#define SET_LIST_BIT(c) \ + (b[((unsigned char) (c)) / BYTEWIDTH] \ + |= 1 << (((unsigned char) c) % BYTEWIDTH)) + + +/* Get the next unsigned number in the uncompiled pattern. */ +#define GET_UNSIGNED_NUMBER(num) \ + { if (p != pend) \ + { \ + PATFETCH (c); \ + while (ISDIGIT (c)) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + if (p == pend) \ + break; \ + PATFETCH (c); \ + } \ + } \ + } + +#define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +#define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) + +/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. + Returns one of error codes defined in `regex.h', or zero for success. + + Assumes the `allocated' (and perhaps `buffer') and `translate' + fields are set in BUFP on entry. + + If it succeeds, results are put in BUFP (if it returns an error, the + contents of BUFP are undefined): + `buffer' is the compiled pattern; + `syntax' is set to SYNTAX; + `used' is set to the length of the compiled pattern; + `fastmap_accurate' is zero; + `re_nsub' is the number of subexpressions in PATTERN; + `not_bol' and `not_eol' are zero; + + The `fastmap' and `newline_anchor' fields are neither + examined nor set. */ + +static reg_errcode_t +regex_compile (pattern, size, syntax, bufp) + const char *pattern; + int size; + reg_syntax_t syntax; + struct re_pattern_buffer *bufp; +{ + /* We fetch characters from PATTERN here. Even though PATTERN is + `char *' (i.e., signed), we declare these variables as unsigned, so + they can be reliably used as array indices. */ + register unsigned char c, c1; + + /* A random tempory spot in PATTERN. */ + const char *p1; + + /* Points to the end of the buffer, where we should append. */ + register unsigned char *b; + + /* Keeps track of unclosed groups. */ + compile_stack_type compile_stack; + + /* Points to the current (ending) position in the pattern. */ + const char *p = pattern; + const char *pend = pattern + size; + + /* How to translate the characters in the pattern. */ + char *translate = bufp->translate; + + /* Address of the count-byte of the most recently inserted `exactn' + command. This makes it possible to tell if a new exact-match + character can be added to that command or if the character requires + a new `exactn' command. */ + unsigned char *pending_exact = 0; + + /* Address of start of the most recently finished expression. + This tells, e.g., postfix * where to find the start of its + operand. Reset at the beginning of groups and alternatives. */ + unsigned char *laststart = 0; + + /* Address of beginning of regexp, or inside of last group. */ + unsigned char *begalt; + + /* Place in the uncompiled pattern (i.e., the {) to + which to go back if the interval is invalid. */ + const char *beg_interval; + + /* Address of the place where a forward jump should go to the end of + the containing expression. Each alternative of an `or' -- except the + last -- ends with a forward jump of this sort. */ + unsigned char *fixup_alt_jump = 0; + + /* Counts open-groups as they are encountered. Remembered for the + matching close-group on the compile stack, so the same register + number is put in the stop_memory as the start_memory. */ + regnum_t regnum = 0; + +#ifdef DEBUG + DEBUG_PRINT1 ("\nCompiling pattern: "); + if (debug) + { + unsigned debug_count; + + for (debug_count = 0; debug_count < size; debug_count++) + printchar (pattern[debug_count]); + putchar ('\n'); + } +#endif /* DEBUG */ + + /* Initialize the compile stack. */ + compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); + if (compile_stack.stack == NULL) + return REG_ESPACE; + + compile_stack.size = INIT_COMPILE_STACK_SIZE; + compile_stack.avail = 0; + + /* Initialize the pattern buffer. */ + bufp->syntax = syntax; + bufp->fastmap_accurate = 0; + bufp->not_bol = bufp->not_eol = 0; + + /* Set `used' to zero, so that if we return an error, the pattern + printer (for debugging) will think there's no pattern. We reset it + at the end. */ + bufp->used = 0; + + /* Always count groups, whether or not bufp->no_sub is set. */ + bufp->re_nsub = 0; + +#if !defined (emacs) && !defined (SYNTAX_TABLE) + /* Initialize the syntax table. */ + init_syntax_once (); +#endif + + if (bufp->allocated == 0) + { + if (bufp->buffer) + { /* If zero allocated, but buffer is non-null, try to realloc + enough space. This loses if buffer's address is bogus, but + that is the user's responsibility. */ + RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); + } + else + { /* Caller did not allocate a buffer. Do it for them. */ + bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); + } + if (!bufp->buffer) return REG_ESPACE; + + bufp->allocated = INIT_BUF_SIZE; + } + + begalt = b = bufp->buffer; + + /* Loop through the uncompiled pattern until we're at the end. */ + while (p != pend) + { + PATFETCH (c); + + switch (c) + { + case '^': + { + if ( /* If at start of pattern, it's an operator. */ + p == pattern + 1 + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's come before. */ + || at_begline_loc_p (pattern, p, syntax)) + BUF_PUSH (begline); + else + goto normal_char; + } + break; + + + case '$': + { + if ( /* If at end of pattern, it's an operator. */ + p == pend + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's next. */ + || at_endline_loc_p (p, pend, syntax)) + BUF_PUSH (endline); + else + goto normal_char; + } + break; + + + case '+': + case '?': + if ((syntax & RE_BK_PLUS_QM) + || (syntax & RE_LIMITED_OPS)) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern... */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + return REG_BADRPT; + else if (!(syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } + + { + /* Are we optimizing this jump? */ + boolean keep_string_p = false; + + /* 1 means zero (many) matches is allowed. */ + char zero_times_ok = 0, many_times_ok = 0; + + /* If there is a sequence of repetition chars, collapse it + down to just one (the right one). We can't combine + interval operators with these because of, e.g., `a{2}*', + which should only match an even number of `a's. */ + + for (;;) + { + zero_times_ok |= c != '+'; + many_times_ok |= c != '?'; + + if (p == pend) + break; + + PATFETCH (c); + + if (c == '*' + || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) + ; + + else if (syntax & RE_BK_PLUS_QM && c == '\\') + { + if (p == pend) return REG_EESCAPE; + + PATFETCH (c1); + if (!(c1 == '+' || c1 == '?')) + { + PATUNFETCH; + PATUNFETCH; + break; + } + + c = c1; + } + else + { + PATUNFETCH; + break; + } + + /* If we get here, we found another repeat character. */ + } + + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; + + /* Now we know whether or not zero matches is allowed + and also whether or not two or more matches is allowed. */ + if (many_times_ok) + { /* More than one repetition is allowed, so put in at the + end a backward relative jump from `b' to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). + + But if we are at the `*' in the exact sequence `.*\n', + insert an unconditional jump backwards to the ., + instead of the beginning of the loop. This way we only + push a failure point once, instead of every time + through the loop. */ + assert (p - 1 > pattern); + + /* Allocate the space for the jump. */ + GET_BUFFER_SPACE (3); + + /* We know we are not at the first character of the pattern, + because laststart was nonzero. And we've already + incremented `p', by the way, to be the character after + the `*'. Do we have to do something analogous here + for null bytes, because of RE_DOT_NOT_NULL? */ + if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') + && zero_times_ok + && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') + && !(syntax & RE_DOT_NEWLINE)) + { /* We have .*\n. */ + STORE_JUMP (jump, b, laststart); + keep_string_p = true; + } + else + /* Anything else. */ + STORE_JUMP (maybe_pop_jump, b, laststart - 3); + + /* We've added more stuff to the buffer. */ + b += 3; + } + + /* On failure, jump from laststart to b + 3, which will be the + end of the buffer after this jump is inserted. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump + : on_failure_jump, + laststart, b + 3); + pending_exact = 0; + b += 3; + + if (!zero_times_ok) + { + /* At least one repetition is required, so insert a + `dummy_failure_jump' before the initial + `on_failure_jump' instruction of the loop. This + effects a skip over that instruction the first time + we hit that loop. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); + b += 3; + } + } + break; + + + case '.': + laststart = b; + BUF_PUSH (anychar); + break; + + + case '[': + { + boolean had_char_class = false; + + if (p == pend) return REG_EBRACK; + + /* Ensure that we have enough space to push a charset: the + opcode, the length count, and the bitset; 34 bytes in all. */ + GET_BUFFER_SPACE (34); + + laststart = b; + + /* We test `*p == '^' twice, instead of using an if + statement, so we only need one BUF_PUSH. */ + BUF_PUSH (*p == '^' ? charset_not : charset); + if (*p == '^') + p++; + + /* Remember the first position in the bracket expression. */ + p1 = p; + + /* Push the number of bytes in the bitmap. */ + BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + + /* Clear the whole map. */ + bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); + + /* charset_not matches newline according to a syntax bit. */ + if ((re_opcode_t) b[-2] == charset_not + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) + SET_LIST_BIT ('\n'); + + /* Read in characters and ranges, setting map bits. */ + for (;;) + { + if (p == pend) return REG_EBRACK; + + PATFETCH (c); + + /* \ might escape characters inside [...] and [^...]. */ + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') + { + if (p == pend) return REG_EESCAPE; + + PATFETCH (c1); + SET_LIST_BIT (c1); + continue; + } + + /* Could be the end of the bracket expression. If it's + not (i.e., when the bracket expression is `[]' so + far), the ']' character bit gets set way below. */ + if (c == ']' && p != p1 + 1) + break; + + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + return REG_ERANGE; + + /* Look ahead to see if it's a range when the last thing + was a character: if this is a hyphen not at the + beginning or the end of a list, then it's the range + operator. */ + if (c == '-' + && !(p - 2 >= pattern && p[-2] == '[') + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') + && *p != ']') + { + reg_errcode_t ret + = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) return ret; + } + + else if (p[0] == '-' && p[1] != ']') + { /* This handles ranges made up of characters only. */ + reg_errcode_t ret; + + /* Move past the `-'. */ + PATFETCH (c1); + + ret = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) return ret; + } + + /* See if we're at the beginning of a possible character + class. */ + + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') + { /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) return REG_EBRACK; + + for (;;) + { + PATFETCH (c); + if (c == ':' || c == ']' || p == pend + || c1 == CHAR_CLASS_MAX_LENGTH) + break; + str[c1++] = c; + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and:`]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but set bits for them). */ + if (c == ':' && *p == ']') + { + int ch; + boolean is_alnum = STREQ (str, "alnum"); + boolean is_alpha = STREQ (str, "alpha"); + boolean is_blank = STREQ (str, "blank"); + boolean is_cntrl = STREQ (str, "cntrl"); + boolean is_digit = STREQ (str, "digit"); + boolean is_graph = STREQ (str, "graph"); + boolean is_lower = STREQ (str, "lower"); + boolean is_print = STREQ (str, "print"); + boolean is_punct = STREQ (str, "punct"); + boolean is_space = STREQ (str, "space"); + boolean is_upper = STREQ (str, "upper"); + boolean is_xdigit = STREQ (str, "xdigit"); + + if (!IS_CHAR_CLASS (str)) return REG_ECTYPE; + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) return REG_EBRACK; + + for (ch = 0; ch < 1 << BYTEWIDTH; ch++) + { + if ( (is_alnum && ISALNUM (ch)) + || (is_alpha && ISALPHA (ch)) + || (is_blank && ISBLANK (ch)) + || (is_cntrl && ISCNTRL (ch)) + || (is_digit && ISDIGIT (ch)) + || (is_graph && ISGRAPH (ch)) + || (is_lower && ISLOWER (ch)) + || (is_print && ISPRINT (ch)) + || (is_punct && ISPUNCT (ch)) + || (is_space && ISSPACE (ch)) + || (is_upper && ISUPPER (ch)) + || (is_xdigit && ISXDIGIT (ch))) + SET_LIST_BIT (ch); + } + had_char_class = true; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT (':'); + had_char_class = false; + } + } + else + { + had_char_class = false; + SET_LIST_BIT (c); + } + } + + /* Discard any (non)matching list bytes that are all 0 at the + end of the map. Decrease the map-length byte too. */ + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + b += b[-1]; + } + break; + + + case '(': + if (syntax & RE_NO_BK_PARENS) + goto handle_open; + else + goto normal_char; + + + case ')': + if (syntax & RE_NO_BK_PARENS) + goto handle_close; + else + goto normal_char; + + + case '\n': + if (syntax & RE_NEWLINE_ALT) + goto handle_alt; + else + goto normal_char; + + + case '|': + if (syntax & RE_NO_BK_VBAR) + goto handle_alt; + else + goto normal_char; + + + case '{': + if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) + goto handle_interval; + else + goto normal_char; + + + case '\\': + if (p == pend) return REG_EESCAPE; + + /* Do not translate the character after the \, so that we can + distinguish, e.g., \B from \b, even if we normally would + translate, e.g., B to b. */ + PATFETCH_RAW (c); + + switch (c) + { + case '(': + if (syntax & RE_NO_BK_PARENS) + goto normal_backslash; + + handle_open: + bufp->re_nsub++; + regnum++; + + if (COMPILE_STACK_FULL) + { + RETALLOC (compile_stack.stack, compile_stack.size << 1, + compile_stack_elt_t); + if (compile_stack.stack == NULL) return REG_ESPACE; + + compile_stack.size <<= 1; + } + + /* These are the values to restore when we hit end of this + group. They are all relative offsets, so that if the + whole pattern moves because of realloc, they will still + be valid. */ + COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; + COMPILE_STACK_TOP.fixup_alt_jump + = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; + COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; + COMPILE_STACK_TOP.regnum = regnum; + + /* We will eventually replace the 0 with the number of + groups inner to this one. But do not push a + start_memory for groups beyond the last one we can + represent in the compiled pattern. */ + if (regnum <= MAX_REGNUM) + { + COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; + BUF_PUSH_3 (start_memory, regnum, 0); + } + + compile_stack.avail++; + + fixup_alt_jump = 0; + laststart = 0; + begalt = b; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + break; + + + case ')': + if (syntax & RE_NO_BK_PARENS) goto normal_backslash; + + if (COMPILE_STACK_EMPTY) + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_backslash; + else + return REG_ERPAREN; + + handle_close: + if (fixup_alt_jump) + { /* Push a dummy failure point at the end of the + alternative for a possible future + `pop_failure_jump' to pop. See comments at + `push_dummy_failure' in `re_match_2'. */ + BUF_PUSH (push_dummy_failure); + + /* We allocated space for this jump when we assigned + to `fixup_alt_jump', in the `handle_alt' case below. */ + STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); + } + + /* See similar code for backslashed left paren above. */ + if (COMPILE_STACK_EMPTY) + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_char; + else + return REG_ERPAREN; + + /* Since we just checked for an empty stack above, this + ``can't happen''. */ + assert (compile_stack.avail != 0); + { + /* We don't just want to restore into `regnum', because + later groups should continue to be numbered higher, + as in `(ab)c(de)' -- the second group is #2. */ + regnum_t this_group_regnum; + + compile_stack.avail--; + begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; + fixup_alt_jump + = COMPILE_STACK_TOP.fixup_alt_jump + ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 + : 0; + laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; + this_group_regnum = COMPILE_STACK_TOP.regnum; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + + /* We're at the end of the group, so now we know how many + groups were inside this one. */ + if (this_group_regnum <= MAX_REGNUM) + { + unsigned char *inner_group_loc + = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; + + *inner_group_loc = regnum - this_group_regnum; + BUF_PUSH_3 (stop_memory, this_group_regnum, + regnum - this_group_regnum); + } + } + break; + + + case '|': /* `\|'. */ + if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) + goto normal_backslash; + handle_alt: + if (syntax & RE_LIMITED_OPS) + goto normal_char; + + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (on_failure_jump, begalt, b + 6); + pending_exact = 0; + b += 3; + + /* The alternative before this one has a jump after it + which gets executed if it gets matched. Adjust that + jump so it will jump to this alternative's analogous + jump (put in below, which in turn will jump to the next + (if any) alternative's such jump, etc.). The last such + jump jumps to the correct final destination. A picture: + _____ _____ + | | | | + | v | v + a | b | c + + If we are at `b', then fixup_alt_jump right now points to a + three-byte space after `a'. We'll put in the jump, set + fixup_alt_jump to right after `b', and leave behind three + bytes which we'll fill in when we get to after `c'. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + /* Mark and leave space for a jump after this alternative, + to be filled in later either by next alternative or + when know we're at the end of a series of alternatives. */ + fixup_alt_jump = b; + GET_BUFFER_SPACE (3); + b += 3; + + laststart = 0; + begalt = b; + break; + + + case '{': + /* If \{ is a literal. */ + if (!(syntax & RE_INTERVALS) + /* If we're at `\{' and it's not the open-interval + operator. */ + || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + || (p - 2 == pattern && p == pend)) + goto normal_backslash; + + handle_interval: + { + /* If got here, then the syntax allows intervals. */ + + /* At least (most) this many matches must be made. */ + int lower_bound = -1, upper_bound = -1; + + beg_interval = p - 1; + + if (p == pend) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_EBRACE; + } + + GET_UNSIGNED_NUMBER (lower_bound); + + if (c == ',') + { + GET_UNSIGNED_NUMBER (upper_bound); + if (upper_bound < 0) upper_bound = RE_DUP_MAX; + } + else + /* Interval such as `{1}' => match exactly once. */ + upper_bound = lower_bound; + + if (lower_bound < 0 || upper_bound > RE_DUP_MAX + || lower_bound > upper_bound) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_BADBR; + } + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (c != '\\') return REG_EBRACE; + + PATFETCH (c); + } + + if (c != '}') + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_BADBR; + } + + /* We just parsed a valid interval. */ + + /* If it's invalid to have no preceding re. */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + return REG_BADRPT; + else if (syntax & RE_CONTEXT_INDEP_OPS) + laststart = b; + else + goto unfetch_interval; + } + + /* If the upper bound is zero, don't want to succeed at + all; jump from `laststart' to `b + 3', which will be + the end of the buffer after we insert the jump. */ + if (upper_bound == 0) + { + GET_BUFFER_SPACE (3); + INSERT_JUMP (jump, laststart, b + 3); + b += 3; + } + + /* Otherwise, we have a nontrivial interval. When + we're all done, the pattern will look like: + set_number_at + set_number_at + succeed_n + + jump_n + (The upper bound and `jump_n' are omitted if + `upper_bound' is 1, though.) */ + else + { /* If the upper bound is > 1, we need to insert + more at the end of the loop. */ + unsigned nbytes = 10 + (upper_bound > 1) * 10; + + GET_BUFFER_SPACE (nbytes); + + /* Initialize lower bound of the `succeed_n', even + though it will be set during matching by its + attendant `set_number_at' (inserted next), + because `re_compile_fastmap' needs to know. + Jump to the `jump_n' we might insert below. */ + INSERT_JUMP2 (succeed_n, laststart, + b + 5 + (upper_bound > 1) * 5, + lower_bound); + b += 5; + + /* Code to initialize the lower bound. Insert + before the `succeed_n'. The `5' is the last two + bytes of this `set_number_at', plus 3 bytes of + the following `succeed_n'. */ + insert_op2 (set_number_at, laststart, 5, lower_bound, b); + b += 5; + + if (upper_bound > 1) + { /* More than one repetition is allowed, so + append a backward jump to the `succeed_n' + that starts this interval. + + When we've reached this during matching, + we'll have matched the interval once, so + jump back only `upper_bound - 1' times. */ + STORE_JUMP2 (jump_n, b, laststart + 5, + upper_bound - 1); + b += 5; + + /* The location we want to set is the second + parameter of the `jump_n'; that is `b-2' as + an absolute address. `laststart' will be + the `set_number_at' we're about to insert; + `laststart+3' the number to set, the source + for the relative address. But we are + inserting into the middle of the pattern -- + so everything is getting moved up by 5. + Conclusion: (b - 2) - (laststart + 3) + 5, + i.e., b - laststart. + + We insert this at the beginning of the loop + so that if we fail during matching, we'll + reinitialize the bounds. */ + insert_op2 (set_number_at, laststart, b - laststart, + upper_bound - 1, b); + b += 5; + } + } + pending_exact = 0; + beg_interval = NULL; + } + break; + + unfetch_interval: + /* If an invalid interval, match the characters as literals. */ + assert (beg_interval); + p = beg_interval; + beg_interval = NULL; + + /* normal_char and normal_backslash need `c'. */ + PATFETCH (c); + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (p > pattern && p[-1] == '\\') + goto normal_backslash; + } + goto normal_char; + +#ifdef emacs + /* There is no way to specify the before_dot and after_dot + operators. rms says this is ok. --karl */ + case '=': + BUF_PUSH (at_dot); + break; + + case 's': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); + break; +#endif /* emacs */ + + + case 'w': + laststart = b; + BUF_PUSH (wordchar); + break; + + + case 'W': + laststart = b; + BUF_PUSH (notwordchar); + break; + + + case '<': + BUF_PUSH (wordbeg); + break; + + case '>': + BUF_PUSH (wordend); + break; + + case 'b': + BUF_PUSH (wordbound); + break; + + case 'B': + BUF_PUSH (notwordbound); + break; + + case '`': + BUF_PUSH (begbuf); + break; + + case '\'': + BUF_PUSH (endbuf); + break; + + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + if (syntax & RE_NO_BK_REFS) + goto normal_char; + + c1 = c - '0'; + + if (c1 > regnum) + return REG_ESUBREG; + + /* Can't back reference to a subexpression if inside of it. */ + if (group_in_compile_stack (compile_stack, c1)) + goto normal_char; + + laststart = b; + BUF_PUSH_2 (duplicate, c1); + break; + + + case '+': + case '?': + if (syntax & RE_BK_PLUS_QM) + goto handle_plus; + else + goto normal_backslash; + + default: + normal_backslash: + /* You might think it would be useful for \ to mean + not to translate; but if we don't translate it + it will never match anything. */ + c = TRANSLATE (c); + goto normal_char; + } + break; + + + default: + /* Expects the character in `c'. */ + normal_char: + /* If no exactn currently being built. */ + if (!pending_exact + + /* If last exactn not at current position. */ + || pending_exact + *pending_exact + 1 != b + + /* We have only one byte following the exactn for the count. */ + || *pending_exact == (1 << BYTEWIDTH) - 1 + + /* If followed by a repetition operator. */ + || *p == '*' || *p == '^' + || ((syntax & RE_BK_PLUS_QM) + ? *p == '\\' && (p[1] == '+' || p[1] == '?') + : (*p == '+' || *p == '?')) + || ((syntax & RE_INTERVALS) + && ((syntax & RE_NO_BK_BRACES) + ? *p == '{' + : (p[0] == '\\' && p[1] == '{')))) + { + /* Start building a new exactn. */ + + laststart = b; + + BUF_PUSH_2 (exactn, 0); + pending_exact = b - 1; + } + + BUF_PUSH (c); + (*pending_exact)++; + break; + } /* switch (c) */ + } /* while p != pend */ + + + /* Through the pattern now. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + if (!COMPILE_STACK_EMPTY) + return REG_EPAREN; + + free (compile_stack.stack); + + /* We have succeeded; set the length of the buffer. */ + bufp->used = b - bufp->buffer; + +#ifdef DEBUG + if (debug) + { + DEBUG_PRINT1 ("\nCompiled pattern: \n"); + print_compiled_pattern (bufp); + } +#endif /* DEBUG */ + +#ifndef MATCH_MAY_ALLOCATE + /* Initialize the failure stack to the largest possible stack. This + isn't necessary unless we're trying to avoid calling alloca in + the search and match routines. */ + { + int num_regs = bufp->re_nsub + 1; + + /* Since DOUBLE_FAIL_STACK refuses to double only if the current size + is strictly greater than re_max_failures, the largest possible stack + is 2 * re_max_failures failure points. */ + fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); + if (fail_stack.stack) + fail_stack.stack = + (fail_stack_elt_t *) realloc (fail_stack.stack, + (fail_stack.size + * sizeof (fail_stack_elt_t))); + else + fail_stack.stack = + (fail_stack_elt_t *) malloc (fail_stack.size + * sizeof (fail_stack_elt_t)); + + /* Initialize some other variables the matcher uses. */ + RETALLOC_IF (regstart, num_regs, const char *); + RETALLOC_IF (regend, num_regs, const char *); + RETALLOC_IF (old_regstart, num_regs, const char *); + RETALLOC_IF (old_regend, num_regs, const char *); + RETALLOC_IF (best_regstart, num_regs, const char *); + RETALLOC_IF (best_regend, num_regs, const char *); + RETALLOC_IF (reg_info, num_regs, register_info_type); + RETALLOC_IF (reg_dummy, num_regs, const char *); + RETALLOC_IF (reg_info_dummy, num_regs, register_info_type); + } +#endif + + return REG_NOERROR; +} /* regex_compile */ + +/* Subroutines for `regex_compile'. */ + +/* Store OP at LOC followed by two-byte integer parameter ARG. */ + +static void +store_op1 (op, loc, arg) + re_opcode_t op; + unsigned char *loc; + int arg; +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg); +} + + +/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +store_op2 (op, loc, arg1, arg2) + re_opcode_t op; + unsigned char *loc; + int arg1, arg2; +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg1); + STORE_NUMBER (loc + 3, arg2); +} + + +/* Copy the bytes from LOC to END to open up three bytes of space at LOC + for OP followed by two-byte integer parameter ARG. */ + +static void +insert_op1 (op, loc, arg, end) + re_opcode_t op; + unsigned char *loc; + int arg; + unsigned char *end; +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 3; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op1 (op, loc, arg); +} + + +/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +insert_op2 (op, loc, arg1, arg2, end) + re_opcode_t op; + unsigned char *loc; + int arg1, arg2; + unsigned char *end; +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 5; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op2 (op, loc, arg1, arg2); +} + + +/* P points to just after a ^ in PATTERN. Return true if that ^ comes + after an alternative or a begin-subexpression. We assume there is at + least one character before the ^. */ + +static boolean +at_begline_loc_p (pattern, p, syntax) + const char *pattern, *p; + reg_syntax_t syntax; +{ + const char *prev = p - 2; + boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; + + return + /* After a subexpression? */ + (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) + /* After an alternative? */ + || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); +} + + +/* The dual of at_begline_loc_p. This one is for $. We assume there is + at least one character after the $, i.e., `P < PEND'. */ + +static boolean +at_endline_loc_p (p, pend, syntax) + const char *p, *pend; + int syntax; +{ + const char *next = p; + boolean next_backslash = *next == '\\'; + const char *next_next = p + 1 < pend ? p + 1 : NULL; + + return + /* Before a subexpression? */ + (syntax & RE_NO_BK_PARENS ? *next == ')' + : next_backslash && next_next && *next_next == ')') + /* Before an alternative? */ + || (syntax & RE_NO_BK_VBAR ? *next == '|' + : next_backslash && next_next && *next_next == '|'); +} + + +/* Returns true if REGNUM is in one of COMPILE_STACK's elements and + false if it's not. */ + +static boolean +group_in_compile_stack (compile_stack, regnum) + compile_stack_type compile_stack; + regnum_t regnum; +{ + int this_element; + + for (this_element = compile_stack.avail - 1; + this_element >= 0; + this_element--) + if (compile_stack.stack[this_element].regnum == regnum) + return true; + + return false; +} + + +/* Read the ending character of a range (in a bracket expression) from the + uncompiled pattern *P_PTR (which ends at PEND). We assume the + starting character is in `P[-2]'. (`P[-1]' is the character `-'.) + Then we set the translation of all bits between the starting and + ending characters (inclusive) in the compiled pattern B. + + Return an error code. + + We use these short variable names so we can use the same macros as + `regex_compile' itself. */ + +static reg_errcode_t +compile_range (p_ptr, pend, translate, syntax, b) + const char **p_ptr, *pend; + char *translate; + reg_syntax_t syntax; + unsigned char *b; +{ + unsigned this_char; + + const char *p = *p_ptr; + int range_start, range_end; + + if (p == pend) + return REG_ERANGE; + + /* Even though the pattern is a signed `char *', we need to fetch + with unsigned char *'s; if the high bit of the pattern character + is set, the range endpoints will be negative if we fetch using a + signed char *. + + We also want to fetch the endpoints without translating them; the + appropriate translation is done in the bit-setting loop below. */ + range_start = ((unsigned char *) p)[-2]; + range_end = ((unsigned char *) p)[0]; + + /* Have to increment the pointer into the pattern string, so the + caller isn't still at the ending character. */ + (*p_ptr)++; + + /* If the start is after the end, the range is empty. */ + if (range_start > range_end) + return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; + + /* Here we see why `this_char' has to be larger than an `unsigned + char' -- the range is inclusive, so if `range_end' == 0xff + (assuming 8-bit characters), we would otherwise go into an infinite + loop, since all characters <= 0xff. */ + for (this_char = range_start; this_char <= range_end; this_char++) + { + SET_LIST_BIT (TRANSLATE (this_char)); + } + + return REG_NOERROR; +} + +/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in + BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible + characters can start a string that matches the pattern. This fastmap + is used by re_search to skip quickly over impossible starting points. + + The caller must supply the address of a (1 << BYTEWIDTH)-byte data + area as BUFP->fastmap. + + We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in + the pattern buffer. + + Returns 0 if we succeed, -2 if an internal error. */ + +int +re_compile_fastmap (bufp) + struct re_pattern_buffer *bufp; +{ + int j, k; +#ifdef MATCH_MAY_ALLOCATE + fail_stack_type fail_stack; +#endif +#ifndef REGEX_MALLOC + char *destination; +#endif + /* We don't push any register information onto the failure stack. */ + unsigned num_regs = 0; + + register char *fastmap = bufp->fastmap; + unsigned char *pattern = bufp->buffer; + unsigned long size = bufp->used; + unsigned char *p = pattern; + register unsigned char *pend = pattern + size; + + /* Assume that each path through the pattern can be null until + proven otherwise. We set this false at the bottom of switch + statement, to which we get only if a particular path doesn't + match the empty string. */ + boolean path_can_be_null = true; + + /* We aren't doing a `succeed_n' to begin with. */ + boolean succeed_n_p = false; + + assert (fastmap != NULL && p != NULL); + + INIT_FAIL_STACK (); + bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ + bufp->fastmap_accurate = 1; /* It will be when we're done. */ + bufp->can_be_null = 0; + + while (p != pend || !FAIL_STACK_EMPTY ()) + { + if (p == pend) + { + bufp->can_be_null |= path_can_be_null; + + /* Reset for next path. */ + path_can_be_null = true; + + p = fail_stack.stack[--fail_stack.avail]; + } + + /* We should never be about to go beyond the end of the pattern. */ + assert (p < pend); + +#ifdef SWITCH_ENUM_BUG + switch ((int) ((re_opcode_t) *p++)) +#else + switch ((re_opcode_t) *p++) +#endif + { + + /* I guess the idea here is to simply not bother with a fastmap + if a backreference is used, since it's too hard to figure out + the fastmap for the corresponding group. Setting + `can_be_null' stops `re_search_2' from using the fastmap, so + that is all we do. */ + case duplicate: + bufp->can_be_null = 1; + return 0; + + + /* Following are the cases which match a character. These end + with `break'. */ + + case exactn: + fastmap[p[1]] = 1; + break; + + + case charset: + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) + fastmap[j] = 1; + break; + + + case charset_not: + /* Chars beyond end of map must be allowed. */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) + fastmap[j] = 1; + break; + + + case wordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == Sword) + fastmap[j] = 1; + break; + + + case notwordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != Sword) + fastmap[j] = 1; + break; + + + case anychar: + /* `.' matches anything ... */ + for (j = 0; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + /* ... except perhaps newline. */ + if (!(bufp->syntax & RE_DOT_NEWLINE)) + fastmap['\n'] = 0; + + /* Return if we have already set `can_be_null'; if we have, + then the fastmap is irrelevant. Something's wrong here. */ + else if (bufp->can_be_null) + return 0; + + /* Otherwise, have to check alternative paths. */ + break; + + +#ifdef emacs + case syntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + case notsyntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + /* All cases after this match the empty string. These end with + `continue'. */ + + + case before_dot: + case at_dot: + case after_dot: + continue; +#endif /* not emacs */ + + + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + case push_dummy_failure: + continue; + + + case jump_n: + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case jump_past_alt: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (j > 0) + continue; + + /* Jump backward implies we just went through the body of a + loop and matched nothing. Opcode jumped to should be + `on_failure_jump' or `succeed_n'. Just treat it like an + ordinary jump. For a * loop, it has pushed its failure + point already; if so, discard that as redundant. */ + if ((re_opcode_t) *p != on_failure_jump + && (re_opcode_t) *p != succeed_n) + continue; + + p++; + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + + /* If what's on the stack is where we are now, pop it. */ + if (!FAIL_STACK_EMPTY () + && fail_stack.stack[fail_stack.avail - 1] == p) + fail_stack.avail--; + + continue; + + + case on_failure_jump: + case on_failure_keep_string_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + + /* For some patterns, e.g., `(a?)?', `p+j' here points to the + end of the pattern. We don't want to push such a point, + since when we restore it above, entering the switch will + increment `p' past the end of the pattern. We don't need + to push such a point since we obviously won't find any more + fastmap entries beyond `pend'. Such a pattern can match + the null string, though. */ + if (p + j < pend) + { + if (!PUSH_PATTERN_OP (p + j, fail_stack)) + return -2; + } + else + bufp->can_be_null = 1; + + if (succeed_n_p) + { + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ + succeed_n_p = false; + } + + continue; + + + case succeed_n: + /* Get to the number of times to succeed. */ + p += 2; + + /* Increment p past the n for when k != 0. */ + EXTRACT_NUMBER_AND_INCR (k, p); + if (k == 0) + { + p -= 4; + succeed_n_p = true; /* Spaghetti code alert. */ + goto handle_on_failure_jump; + } + continue; + + + case set_number_at: + p += 4; + continue; + + + case start_memory: + case stop_memory: + p += 2; + continue; + + + default: + abort (); /* We have listed all the cases. */ + } /* switch *p++ */ + + /* Getting here means we have found the possible starting + characters for one path of the pattern -- and that the empty + string does not match. We need not follow this path further. + Instead, look at the next alternative (remembered on the + stack), or quit if no more. The test at the top of the loop + does these things. */ + path_can_be_null = false; + p = pend; + } /* while p */ + + /* Set `can_be_null' for the last path (also the first path, if the + pattern is empty). */ + bufp->can_be_null |= path_can_be_null; + return 0; +} /* re_compile_fastmap */ + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use + this memory for recording register information. STARTS and ENDS + must be allocated using the malloc library routine, and must each + be at least NUM_REGS * sizeof (regoff_t) bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ + +void +re_set_registers (bufp, regs, num_regs, starts, ends) + struct re_pattern_buffer *bufp; + struct re_registers *regs; + unsigned num_regs; + regoff_t *starts, *ends; +{ + if (num_regs) + { + bufp->regs_allocated = REGS_REALLOCATE; + regs->num_regs = num_regs; + regs->start = starts; + regs->end = ends; + } + else + { + bufp->regs_allocated = REGS_UNALLOCATED; + regs->num_regs = 0; + regs->start = regs->end = (regoff_t) 0; + } +} + +/* Searching routines. */ + +/* Like re_search_2, below, but only one string is specified, and + doesn't let you say where to stop matching. */ + +int +re_search (bufp, string, size, startpos, range, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, startpos, range; + struct re_registers *regs; +{ + return re_search_2 (bufp, NULL, 0, string, size, startpos, range, + regs, size); +} + + +/* Using the compiled pattern in BUFP->buffer, first tries to match the + virtual concatenation of STRING1 and STRING2, starting first at index + STARTPOS, then at STARTPOS + 1, and so on. + + STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. + + RANGE is how far to scan while trying to match. RANGE = 0 means try + only at STARTPOS; in general, the last start tried is STARTPOS + + RANGE. + + In REGS, return the indices of the virtual concatenation of STRING1 + and STRING2 that matched the entire BUFP->buffer and its contained + subexpressions. + + Do not consider matching one past the index STOP in the virtual + concatenation of STRING1 and STRING2. + + We return either the position in the strings at which the match was + found, -1 if no match, or -2 if error (such as failure + stack overflow). */ + +int +re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int startpos; + int range; + struct re_registers *regs; + int stop; +{ + int val; + register char *fastmap = bufp->fastmap; + register char *translate = bufp->translate; + int total_size = size1 + size2; + int endpos = startpos + range; + + /* Check for out-of-range STARTPOS. */ + if (startpos < 0 || startpos > total_size) + return -1; + + /* Fix up RANGE if it might eventually take us outside + the virtual concatenation of STRING1 and STRING2. */ + if (endpos < -1) + range = -1 - startpos; + else if (endpos > total_size) + range = total_size - startpos; + + /* If the search isn't to be a backwards one, don't waste time in a + search for a pattern that must be anchored. */ + if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0) + { + if (startpos > 0) + return -1; + else + range = 1; + } + + /* Update the fastmap now if not correct already. */ + if (fastmap && !bufp->fastmap_accurate) + if (re_compile_fastmap (bufp) == -2) + return -2; + + /* Loop through the string, looking for a place to start matching. */ + for (;;) + { + /* If a fastmap is supplied, skip quickly over characters that + cannot be the start of a match. If the pattern can match the + null string, however, we don't need to skip characters; we want + the first null string. */ + if (fastmap && startpos < total_size && !bufp->can_be_null) + { + if (range > 0) /* Searching forwards. */ + { + register const char *d; + register int lim = 0; + int irange = range; + + if (startpos < size1 && startpos + range >= size1) + lim = range - (size1 - startpos); + + d = (startpos >= size1 ? string2 - size1 : string1) + startpos; + + /* Written out as an if-else to avoid testing `translate' + inside the loop. */ + if (translate) + while (range > lim + && !fastmap[(unsigned char) + translate[(unsigned char) *d++]]) + range--; + else + while (range > lim && !fastmap[(unsigned char) *d++]) + range--; + + startpos += irange - range; + } + else /* Searching backwards. */ + { + register char c = (size1 == 0 || startpos >= size1 + ? string2[startpos - size1] + : string1[startpos]); + + if (!fastmap[(unsigned char) TRANSLATE (c)]) + goto advance; + } + } + + /* If can't match the null string, and that's all we have left, fail. */ + if (range >= 0 && startpos == total_size && fastmap + && !bufp->can_be_null) + return -1; + + val = re_match_2 (bufp, string1, size1, string2, size2, + startpos, regs, stop); + if (val >= 0) + return startpos; + + if (val == -2) + return -2; + + advance: + if (!range) + break; + else if (range > 0) + { + range--; + startpos++; + } + else + { + range++; + startpos--; + } + } + return -1; +} /* re_search_2 */ + +/* Declarations and macros for re_match_2. */ + +static int bcmp_translate (); +static boolean alt_match_null_string_p (), + common_op_match_null_string_p (), + group_match_null_string_p (); + +/* This converts PTR, a pointer into one of the search strings `string1' + and `string2' into an offset from the beginning of that string. */ +#define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) \ + ? ((regoff_t) ((ptr) - string1)) \ + : ((regoff_t) ((ptr) - string2 + size1))) + +/* Macros for dealing with the split strings in re_match_2. */ + +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) + +/* Call before fetching a character with *d. This switches over to + string2 if necessary. */ +#define PREFETCH() \ + while (d == dend) \ + { \ + /* End of string2 => fail. */ \ + if (dend == end_match_2) \ + goto fail; \ + /* End of string1 => advance to string2. */ \ + d = string2; \ + dend = end_match_2; \ + } + + +/* Test if at very beginning or at very end of the virtual concatenation + of `string1' and `string2'. If only one string, it's `string2'. */ +#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) +#define AT_STRINGS_END(d) ((d) == end2) + + +/* Test if D points to a character which is word-constituent. We have + two special cases to check for: if past the end of string1, look at + the first character in string2; and if before the beginning of + string2, look at the last character in string1. */ +#define WORDCHAR_P(d) \ + (SYNTAX ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ + == Sword) + +/* Test if the character before D and the one at D differ with respect + to being word-constituent. */ +#define AT_WORD_BOUNDARY(d) \ + (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ + || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) + + +/* Free everything we malloc. */ +#ifdef MATCH_MAY_ALLOCATE +#ifdef REGEX_MALLOC +#define FREE_VAR(var) if (var) free (var); var = NULL +#define FREE_VARIABLES() \ + do { \ + FREE_VAR (fail_stack.stack); \ + FREE_VAR (regstart); \ + FREE_VAR (regend); \ + FREE_VAR (old_regstart); \ + FREE_VAR (old_regend); \ + FREE_VAR (best_regstart); \ + FREE_VAR (best_regend); \ + FREE_VAR (reg_info); \ + FREE_VAR (reg_dummy); \ + FREE_VAR (reg_info_dummy); \ + } while (0) +#else /* not REGEX_MALLOC */ +/* Some MIPS systems (at least) want this to free alloca'd storage. */ +#define FREE_VARIABLES() alloca (0) +#endif /* not REGEX_MALLOC */ +#else +#define FREE_VARIABLES() /* Do nothing! */ +#endif /* not MATCH_MAY_ALLOCATE */ + +/* These values must meet several constraints. They must not be valid + register values; since we have a limit of 255 registers (because + we use only one byte in the pattern for the register number), we can + use numbers larger than 255. They must differ by 1, because of + NUM_FAILURE_ITEMS above. And the value for the lowest register must + be larger than the value for the highest register, so we do not try + to actually save any registers when none are active. */ +#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) +#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) + +/* Matching routines. */ + +#ifndef emacs /* Emacs never uses this. */ +/* re_match is like re_match_2 except it takes only a single string. */ + +int +re_match (bufp, string, size, pos, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, pos; + struct re_registers *regs; + { + return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size); +} +#endif /* not emacs */ + + +/* re_match_2 matches the compiled pattern in BUFP against the + the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 + and SIZE2, respectively). We start matching at POS, and stop + matching at STOP. + + If REGS is non-null and the `no_sub' field of BUFP is nonzero, we + store offsets for the substring each group matched in REGS. See the + documentation for exactly how many groups we fill. + + We return -1 if no match, -2 if an internal error (such as the + failure stack overflowing). Otherwise, we return the length of the + matched substring. */ + +int +re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int pos; + struct re_registers *regs; + int stop; +{ + /* General temporaries. */ + int mcnt; + unsigned char *p1; + + /* Just past the end of the corresponding string. */ + const char *end1, *end2; + + /* Pointers into string1 and string2, just past the last characters in + each to consider matching. */ + const char *end_match_1, *end_match_2; + + /* Where we are in the data, and the end of the current string. */ + const char *d, *dend; + + /* Where we are in the pattern, and the end of the pattern. */ + unsigned char *p = bufp->buffer; + register unsigned char *pend = p + bufp->used; + + /* We use this to map every character in the string. */ + char *translate = bufp->translate; + + /* Failure point stack. Each place that can handle a failure further + down the line pushes a failure point on this stack. It consists of + restart, regend, and reg_info for all registers corresponding to + the subexpressions we're currently inside, plus the number of such + registers, and, finally, two char *'s. The first char * is where + to resume scanning the pattern; the second one is where to resume + scanning the strings. If the latter is zero, the failure point is + a ``dummy''; if a failure happens and the failure point is a dummy, + it gets discarded and the next next one is tried. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ + fail_stack_type fail_stack; +#endif +#ifdef DEBUG + static unsigned failure_id = 0; + unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; +#endif + + /* We fill all the registers internally, independent of what we + return, for use in backreferences. The number here includes + an element for register zero. */ + unsigned num_regs = bufp->re_nsub + 1; + + /* The currently active registers. */ + unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG; + unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG; + + /* Information on the contents of registers. These are pointers into + the input strings; they record just what was matched (on this + attempt) by a subexpression part of the pattern, that is, the + regnum-th regstart pointer points to where in the pattern we began + matching and the regnum-th regend points to right after where we + stopped matching the regnum-th subexpression. (The zeroth register + keeps track of what the whole pattern matches.) */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **regstart, **regend; +#endif + + /* If a group that's operated upon by a repetition operator fails to + match anything, then the register for its start will need to be + restored because it will have been set to wherever in the string we + are when we last see its open-group operator. Similarly for a + register's end. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **old_regstart, **old_regend; +#endif + + /* The is_active field of reg_info helps us keep track of which (possibly + nested) subexpressions we are currently in. The matched_something + field of reg_info[reg_num] helps us tell whether or not we have + matched any of the pattern so far this time through the reg_num-th + subexpression. These two fields get reset each time through any + loop their register is in. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ + register_info_type *reg_info; +#endif + + /* The following record the register info as found in the above + variables when we find a match better than any we've seen before. + This happens as we backtrack through the failure points, which in + turn happens only if we have not yet matched the entire string. */ + unsigned best_regs_set = false; +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **best_regstart, **best_regend; +#endif + + /* Logically, this is `best_regend[0]'. But we don't want to have to + allocate space for that if we're not allocating space for anything + else (see below). Also, we never need info about register 0 for + any of the other register vectors, and it seems rather a kludge to + treat `best_regend' differently than the rest. So we keep track of + the end of the best match so far in a separate variable. We + initialize this to NULL so that when we backtrack the first time + and need to test it, it's not garbage. */ + const char *match_end = NULL; + + /* Used when we pop values we don't care about. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const char **reg_dummy; + register_info_type *reg_info_dummy; +#endif + +#ifdef DEBUG + /* Counts the total number of registers pushed. */ + unsigned num_regs_pushed = 0; +#endif + + DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); + + INIT_FAIL_STACK (); + +#ifdef MATCH_MAY_ALLOCATE + /* Do not bother to initialize all the register variables if there are + no groups in the pattern, as it takes a fair amount of time. If + there are groups, we include space for register 0 (the whole + pattern), even though we never use it, since it simplifies the + array indexing. We should fix this. */ + if (bufp->re_nsub) + { + regstart = REGEX_TALLOC (num_regs, const char *); + regend = REGEX_TALLOC (num_regs, const char *); + old_regstart = REGEX_TALLOC (num_regs, const char *); + old_regend = REGEX_TALLOC (num_regs, const char *); + best_regstart = REGEX_TALLOC (num_regs, const char *); + best_regend = REGEX_TALLOC (num_regs, const char *); + reg_info = REGEX_TALLOC (num_regs, register_info_type); + reg_dummy = REGEX_TALLOC (num_regs, const char *); + reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); + + if (!(regstart && regend && old_regstart && old_regend && reg_info + && best_regstart && best_regend && reg_dummy && reg_info_dummy)) + { + FREE_VARIABLES (); + return -2; + } + } +#if defined (REGEX_MALLOC) + else + { + /* We must initialize all our variables to NULL, so that + `FREE_VARIABLES' doesn't try to free them. */ + regstart = regend = old_regstart = old_regend = best_regstart + = best_regend = reg_dummy = NULL; + reg_info = reg_info_dummy = (register_info_type *) NULL; + } +#endif /* REGEX_MALLOC */ +#endif /* MATCH_MAY_ALLOCATE */ + + /* The starting position is bogus. */ + if (pos < 0 || pos > size1 + size2) + { + FREE_VARIABLES (); + return -1; + } + + /* Initialize subexpression text positions to -1 to mark ones that no + start_memory/stop_memory has been seen for. Also initialize the + register information struct. */ + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + regstart[mcnt] = regend[mcnt] + = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; + + REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; + IS_ACTIVE (reg_info[mcnt]) = 0; + MATCHED_SOMETHING (reg_info[mcnt]) = 0; + EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; + } + + /* We move `string1' into `string2' if the latter's empty -- but not if + `string1' is null. */ + if (size2 == 0 && string1 != NULL) + { + string2 = string1; + size2 = size1; + string1 = 0; + size1 = 0; + } + end1 = string1 + size1; + end2 = string2 + size2; + + /* Compute where to stop matching, within the two strings. */ + if (stop <= size1) + { + end_match_1 = string1 + stop; + end_match_2 = string2; + } + else + { + end_match_1 = end1; + end_match_2 = string2 + stop - size1; + } + + /* `p' scans through the pattern as `d' scans through the data. + `dend' is the end of the input string that `d' points within. `d' + is advanced into the following input string whenever necessary, but + this happens before fetching; therefore, at the beginning of the + loop, `d' can be pointing at the end of a string, but it cannot + equal `string2'. */ + if (size1 > 0 && pos <= size1) + { + d = string1 + pos; + dend = end_match_1; + } + else + { + d = string2 + pos - size1; + dend = end_match_2; + } + + DEBUG_PRINT1 ("The compiled pattern is: "); + DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); + DEBUG_PRINT1 ("The string to match is: `"); + DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); + DEBUG_PRINT1 ("'\n"); + + /* This loops over pattern commands. It exits by returning from the + function if the match is complete, or it drops through if the match + fails at this starting point in the input data. */ + for (;;) + { + DEBUG_PRINT2 ("\n0x%x: ", p); + + if (p == pend) + { /* End of pattern means we might have succeeded. */ + DEBUG_PRINT1 ("end of pattern ... "); + + /* If we haven't matched the entire string, and we want the + longest match, try backtracking. */ + if (d != end_match_2) + { + DEBUG_PRINT1 ("backtracking.\n"); + + if (!FAIL_STACK_EMPTY ()) + { /* More failure points to try. */ + boolean same_str_p = (FIRST_STRING_P (match_end) + == MATCHING_IN_FIRST_STRING); + + /* If exceeds best match so far, save it. */ + if (!best_regs_set + || (same_str_p && d > match_end) + || (!same_str_p && !MATCHING_IN_FIRST_STRING)) + { + best_regs_set = true; + match_end = d; + + DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); + + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } + + /* If no failure points, don't restore garbage. */ + else if (best_regs_set) + { + restore_best_regs: + /* Restore best match. It may happen that `dend == + end_match_1' while the restored d is in string2. + For example, the pattern `x.*y.*z' against the + strings `x-' and `y-z-', if the two strings are + not consecutive in memory. */ + DEBUG_PRINT1 ("Restoring best registers.\n"); + + d = match_end; + dend = ((d >= string1 && d <= end1) + ? end_match_1 : end_match_2); + + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } /* d != end_match_2 */ + + DEBUG_PRINT1 ("Accepting match.\n"); + + /* If caller wants register contents data back, do it. */ + if (regs && !bufp->no_sub) + { + /* Have the register data arrays been allocated? */ + if (bufp->regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. We need one + extra element beyond `num_regs' for the `-1' marker + GNU code uses. */ + regs->num_regs = MAX (RE_NREGS, num_regs + 1); + regs->start = TALLOC (regs->num_regs, regoff_t); + regs->end = TALLOC (regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + return -2; + bufp->regs_allocated = REGS_REALLOCATE; + } + else if (bufp->regs_allocated == REGS_REALLOCATE) + { /* Yes. If we need more elements than were already + allocated, reallocate them. If we need fewer, just + leave it alone. */ + if (regs->num_regs < num_regs + 1) + { + regs->num_regs = num_regs + 1; + RETALLOC (regs->start, regs->num_regs, regoff_t); + RETALLOC (regs->end, regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + return -2; + } + } + else + { + /* These braces fend off a "empty body in an else-statement" + warning under GCC when assert expands to nothing. */ + assert (bufp->regs_allocated == REGS_FIXED); + } + + /* Convert the pointer data in `regstart' and `regend' to + indices. Register zero has to be set differently, + since we haven't kept track of any info for it. */ + if (regs->num_regs > 0) + { + regs->start[0] = pos; + regs->end[0] = (MATCHING_IN_FIRST_STRING + ? ((regoff_t) (d - string1)) + : ((regoff_t) (d - string2 + size1))); + } + + /* Go through the first `min (num_regs, regs->num_regs)' + registers, since that is all we initialized. */ + for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++) + { + if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) + regs->start[mcnt] = regs->end[mcnt] = -1; + else + { + regs->start[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); + regs->end[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); + } + } + + /* If the regs structure we return has more elements than + were in the pattern, set the extra elements to -1. If + we (re)allocated the registers, this is the case, + because we always allocate enough to have at least one + -1 at the end. */ + for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; + } /* regs && !bufp->no_sub */ + + FREE_VARIABLES (); + DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", + nfailure_points_pushed, nfailure_points_popped, + nfailure_points_pushed - nfailure_points_popped); + DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); + + mcnt = d - pos - (MATCHING_IN_FIRST_STRING + ? string1 + : string2 - size1); + + DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); + + return mcnt; + } + + /* Otherwise match next pattern command. */ +#ifdef SWITCH_ENUM_BUG + switch ((int) ((re_opcode_t) *p++)) +#else + switch ((re_opcode_t) *p++) +#endif + { + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case no_op: + DEBUG_PRINT1 ("EXECUTING no_op.\n"); + break; + + + /* Match the next n pattern characters exactly. The following + byte in the pattern defines n, and the n bytes after that + are the characters to match. */ + case exactn: + mcnt = *p++; + DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); + + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (translate) + { + do + { + PREFETCH (); + if (translate[(unsigned char) *d++] != (char) *p++) + goto fail; + } + while (--mcnt); + } + else + { + do + { + PREFETCH (); + if (*d++ != (char) *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED (); + break; + + + /* Match any character except possibly a newline or a null. */ + case anychar: + DEBUG_PRINT1 ("EXECUTING anychar.\n"); + + PREFETCH (); + + if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') + || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) + goto fail; + + SET_REGS_MATCHED (); + DEBUG_PRINT2 (" Matched `%d'.\n", *d); + d++; + break; + + + case charset: + case charset_not: + { + register unsigned char c; + boolean not = (re_opcode_t) *(p - 1) == charset_not; + + DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); + + PREFETCH (); + c = TRANSLATE (*d); /* The character to match. */ + + /* Cast to `unsigned' instead of `unsigned char' in case the + bit list is a full 32 bytes long. */ + if (c < (unsigned) (*p * BYTEWIDTH) + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + p += 1 + *p; + + if (!not) goto fail; + + SET_REGS_MATCHED (); + d++; + break; + } + + + /* The beginning of a group is represented by start_memory. + The arguments are the register number in the next byte, and the + number of groups inner to this one in the next. The text + matched within the group is recorded (in the internal + registers data structure) under the register number. */ + case start_memory: + DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); + + /* Find out if this group can match the empty string. */ + p1 = p; /* To send to group_match_null_string_p. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[*p]) + = group_match_null_string_p (&p1, pend, reg_info); + + /* Save the position in the string where we were the last time + we were at this open-group operator in case the group is + operated upon by a repetition operator, e.g., with `(a*)*b' + against `ab'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regstart[*p]) ? d : regstart[*p] + : regstart[*p]; + DEBUG_PRINT2 (" old_regstart: %d\n", + POINTER_TO_OFFSET (old_regstart[*p])); + + regstart[*p] = d; + DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); + + IS_ACTIVE (reg_info[*p]) = 1; + MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* This is the new highest active register. */ + highest_active_reg = *p; + + /* If nothing was active before, this is the new lowest active + register. */ + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *p; + + /* Move past the register number and inner group count. */ + p += 2; + break; + + + /* The stop_memory opcode represents the end of a group. Its + arguments are the same as start_memory's: the register + number, and the number of inner groups. */ + case stop_memory: + DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); + + /* We need to save the string position the last time we were at + this close-group operator in case the group is operated + upon by a repetition operator, e.g., with `((a*)*(b*)*)*' + against `aba'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regend[*p]) ? d : regend[*p] + : regend[*p]; + DEBUG_PRINT2 (" old_regend: %d\n", + POINTER_TO_OFFSET (old_regend[*p])); + + regend[*p] = d; + DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); + + /* This register isn't active anymore. */ + IS_ACTIVE (reg_info[*p]) = 0; + + /* If this was the only register active, nothing is active + anymore. */ + if (lowest_active_reg == highest_active_reg) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + { /* We must scan for the new highest active register, since + it isn't necessarily one less than now: consider + (a(b)c(d(e)f)g). When group 3 ends, after the f), the + new highest active register is 1. */ + unsigned char r = *p - 1; + while (r > 0 && !IS_ACTIVE (reg_info[r])) + r--; + + /* If we end up at register zero, that means that we saved + the registers as the result of an `on_failure_jump', not + a `start_memory', and we jumped to past the innermost + `stop_memory'. For example, in ((.)*) we save + registers 1 and 2 as a result of the *, but when we pop + back to the second ), we are at the stop_memory 1. + Thus, nothing is active. */ + if (r == 0) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + highest_active_reg = r; + } + + /* If just failed to match something this time around with a + group that's operated on by a repetition operator, try to + force exit from the ``loop'', and restore the register + information for this group that we had before trying this + last match. */ + if ((!MATCHED_SOMETHING (reg_info[*p]) + || (re_opcode_t) p[-3] == start_memory) + && (p + 2) < pend) + { + boolean is_a_jump_n = false; + + p1 = p + 2; + mcnt = 0; + switch ((re_opcode_t) *p1++) + { + case jump_n: + is_a_jump_n = true; + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (is_a_jump_n) + p1 += 2; + break; + + default: + /* do nothing */ ; + } + p1 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump right before the start_memory + corresponding to this stop_memory, exit from the loop + by forcing a failure after pushing on the stack the + on_failure_jump's jump in the pattern, and d. */ + if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump + && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) + { + /* If this group ever matched anything, then restore + what its registers were before trying this last + failed match, e.g., with `(a*)*b' against `ab' for + regstart[1], and, e.g., with `((a*)*(b*)*)*' + against `aba' for regend[3]. + + Also restore the registers for inner groups for, + e.g., `((a*)(b*))*' against `aba' (register 3 would + otherwise get trashed). */ + + if (EVER_MATCHED_SOMETHING (reg_info[*p])) + { + unsigned r; + + EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Restore this and inner groups' (if any) registers. */ + for (r = *p; r < *p + *(p + 1); r++) + { + regstart[r] = old_regstart[r]; + + /* xx why this test? */ + if ((int) old_regend[r] >= (int) regstart[r]) + regend[r] = old_regend[r]; + } + } + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + PUSH_FAILURE_POINT (p1 + mcnt, d, -2); + + goto fail; + } + } + + /* Move past the register number and the inner group count. */ + p += 2; + break; + + + /* \ has been turned into a `duplicate' command which is + followed by the numeric value of as the register number. */ + case duplicate: + { + register const char *d2, *dend2; + int regno = *p++; /* Get which register to match against. */ + DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); + + /* Can't back reference a group which we've never matched. */ + if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) + goto fail; + + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ + + dend2 = ((FIRST_STRING_P (regstart[regno]) + == FIRST_STRING_P (regend[regno])) + ? regend[regno] : end_match_1); + for (;;) + { + /* If necessary, advance to next segment in register + contents. */ + while (d2 == dend2) + { + if (dend2 == end_match_2) break; + if (dend2 == regend[regno]) break; + + /* End of string1 => advance to string2. */ + d2 = string2; + dend2 = regend[regno]; + } + /* At end of register contents => success */ + if (d2 == dend2) break; + + /* If necessary, advance to next segment in data. */ + PREFETCH (); + + /* How many characters left in this segment to match. */ + mcnt = dend - d; + + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + + /* Compare that many; failure if mismatch, else move + past them. */ + if (translate + ? bcmp_translate (d, d2, mcnt, translate) + : bcmp (d, d2, mcnt)) + goto fail; + d += mcnt, d2 += mcnt; + } + } + break; + + + /* begline matches the empty string at the beginning of the string + (unless `not_bol' is set in `bufp'), and, if + `newline_anchor' is set, after newlines. */ + case begline: + DEBUG_PRINT1 ("EXECUTING begline.\n"); + + if (AT_STRINGS_BEG (d)) + { + if (!bufp->not_bol) break; + } + else if (d[-1] == '\n' && bufp->newline_anchor) + { + break; + } + /* In all other cases, we fail. */ + goto fail; + + + /* endline is the dual of begline. */ + case endline: + DEBUG_PRINT1 ("EXECUTING endline.\n"); + + if (AT_STRINGS_END (d)) + { + if (!bufp->not_eol) break; + } + + /* We have to ``prefetch'' the next character. */ + else if ((d == end1 ? *string2 : *d) == '\n' + && bufp->newline_anchor) + { + break; + } + goto fail; + + + /* Match at the very beginning of the data. */ + case begbuf: + DEBUG_PRINT1 ("EXECUTING begbuf.\n"); + if (AT_STRINGS_BEG (d)) + break; + goto fail; + + + /* Match at the very end of the data. */ + case endbuf: + DEBUG_PRINT1 ("EXECUTING endbuf.\n"); + if (AT_STRINGS_END (d)) + break; + goto fail; + + + /* on_failure_keep_string_jump is used to optimize `.*\n'. It + pushes NULL as the value for the string on the stack. Then + `pop_failure_point' will keep the current value for the + string, instead of restoring it. To see why, consider + matching `foo\nbar' against `.*\n'. The .* matches the foo; + then the . fails against the \n. But the next thing we want + to do is match the \n against the \n; if we restored the + string value, we would be back at the foo. + + Because this is used only in specific cases, we don't need to + check all the things that `on_failure_jump' does, to make + sure the right things get saved on the stack. Hence we don't + share its code. The only reason to push anything on the + stack at all is that otherwise we would have to change + `anychar's code to do something besides goto fail in this + case; that seems worse than this. */ + case on_failure_keep_string_jump: + DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); + + PUSH_FAILURE_POINT (p + mcnt, NULL, -2); + break; + + + /* Uses of on_failure_jump: + + Each alternative starts with an on_failure_jump that points + to the beginning of the next alternative. Each alternative + except the last ends with a jump that in effect jumps past + the rest of the alternatives. (They really jump to the + ending jump of the following alternative, because tensioning + these jumps is a hassle.) + + Repeats start with an on_failure_jump that points past both + the repetition text and either the following jump or + pop_failure_jump back to this on_failure_jump. */ + case on_failure_jump: + on_failure: + DEBUG_PRINT1 ("EXECUTING on_failure_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); + + /* If this on_failure_jump comes right before a group (i.e., + the original * applied to a group), save the information + for that group and all inner ones, so that if we fail back + to this point, the group's information will be correct. + For example, in \(a*\)*\1, we need the preceding group, + and in \(\(a*\)b*\)\2, we need the inner group. */ + + /* We can't use `p' to check ahead because we push + a failure point to `p + mcnt' after we do this. */ + p1 = p; + + /* We need to skip no_op's before we look for the + start_memory in case this on_failure_jump is happening as + the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 + against aba. */ + while (p1 < pend && (re_opcode_t) *p1 == no_op) + p1++; + + if (p1 < pend && (re_opcode_t) *p1 == start_memory) + { + /* We have a new highest active register now. This will + get reset at the start_memory we are about to get to, + but we will have saved all the registers relevant to + this repetition op, as described above. */ + highest_active_reg = *(p1 + 1) + *(p1 + 2); + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *(p1 + 1); + } + + DEBUG_PRINT1 (":\n"); + PUSH_FAILURE_POINT (p + mcnt, d, -2); + break; + + + /* A smart repeat ends with `maybe_pop_jump'. + We change it to either `pop_failure_jump' or `jump'. */ + case maybe_pop_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); + { + register unsigned char *p2 = p; + + /* Compare the beginning of the repeat with what in the + pattern follows its end. If we can establish that there + is nothing that they would both match, i.e., that we + would have to backtrack because of (as in, e.g., `a*a') + then we can change to pop_failure_jump, because we'll + never have to backtrack. + + This is not true in the case of alternatives: in + `(a|ab)*' we do need to backtrack to the `ab' alternative + (e.g., if the string was `ab'). But instead of trying to + detect that here, the alternative has put on a dummy + failure point which is what we will end up popping. */ + + /* Skip over open/close-group commands. + If what follows this loop is a ...+ construct, + look at what begins its body, since we will have to + match at least one of that. */ + while (1) + { + if (p2 + 2 < pend + && ((re_opcode_t) *p2 == stop_memory + || (re_opcode_t) *p2 == start_memory)) + p2 += 3; + else if (p2 + 6 < pend + && (re_opcode_t) *p2 == dummy_failure_jump) + p2 += 6; + else + break; + } + + p1 = p + mcnt; + /* p1[0] ... p1[2] are the `on_failure_jump' corresponding + to the `maybe_finalize_jump' of this case. Examine what + follows. */ + + /* If we're at the end of the pattern, we can change. */ + if (p2 == pend) + { + /* Consider what happens when matching ":\(.*\)" + against ":/". I don't really understand this code + yet. */ + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 + (" End of pattern: change to `pop_failure_jump'.\n"); + } + + else if ((re_opcode_t) *p2 == exactn + || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) + { + register unsigned char c + = *p2 == (unsigned char) endline ? '\n' : p2[2]; + + if ((re_opcode_t) p1[3] == exactn && p1[5] != c) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + c, p1[5]); + } + + else if ((re_opcode_t) p1[3] == charset + || (re_opcode_t) p1[3] == charset_not) + { + int not = (re_opcode_t) p1[3] == charset_not; + + if (c < (unsigned char) (p1[4] * BYTEWIDTH) + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + /* `not' is equal to 1 if c would match, which means + that we can't change to pop_failure_jump. */ + if (!not) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } + else if ((re_opcode_t) *p2 == charset) + { + register unsigned char c + = *p2 == (unsigned char) endline ? '\n' : p2[2]; + + if ((re_opcode_t) p1[3] == exactn + && ! (p2[1] * BYTEWIDTH > p1[4] + && (p2[1 + p1[4] / BYTEWIDTH] + & (1 << (p1[4] % BYTEWIDTH))))) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + c, p1[5]); + } + + else if ((re_opcode_t) p1[3] == charset_not) + { + int idx; + /* We win if the charset_not inside the loop + lists every character listed in the charset after. */ + for (idx = 0; idx < p2[1]; idx++) + if (! (p2[2 + idx] == 0 + || (idx < p1[4] + && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) + break; + + if (idx == p2[1]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + else if ((re_opcode_t) p1[3] == charset) + { + int idx; + /* We win if the charset inside the loop + has no overlap with the one after the loop. */ + for (idx = 0; idx < p2[1] && idx < p1[4]; idx++) + if ((p2[2 + idx] & p1[5 + idx]) != 0) + break; + + if (idx == p2[1] || idx == p1[4]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } + } + p -= 2; /* Point at relative address again. */ + if ((re_opcode_t) p[-1] != pop_failure_jump) + { + p[-1] = (unsigned char) jump; + DEBUG_PRINT1 (" Match => jump.\n"); + goto unconditional_jump; + } + /* Note fall through. */ + + + /* The end of a simple repeat has a pop_failure_jump back to + its matching on_failure_jump, where the latter will push a + failure point. The pop_failure_jump takes off failure + points put on by this pop_failure_jump's matching + on_failure_jump; we got through the pattern to here from the + matching on_failure_jump, so didn't fail. */ + case pop_failure_jump: + { + /* We need to pass separate storage for the lowest and + highest registers, even though we don't care about the + actual values. Otherwise, we will restore only one + register from the stack, since lowest will == highest in + `pop_failure_point'. */ + unsigned dummy_low_reg, dummy_high_reg; + unsigned char *pdummy; + const char *sdummy; + + DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); + POP_FAILURE_POINT (sdummy, pdummy, + dummy_low_reg, dummy_high_reg, + reg_dummy, reg_dummy, reg_info_dummy); + } + /* Note fall through. */ + + + /* Unconditionally jump (without popping any failure points). */ + case jump: + unconditional_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ + DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); + p += mcnt; /* Do the jump. */ + DEBUG_PRINT2 ("(to 0x%x).\n", p); + break; + + + /* We need this opcode so we can detect where alternatives end + in `group_match_null_string_p' et al. */ + case jump_past_alt: + DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); + goto unconditional_jump; + + + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at pop_failure_jump. We will end up at + pop_failure_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for pop_failure_jump to pop. */ + case dummy_failure_jump: + DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); + /* It doesn't matter what we push for the string here. What + the code at `fail' tests is the value for the pattern. */ + PUSH_FAILURE_POINT (0, 0, -2); + goto unconditional_jump; + + + /* At the end of an alternative, we need to push a dummy failure + point in case we are followed by a `pop_failure_jump', because + we don't want the failure point for the alternative to be + popped. For example, matching `(a|ab)*' against `aab' + requires that we match the `ab' alternative. */ + case push_dummy_failure: + DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); + /* See comments just above at `dummy_failure_jump' about the + two zeroes. */ + PUSH_FAILURE_POINT (0, 0, -2); + break; + + /* Have to succeed matching what follows at least n times. + After that, handle like `on_failure_jump'. */ + case succeed_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); + + assert (mcnt >= 0); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt > 0) + { + mcnt--; + p += 2; + STORE_NUMBER_AND_INCR (p, mcnt); + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt); + } + else if (mcnt == 0) + { + DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); + p[2] = (unsigned char) no_op; + p[3] = (unsigned char) no_op; + goto on_failure; + } + break; + + case jump_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); + + /* Originally, this is how many times we CAN jump. */ + if (mcnt) + { + mcnt--; + STORE_NUMBER (p + 2, mcnt); + goto unconditional_jump; + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 4; + break; + + case set_number_at: + { + DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); + STORE_NUMBER (p1, mcnt); + break; + } + + case wordbound: + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + break; + goto fail; + + case notwordbound: + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + goto fail; + break; + + case wordbeg: + DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); + if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) + break; + goto fail; + + case wordend: + DEBUG_PRINT1 ("EXECUTING wordend.\n"); + if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) + && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) + break; + goto fail; + +#ifdef emacs +#ifdef emacs19 + case before_dot: + DEBUG_PRINT1 ("EXECUTING before_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) >= point) + goto fail; + break; + + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) != point) + goto fail; + break; + + case after_dot: + DEBUG_PRINT1 ("EXECUTING after_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) <= point) + goto fail; + break; +#else /* not emacs19 */ + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point) + goto fail; + break; +#endif /* not emacs19 */ + + case syntaxspec: + DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchsyntax; + + case wordchar: + DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); + mcnt = (int) Sword; + matchsyntax: + PREFETCH (); + if (SYNTAX (*d++) != (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + + case notsyntaxspec: + DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchnotsyntax; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); + mcnt = (int) Sword; + matchnotsyntax: + PREFETCH (); + if (SYNTAX (*d++) == (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + +#else /* not emacs */ + case wordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); + PREFETCH (); + if (!WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); + PREFETCH (); + if (WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; +#endif /* not emacs */ + + default: + abort (); + } + continue; /* Successfully executed one pattern command; keep going. */ + + + /* We goto here if a matching operation fails. */ + fail: + if (!FAIL_STACK_EMPTY ()) + { /* A restart point is known. Restore to that state. */ + DEBUG_PRINT1 ("\nFAIL:\n"); + POP_FAILURE_POINT (d, p, + lowest_active_reg, highest_active_reg, + regstart, regend, reg_info); + + /* If this failure point is a dummy, try the next one. */ + if (!p) + goto fail; + + /* If we failed to the end of the pattern, don't examine *p. */ + assert (p <= pend); + if (p < pend) + { + boolean is_a_jump_n = false; + + /* If failed to a backwards jump that's part of a repetition + loop, need to pop this failure point and use the next one. */ + switch ((re_opcode_t) *p) + { + case jump_n: + is_a_jump_n = true; + case maybe_pop_jump: + case pop_failure_jump: + case jump: + p1 = p + 1; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + + if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) + || (!is_a_jump_n + && (re_opcode_t) *p1 == on_failure_jump)) + goto fail; + break; + default: + /* do nothing */ ; + } + } + + if (d >= string1 && d <= end1) + dend = end_match_1; + } + else + break; /* Matching at this starting point really fails. */ + } /* for (;;) */ + + if (best_regs_set) + goto restore_best_regs; + + FREE_VARIABLES (); + + return -1; /* Failure to match. */ +} /* re_match_2 */ + +/* Subroutine definitions for re_match_2. */ + + +/* We are passed P pointing to a register number after a start_memory. + + Return true if the pattern up to the corresponding stop_memory can + match the empty string, and false otherwise. + + If we find the matching stop_memory, sets P to point to one past its number. + Otherwise, sets P to an undefined byte less than or equal to END. + + We don't handle duplicates properly (yet). */ + +static boolean +group_match_null_string_p (p, end, reg_info) + unsigned char **p, *end; + register_info_type *reg_info; +{ + int mcnt; + /* Point to after the args to the start_memory. */ + unsigned char *p1 = *p + 2; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and return true or + false, as appropriate, when we get to one that can't, or to the + matching stop_memory. */ + + switch ((re_opcode_t) *p1) + { + /* Could be either a loop or a series of alternatives. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + /* If the next operation is not a jump backwards in the + pattern. */ + + if (mcnt >= 0) + { + /* Go through the on_failure_jumps of the alternatives, + seeing if any of the alternatives cannot match nothing. + The last alternative starts with only a jump, + whereas the rest start with on_failure_jump and end + with a jump, e.g., here is the pattern for `a|b|c': + + /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 + /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 + /exactn/1/c + + So, we have to first go through the first (n-1) + alternatives and then deal with the last one separately. */ + + + /* Deal with the first (n-1) alternatives, which start + with an on_failure_jump (see above) that jumps to right + past a jump_past_alt. */ + + while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) + { + /* `mcnt' holds how many bytes long the alternative + is, including the ending `jump_past_alt' and + its number. */ + + if (!alt_match_null_string_p (p1, p1 + mcnt - 3, + reg_info)) + return false; + + /* Move to right after this alternative, including the + jump_past_alt. */ + p1 += mcnt; + + /* Break if it's the beginning of an n-th alternative + that doesn't begin with an on_failure_jump. */ + if ((re_opcode_t) *p1 != on_failure_jump) + break; + + /* Still have to check that it's not an n-th + alternative that starts with an on_failure_jump. */ + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) + { + /* Get to the beginning of the n-th alternative. */ + p1 -= 3; + break; + } + } + + /* Deal with the last alternative: go back and get number + of the `jump_past_alt' just before it. `mcnt' contains + the length of the alternative. */ + EXTRACT_NUMBER (mcnt, p1 - 2); + + if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) + return false; + + p1 += mcnt; /* Get past the n-th alternative. */ + } /* if mcnt > 0 */ + break; + + + case stop_memory: + assert (p1[1] == **p); + *p = p1 + 2; + return true; + + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return false; +} /* group_match_null_string_p */ + + +/* Similar to group_match_null_string_p, but doesn't deal with alternatives: + It expects P to be the first byte of a single alternative and END one + byte past the last. The alternative can contain groups. */ + +static boolean +alt_match_null_string_p (p, end, reg_info) + unsigned char *p, *end; + register_info_type *reg_info; +{ + int mcnt; + unsigned char *p1 = p; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and break when we get + to one that can't. */ + + switch ((re_opcode_t) *p1) + { + /* It's a loop. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + break; + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return true; +} /* alt_match_null_string_p */ + + +/* Deals with the ops common to group_match_null_string_p and + alt_match_null_string_p. + + Sets P to one after the op and its arguments, if any. */ + +static boolean +common_op_match_null_string_p (p, end, reg_info) + unsigned char **p, *end; + register_info_type *reg_info; +{ + int mcnt; + boolean ret; + int reg_no; + unsigned char *p1 = *p; + + switch ((re_opcode_t) *p1++) + { + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbeg: + case wordend: + case wordbound: + case notwordbound: +#ifdef emacs + case before_dot: + case at_dot: + case after_dot: +#endif + break; + + case start_memory: + reg_no = *p1; + assert (reg_no > 0 && reg_no <= MAX_REGNUM); + ret = group_match_null_string_p (&p1, end, reg_info); + + /* Have to set this here in case we're checking a group which + contains a group and a back reference to it. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; + + if (!ret) + return false; + break; + + /* If this is an optimized succeed_n for zero times, make the jump. */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (mcnt >= 0) + p1 += mcnt; + else + return false; + break; + + case succeed_n: + /* Get to the number of times to succeed. */ + p1 += 2; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + if (mcnt == 0) + { + p1 -= 4; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + } + else + return false; + break; + + case duplicate: + if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) + return false; + break; + + case set_number_at: + p1 += 4; + + default: + /* All other opcodes mean we cannot match the empty string. */ + return false; + } + + *p = p1; + return true; +} /* common_op_match_null_string_p */ + + +/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN + bytes; nonzero otherwise. */ + +static int +bcmp_translate (s1, s2, len, translate) + unsigned char *s1, *s2; + register int len; + char *translate; +{ + register unsigned char *p1 = s1, *p2 = s2; + while (len) + { + if (translate[*p1++] != translate[*p2++]) return 1; + len--; + } + return 0; +} + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length SIZE) and puts the result in BUFP. + Returns 0 if the pattern was valid, otherwise an error string. + + Assumes the `allocated' (and perhaps `buffer') and `translate' fields + are set in BUFP on entry. + + We call regex_compile to do the actual compilation. */ + +const char * +re_compile_pattern (pattern, length, bufp) + const char *pattern; + int length; + struct re_pattern_buffer *bufp; +{ + reg_errcode_t ret; + + /* GNU code is written to assume at least RE_NREGS registers will be set + (and at least one extra will be -1). */ + bufp->regs_allocated = REGS_UNALLOCATED; + + /* And GNU code determines whether or not to get register information + by passing null for the REGS argument to re_match, etc., not by + setting no_sub. */ + bufp->no_sub = 0; + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + + ret = regex_compile (pattern, length, re_syntax_options, bufp); + + return re_error_msg[(int) ret]; +} + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them if this is an Emacs or POSIX compilation. */ + +#if !defined (emacs) && !defined (_POSIX_SOURCE) + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer re_comp_buf; + +char * +re_comp (s) + const char *s; +{ + reg_errcode_t ret; + + if (!s) + { + if (!re_comp_buf.buffer) + return "No previous regular expression"; + return 0; + } + + if (!re_comp_buf.buffer) + { + re_comp_buf.buffer = (unsigned char *) malloc (200); + if (re_comp_buf.buffer == NULL) + return "Memory exhausted"; + re_comp_buf.allocated = 200; + + re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); + if (re_comp_buf.fastmap == NULL) + return "Memory exhausted"; + } + + /* Since `re_exec' always passes NULL for the `regs' argument, we + don't need to initialize the pattern buffer fields which affect it. */ + + /* Match anchors at newlines. */ + re_comp_buf.newline_anchor = 1; + + ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + + /* Yes, we're discarding `const' here. */ + return (char *) re_error_msg[(int) ret]; +} + + +int +re_exec (s) + const char *s; +{ + const int len = strlen (s); + return + 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); +} +#endif /* not emacs and not _POSIX_SOURCE */ + +/* POSIX.2 functions. Don't define these for Emacs. */ + +#ifndef emacs + +/* regcomp takes a regular expression as a string and compiles it. + + PREG is a regex_t *. We do not expect any fields to be initialized, + since POSIX says we shouldn't. Thus, we set + + `buffer' to the compiled pattern; + `used' to the length of the compiled pattern; + `syntax' to RE_SYNTAX_POSIX_EXTENDED if the + REG_EXTENDED bit in CFLAGS is set; otherwise, to + RE_SYNTAX_POSIX_BASIC; + `newline_anchor' to REG_NEWLINE being set in CFLAGS; + `fastmap' and `fastmap_accurate' to zero; + `re_nsub' to the number of subexpressions in PATTERN. + + PATTERN is the address of the pattern string. + + CFLAGS is a series of bits which affect compilation. + + If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we + use POSIX basic syntax. + + If REG_NEWLINE is set, then . and [^...] don't match newline. + Also, regexec will try a match beginning after every newline. + + If REG_ICASE is set, then we considers upper- and lowercase + versions of letters to be equivalent when matching. + + If REG_NOSUB is set, then when PREG is passed to regexec, that + routine will report only success or failure, and nothing about the + registers. + + It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for + the return codes and their meanings.) */ + +int +regcomp (preg, pattern, cflags) + regex_t *preg; + const char *pattern; + int cflags; +{ + reg_errcode_t ret; + unsigned syntax + = (cflags & REG_EXTENDED) ? + RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; + + /* regex_compile will allocate the space for the compiled pattern. */ + preg->buffer = 0; + preg->allocated = 0; + preg->used = 0; + + /* Don't bother to use a fastmap when searching. This simplifies the + REG_NEWLINE case: if we used a fastmap, we'd have to put all the + characters after newlines into the fastmap. This way, we just try + every character. */ + preg->fastmap = 0; + + if (cflags & REG_ICASE) + { + unsigned i; + + preg->translate = (char *) malloc (CHAR_SET_SIZE); + if (preg->translate == NULL) + return (int) REG_ESPACE; + + /* Map uppercase characters to corresponding lowercase ones. */ + for (i = 0; i < CHAR_SET_SIZE; i++) + preg->translate[i] = ISUPPER (i) ? tolower (i) : i; + } + else + preg->translate = NULL; + + /* If REG_NEWLINE is set, newlines are treated differently. */ + if (cflags & REG_NEWLINE) + { /* REG_NEWLINE implies neither . nor [^...] match newline. */ + syntax &= ~RE_DOT_NEWLINE; + syntax |= RE_HAT_LISTS_NOT_NEWLINE; + /* It also changes the matching behavior. */ + preg->newline_anchor = 1; + } + else + preg->newline_anchor = 0; + + preg->no_sub = !!(cflags & REG_NOSUB); + + /* POSIX says a null character in the pattern terminates it, so we + can use strlen here in compiling the pattern. */ + ret = regex_compile (pattern, strlen (pattern), syntax, preg); + + /* POSIX doesn't distinguish between an unmatched open-group and an + unmatched close-group: both are REG_EPAREN. */ + if (ret == REG_ERPAREN) ret = REG_EPAREN; + + return (int) ret; +} + + +/* regexec searches for a given pattern, specified by PREG, in the + string STRING. + + If NMATCH is zero or REG_NOSUB was set in the cflags argument to + `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at + least NMATCH elements, and we set them to the offsets of the + corresponding matched substrings. + + EFLAGS specifies `execution flags' which affect matching: if + REG_NOTBOL is set, then ^ does not match at the beginning of the + string; if REG_NOTEOL is set, then $ does not match at the end. + + We return 0 if we find a match and REG_NOMATCH if not. */ + +int +regexec (preg, string, nmatch, pmatch, eflags) + const regex_t *preg; + const char *string; + size_t nmatch; + regmatch_t pmatch[]; + int eflags; +{ + int ret; + struct re_registers regs; + regex_t private_preg; + int len = strlen (string); + boolean want_reg_info = !preg->no_sub && nmatch > 0; + + private_preg = *preg; + + private_preg.not_bol = !!(eflags & REG_NOTBOL); + private_preg.not_eol = !!(eflags & REG_NOTEOL); + + /* The user has told us exactly how many registers to return + information about, via `nmatch'. We have to pass that on to the + matching routines. */ + private_preg.regs_allocated = REGS_FIXED; + + if (want_reg_info) + { + regs.num_regs = nmatch; + regs.start = TALLOC (nmatch, regoff_t); + regs.end = TALLOC (nmatch, regoff_t); + if (regs.start == NULL || regs.end == NULL) + return (int) REG_NOMATCH; + } + + /* Perform the searching operation. */ + ret = re_search (&private_preg, string, len, + /* start: */ 0, /* range: */ len, + want_reg_info ? ®s : (struct re_registers *) 0); + + /* Copy the register information to the POSIX structure. */ + if (want_reg_info) + { + if (ret >= 0) + { + unsigned r; + + for (r = 0; r < nmatch; r++) + { + pmatch[r].rm_so = regs.start[r]; + pmatch[r].rm_eo = regs.end[r]; + } + } + + /* If we needed the temporary register info, free the space now. */ + free (regs.start); + free (regs.end); + } + + /* We want zero return to mean success, unlike `re_search'. */ + return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; +} + + +/* Returns a message corresponding to an error code, ERRCODE, returned + from either regcomp or regexec. We don't use PREG here. */ + +size_t +regerror (errcode, preg, errbuf, errbuf_size) + int errcode; + const regex_t *preg; + char *errbuf; + size_t errbuf_size; +{ + const char *msg; + size_t msg_size; + + if (errcode < 0 + || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0]))) + /* Only error codes returned by the rest of the code should be passed + to this routine. If we are given anything else, or if other regex + code generates an invalid error code, then the program has a bug. + Dump core so we can fix it. */ + abort (); + + msg = re_error_msg[errcode]; + + /* POSIX doesn't require that we do anything in this case, but why + not be nice. */ + if (! msg) + msg = "Success"; + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (errbuf_size != 0) + { + if (msg_size > errbuf_size) + { + strncpy (errbuf, msg, errbuf_size - 1); + errbuf[errbuf_size - 1] = 0; + } + else + strcpy (errbuf, msg); + } + + return msg_size; +} + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (preg) + regex_t *preg; +{ + if (preg->buffer != NULL) + free (preg->buffer); + preg->buffer = NULL; + + preg->allocated = 0; + preg->used = 0; + + if (preg->fastmap != NULL) + free (preg->fastmap); + preg->fastmap = NULL; + preg->fastmap_accurate = 0; + + if (preg->translate != NULL) + free (preg->translate); + preg->translate = NULL; +} + +#endif /* not emacs */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/lib/gnu_lib/regex.h b/lib/gnu_lib/regex.h new file mode 100644 index 0000000..a495005 --- /dev/null +++ b/lib/gnu_lib/regex.h @@ -0,0 +1,490 @@ +/* Definitions for data structures and routines for the regular + expression library, version 0.12. + + Copyright (C) 1985, 89, 90, 91, 92, 1993 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 2, 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef __REGEXP_LIBRARY_H__ +#define __REGEXP_LIBRARY_H__ + +/* POSIX says that must be included (by the caller) before + . */ + +#ifdef VMS +/* VMS doesn't have `size_t' in , even though POSIX says it + should be there. */ +#include +#endif + + +/* The following bits are used to determine the regexp syntax we + recognize. The set/not-set meanings are chosen so that Emacs syntax + remains the value 0. The bits are given in alphabetical order, and + the definitions shifted by one from the previous bit; thus, when we + add or remove a bit, only one other definition need change. */ +typedef unsigned reg_syntax_t; + +/* If this bit is not set, then \ inside a bracket expression is literal. + If set, then such a \ quotes the following character. */ +#define RE_BACKSLASH_ESCAPE_IN_LISTS (1) + +/* If this bit is not set, then + and ? are operators, and \+ and \? are + literals. + If set, then \+ and \? are operators and + and ? are literals. */ +#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) + +/* If this bit is set, then character classes are supported. They are: + [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], + [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. + If not set, then character classes are not supported. */ +#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) + +/* If this bit is set, then ^ and $ are always anchors (outside bracket + expressions, of course). + If this bit is not set, then it depends: + ^ is an anchor if it is at the beginning of a regular + expression or after an open-group or an alternation operator; + $ is an anchor if it is at the end of a regular expression, or + before a close-group or an alternation operator. + + This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because + POSIX draft 11.2 says that * etc. in leading positions is undefined. + We already implemented a previous draft which made those constructs + invalid, though, so we haven't changed the code back. */ +#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) + +/* If this bit is set, then special characters are always special + regardless of where they are in the pattern. + If this bit is not set, then special characters are special only in + some contexts; otherwise they are ordinary. Specifically, + * + ? and intervals are only special when not after the beginning, + open-group, or alternation operator. */ +#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) + +/* If this bit is set, then *, +, ?, and { cannot be first in an re or + immediately after an alternation or begin-group operator. */ +#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) + +/* If this bit is set, then . matches newline. + If not set, then it doesn't. */ +#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) + +/* If this bit is set, then . doesn't match NUL. + If not set, then it does. */ +#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) + +/* If this bit is set, nonmatching lists [^...] do not match newline. + If not set, they do. */ +#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) + +/* If this bit is set, either \{...\} or {...} defines an + interval, depending on RE_NO_BK_BRACES. + If not set, \{, \}, {, and } are literals. */ +#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) + +/* If this bit is set, +, ? and | aren't recognized as operators. + If not set, they are. */ +#define RE_LIMITED_OPS (RE_INTERVALS << 1) + +/* If this bit is set, newline is an alternation operator. + If not set, newline is literal. */ +#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) + +/* If this bit is set, then `{...}' defines an interval, and \{ and \} + are literals. + If not set, then `\{...\}' defines an interval. */ +#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) + +/* If this bit is set, (...) defines a group, and \( and \) are literals. + If not set, \(...\) defines a group, and ( and ) are literals. */ +#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) + +/* If this bit is set, then \ matches . + If not set, then \ is a back-reference. */ +#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) + +/* If this bit is set, then | is an alternation operator, and \| is literal. + If not set, then \| is an alternation operator, and | is literal. */ +#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) + +/* If this bit is set, then an ending range point collating higher + than the starting range point, as in [z-a], is invalid. + If not set, then when ending range point collates higher than the + starting range point, the range is ignored. */ +#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) + +/* If this bit is set, then an unmatched ) is ordinary. + If not set, then an unmatched ) is invalid. */ +#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) + +/* This global variable defines the particular regexp syntax to use (for + some interfaces). When a regexp is compiled, the syntax used is + stored in the pattern buffer, so changing this does not affect + already-compiled regexps. */ +extern reg_syntax_t re_syntax_options; + +/* Define combinations of the above bits for the standard possibilities. + (The [[[ comments delimit what gets put into the Texinfo file, so + don't delete them!) */ +/* [[[begin syntaxes]]] */ +#define RE_SYNTAX_EMACS 0 + +#define RE_SYNTAX_AWK \ + (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ + | RE_UNMATCHED_RIGHT_PAREN_ORD) + +#define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS) + +#define RE_SYNTAX_GREP \ + (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ + | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ + | RE_NEWLINE_ALT) + +#define RE_SYNTAX_EGREP \ + (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ + | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ + | RE_NO_BK_VBAR) + +#define RE_SYNTAX_POSIX_EGREP \ + (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES) + +/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ +#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC + +#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC + +/* Syntax bits common to both basic and extended POSIX regex syntax. */ +#define _RE_SYNTAX_POSIX_COMMON \ + (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ + | RE_INTERVALS | RE_NO_EMPTY_RANGES) + +#define RE_SYNTAX_POSIX_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) + +/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes + RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this + isn't minimal, since other operators, such as \`, aren't disabled. */ +#define RE_SYNTAX_POSIX_MINIMAL_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) + +#define RE_SYNTAX_POSIX_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS + replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */ +#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) +/* [[[end syntaxes]]] */ + +/* Maximum number of duplicates an interval can allow. Some systems + (erroneously) define this in other header files, but we want our + value, so remove any previous define. */ +#ifdef RE_DUP_MAX +#undef RE_DUP_MAX +#endif +#define RE_DUP_MAX ((1 << 15) - 1) + + +/* POSIX `cflags' bits (i.e., information for `regcomp'). */ + +/* If this bit is set, then use extended regular expression syntax. + If not set, then use basic regular expression syntax. */ +#define REG_EXTENDED 1 + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define REG_ICASE (REG_EXTENDED << 1) + +/* If this bit is set, then anchors do not match at newline + characters in the string. + If not set, then anchors do match at newlines. */ +#define REG_NEWLINE (REG_ICASE << 1) + +/* If this bit is set, then report only success or fail in regexec. + If not set, then returns differ between not matching and errors. */ +#define REG_NOSUB (REG_NEWLINE << 1) + + +/* POSIX `eflags' bits (i.e., information for regexec). */ + +/* If this bit is set, then the beginning-of-line operator doesn't match + the beginning of the string (presumably because it's not the + beginning of a line). + If not set, then the beginning-of-line operator does match the + beginning of the string. */ +#define REG_NOTBOL 1 + +/* Like REG_NOTBOL, except for the end-of-line. */ +#define REG_NOTEOL (1 << 1) + + +/* If any error codes are removed, changed, or added, update the + `re_error_msg' table in regex.c. */ +typedef enum +{ + REG_NOERROR = 0, /* Success. */ + REG_NOMATCH, /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ + REG_BADPAT, /* Invalid pattern. */ + REG_ECOLLATE, /* Not implemented. */ + REG_ECTYPE, /* Invalid character class name. */ + REG_EESCAPE, /* Trailing backslash. */ + REG_ESUBREG, /* Invalid back reference. */ + REG_EBRACK, /* Unmatched left bracket. */ + REG_EPAREN, /* Parenthesis imbalance. */ + REG_EBRACE, /* Unmatched \{. */ + REG_BADBR, /* Invalid contents of \{\}. */ + REG_ERANGE, /* Invalid range end. */ + REG_ESPACE, /* Ran out of memory. */ + REG_BADRPT, /* No preceding re for repetition op. */ + + /* Error codes we've added. */ + REG_EEND, /* Premature end. */ + REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ + REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ +} reg_errcode_t; + +/* This data structure represents a compiled pattern. Before calling + the pattern compiler, the fields `buffer', `allocated', `fastmap', + `translate', and `no_sub' can be set. After the pattern has been + compiled, the `re_nsub' field is available. All other fields are + private to the regex routines. */ + +struct re_pattern_buffer +{ +/* [[[begin pattern_buffer]]] */ + /* Space that holds the compiled pattern. It is declared as + `unsigned char *' because its elements are + sometimes used as array indexes. */ + unsigned char *buffer; + + /* Number of bytes to which `buffer' points. */ + unsigned long allocated; + + /* Number of bytes actually used in `buffer'. */ + unsigned long used; + + /* Syntax setting with which the pattern was compiled. */ + reg_syntax_t syntax; + + /* Pointer to a fastmap, if any, otherwise zero. re_search uses + the fastmap, if there is one, to skip over impossible + starting points for matches. */ + char *fastmap; + + /* Either a translate table to apply to all characters before + comparing them, or zero for no translation. The translation + is applied to a pattern when it is compiled and to a string + when it is matched. */ + char *translate; + + /* Number of subexpressions found by the compiler. */ + size_t re_nsub; + + /* Zero if this pattern cannot match the empty string, one else. + Well, in truth it's used only in `re_search_2', to see + whether or not we should use the fastmap, so we don't set + this absolutely perfectly; see `re_compile_fastmap' (the + `duplicate' case). */ + unsigned can_be_null : 1; + + /* If REGS_UNALLOCATED, allocate space in the `regs' structure + for `max (RE_NREGS, re_nsub + 1)' groups. + If REGS_REALLOCATE, reallocate space if necessary. + If REGS_FIXED, use what's there. */ +#define REGS_UNALLOCATED 0 +#define REGS_REALLOCATE 1 +#define REGS_FIXED 2 + unsigned regs_allocated : 2; + + /* Set to zero when `regex_compile' compiles a pattern; set to one + by `re_compile_fastmap' if it updates the fastmap. */ + unsigned fastmap_accurate : 1; + + /* If set, `re_match_2' does not return information about + subexpressions. */ + unsigned no_sub : 1; + + /* If set, a beginning-of-line anchor doesn't match at the + beginning of the string. */ + unsigned not_bol : 1; + + /* Similarly for an end-of-line anchor. */ + unsigned not_eol : 1; + + /* If true, an anchor at a newline matches. */ + unsigned newline_anchor : 1; + +/* [[[end pattern_buffer]]] */ +}; + +typedef struct re_pattern_buffer regex_t; + + +/* search.c (search_buffer) in Emacs needs this one opcode value. It is + defined both in `regex.c' and here. */ +#define RE_EXACTN_VALUE 1 + +/* Type for byte offsets within the string. POSIX mandates this. */ +typedef int regoff_t; + + +/* This is the structure we store register match data in. See + regex.texinfo for a full description of what registers match. */ +struct re_registers +{ + unsigned num_regs; + regoff_t *start; + regoff_t *end; +}; + + +/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, + `re_match_2' returns information about at least this many registers + the first time a `regs' structure is passed. */ +#ifndef RE_NREGS +#define RE_NREGS 30 +#endif + + +/* POSIX specification for registers. Aside from the different names than + `re_registers', POSIX uses an array of structures, instead of a + structure of arrays. */ +typedef struct +{ + regoff_t rm_so; /* Byte offset from string's start to substring's start. */ + regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ +} regmatch_t; + +/* Declarations for routines. */ + +/* To avoid duplicating every routine declaration -- once with a + prototype (if we are ANSI), and once without (if we aren't) -- we + use the following macro to declare argument types. This + unfortunately clutters up the declarations a bit, but I think it's + worth it. */ + +#if __STDC__ + +#define _RE_ARGS(args) args + +#else /* not __STDC__ */ + +#define _RE_ARGS(args) () + +#endif /* not __STDC__ */ + +/* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the `re_syntax_options' variable. */ +extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); + +/* Compile the regular expression PATTERN, with length LENGTH + and syntax given by the global `re_syntax_options', into the buffer + BUFFER. Return NULL if successful, and an error string if not. */ +extern const char *re_compile_pattern + _RE_ARGS ((const char *pattern, int length, + struct re_pattern_buffer *buffer)); + + +/* Compile a fastmap for the compiled pattern in BUFFER; used to + accelerate searches. Return 0 if successful and -2 if was an + internal error. */ +extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); + + +/* Search in the string STRING (with length LENGTH) for the pattern + compiled into BUFFER. Start searching at position START, for RANGE + characters. Return the starting position of the match, -1 for no + match, or -2 for an internal error. Also return register + information in REGS (if REGS and BUFFER->no_sub are nonzero). */ +extern int re_search + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, int range, struct re_registers *regs)); + + +/* Like `re_search', but search in the concatenation of STRING1 and + STRING2. Also, stop searching at index START + STOP. */ +extern int re_search_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, int range, struct re_registers *regs, int stop)); + + +/* Like `re_search', but return how many characters in STRING the regexp + in BUFFER matched, starting at position START. */ +extern int re_match + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, struct re_registers *regs)); + + +/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ +extern int re_match_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, struct re_registers *regs, int stop)); + + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using BUFFER and REGS will use this memory + for recording register information. STARTS and ENDS must be + allocated with malloc, and must each be at least `NUM_REGS * sizeof + (regoff_t)' bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ +extern void re_set_registers + _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, + unsigned num_regs, regoff_t *starts, regoff_t *ends)); + +/* 4.2 bsd compatibility. */ +extern char *re_comp _RE_ARGS ((const char *)); +extern int re_exec _RE_ARGS ((const char *)); + +/* POSIX compatibility. */ +extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags)); +extern int regexec + _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags)); +extern size_t regerror + _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf, + size_t errbuf_size)); +extern void regfree _RE_ARGS ((regex_t *preg)); + +#endif /* not __REGEXP_LIBRARY_H__ */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/lib/lookup.c b/lib/lookup.c new file mode 100644 index 0000000..e2f00dc --- /dev/null +++ b/lib/lookup.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include "eppl_ut.h" +FILE *lookup_file(const char *name,const char *suffix,const char *dir) +/* éÝÅÔ ÆÁÊÌ ÓÎÁÞÁÌÁ × ÔÅËÕÝÅÊ ÄÉÒÅËÔÏÒÉÉ, ÐÏÔÏÍ × ÄÉÒÅËÔÏÒÉÉ + dir × ÔÅËÕÝÅÊ ÄÉÒÅËÔÏÒÉÉ, ÐÏÔÏÍ × /usr/local/lib/fgis/$dir */ +{ char namebuf[1024],pathbuf[1024]; + + struct stat buf; + strcpy(namebuf,name); + if (strlen(name) +#include +#include "epp.h" +int compare_cell_size(EPP *f1,EPP *f2) +{ double xsize1=fabs(f1->XRight-f1->XLeft)/(f1->lc-f1->fc); + double xsize2=fabs(f2->XRight-f2->XLeft)/(f2->lc-f2->fc); + double ysize1=fabs(f1->YTop-f1->YBottom)/(f1->lr-f1->fr); + double ysize2=fabs(f2->YTop-f2->YBottom)/(f2->lr-f2->fr); +/* fprintf(stderr,"Xsize ratio %g X tolerance %g\nYsize ratio %g Y tolerance %g\n", + xsize1/xsize2,1.0/(f1->lc-f1->fc),ysize1/ysize2,1.0/(f1->lr-f1->fr)); +*/ return (fabs(xsize1/xsize2-1.0)<1.0/(f1->lc-f1->fc)&& + fabs(ysize1/ysize2-1.0)<1.0/(f1->lr-f1->fr)); +} +int is_aligned(EPP *f1,EPP *f2) +{ if (!compare_cell_size(f1,f2)) return 0; + return (epp_row(f1,alt_yc(f2,f2->fr))==f2->fr&& + epp_col(f1,alt_xc(f2,f2->fc))==f2->fc); +} +EPP_LINK link_epp(EPP *base,EPP *overlay) +{double x1,y1,x2,y2; + EPP_LINK tmp=malloc(sizeof(LINK_BUFFER)); + if (base->XLeftXRight) + {x1=base->XLeftXLeft?base->XLeft:overlay->XLeft; + x2=base->XRight>overlay->XRight?base->XRight:overlay->XRight; + } + else + {x1=base->XLeft>overlay->XLeft?base->XLeft:overlay->XLeft; + x2=base->XRightXRight?base->XRight:overlay->XRight; + } + if (base->YBottomYTop) + {y1=base->YBottomYBottom?base->YBottom:overlay->YBottom; + y2=base->YTop>overlay->YTop?base->YTop:overlay->YTop; + } + else + {y1=base->YBottom>overlay->YBottom?base->YBottom:overlay->YBottom; + y2=base->YTopYTop?base->YTop:overlay->YTop; + } + tmp->ax=epp_col(overlay,x2)-epp_col(overlay,x1); + tmp->cx=epp_col(base,x2)-epp_col(base,x1); + tmp->bx=epp_col(overlay,x1)*tmp->cx-epp_col(base,x1)*tmp->ax; + tmp->ay=epp_row(overlay,y2)-epp_row(overlay,y1); + tmp->cy=epp_row(base,y2)-epp_row(base,y1); + tmp->by=epp_row(overlay,y1)*tmp->cy-epp_row(base,y1)*tmp->ay; + return tmp; +} +int linked_row(EPP_LINK link,int row) +{ return (link->ay*row+link->by)/link->cy; +} +int linked_col(EPP_LINK link,int col) +{ return (link->ax*col+link->bx)/link->cx; +} + + diff --git a/lib/reclass.tab.c b/lib/reclass.tab.c new file mode 100644 index 0000000..13c731f --- /dev/null +++ b/lib/reclass.tab.c @@ -0,0 +1,967 @@ + +/* A Bison parser, made from reclass.y + by GNU Bison version 1.25 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define NUMBER 258 + +#line 1 "reclass.y" + +#include +#include +#include "reclass.h" +#include "epp.h" +#define YYSTYPE int +int yylex(); +int yyerror(); + RECLASS table; + int curval,startval,endval,loop_var; + int maxclass; + int interactive_parser=0; +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 33 +#define YYFLAG -32768 +#define YYNTBASE 10 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 258 ? yytranslate[x] : 18) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, + 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, + 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 6, 7, 10, 12, 14, 17, 24, 26, + 29, 31, 34, 36, 40, 42 +}; + +static const short yyrhs[] = { 11, + 0, 10, 13, 11, 0, 0, 12, 14, 0, 17, + 0, 1, 0, 16, 4, 0, 5, 16, 6, 16, + 7, 4, 0, 8, 0, 9, 8, 0, 15, 0, + 14, 15, 0, 16, 0, 16, 6, 16, 0, 3, + 0, 16, 6, 16, 4, 16, 6, 16, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 17, 19, 22, 23, 24, 25, 31, 32, 34, 35, + 36, 37, 38, 46, 54, 59 +}; +#endif + + +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","NUMBER", +"'='","'('","':'","')'","'\\n'","'\\r'","list","statement","dest","eol","range", +"subrange","value","map_statement", NULL +}; +#endif + +static const short yyr1[] = { 0, + 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, + 14, 14, 15, 15, 16, 17 +}; + +static const short yyr2[] = { 0, + 1, 3, 0, 2, 1, 1, 2, 6, 1, 2, + 1, 2, 1, 3, 1, 7 +}; + +static const short yydefact[] = { 0, + 6, 15, 0, 0, 1, 0, 0, 5, 0, 9, + 0, 0, 4, 11, 13, 7, 0, 0, 10, 2, + 12, 0, 0, 0, 14, 0, 0, 0, 8, 0, + 16, 0, 0 +}; + +static const short yydefgoto[] = { 4, + 5, 6, 12, 13, 14, 7, 8 +}; + +static const short yypact[] = { 4, +-32768,-32768, -2, 8,-32768, -2, 14,-32768, -4,-32768, + 3, 4, -2,-32768, 0,-32768, -2, -2,-32768,-32768, +-32768, -2, 17, 15,-32768, -2, 20, 19,-32768, -2, +-32768, 26,-32768 +}; + +static const short yypgoto[] = {-32768, + 16,-32768,-32768,-32768, 18, -3,-32768 +}; + + +#define YYLAST 31 + + +static const short yytable[] = { 9, + 2, 18, 15, -3, 1, 22, 2, 32, 3, 15, + 19, -3, -3, 23, 24, 10, 11, 16, 25, 17, + 26, 27, 28, 29, 30, 33, 31, 20, 0, 0, + 21 +}; + +static const short yycheck[] = { 3, + 3, 6, 6, 0, 1, 6, 3, 0, 5, 13, + 8, 8, 9, 17, 18, 8, 9, 4, 22, 6, + 4, 7, 26, 4, 6, 0, 30, 12, -1, -1, + 13 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/lib/bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 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 2, 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (to, from, count) + char *to; + char *from; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *to, char *from, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 196 "/usr/lib/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +int +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 6: +#line 25 "reclass.y" +{ if (interactive_parser) + yyerrok; + else + YYABORT; + ; + break;} +case 7: +#line 31 "reclass.y" +{ curval=yyvsp[-1]; ; + break;} +case 8: +#line 32 "reclass.y" +{ curval=-1; startval=yyvsp[-4] ; endval = yyvsp[-2]; + loop_var=startval;; + break;} +case 13: +#line 38 "reclass.y" +{ + if (curval>=0) table[yyvsp[0]]=curval; + else {table[yyvsp[0]]=loop_var++; + if (loop_var>endval) + loop_var=startval; + } + ; + break;} +case 14: +#line 46 "reclass.y" +{ int i; for(i=yyvsp[-2];i<=yyvsp[0];i++) + if (curval>=0) table[i]=curval; + else {table[i]=loop_var++; + if (loop_var>endval) + loop_var=startval; + } + ; + break;} +case 15: +#line 54 "reclass.y" +{if (yyvsp[0]>65535) + { yyerror("Class value out of range\n"); + return 1;YYERROR; + } + ; + break;} +case 16: +#line 59 "reclass.y" +{ + int i,start,stop,startv,stopv; + if (yyvsp[-2]>yyvsp[0]) {start=yyvsp[0];startv=yyvsp[-4];stop=yyvsp[-2];stopv=yyvsp[-6];} + else {start=yyvsp[-2];startv=yyvsp[-6];stop=yyvsp[0];stopv=yyvsp[-4];} + for (i=start;i<=stop;i++) + table[i]=(i-start)*(stopv-startv)/(start-stop)+startv; + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 498 "/usr/lib/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 68 "reclass.y" + +int (*my_getc)(); +int yylex() +{ int c,numb=0,isnumb=0; + static char unget_buf=0; + while ((c=unget_buf?unget_buf:(*my_getc)())!=EOF) + { unget_buf=0; + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': {isnumb=1; numb=numb*10+c-'0'; break;} + case ' ': + case '\t': {if (isnumb) { yylval=numb; return NUMBER; } break;} + default: if (isnumb) { yylval=numb; unget_buf=c; return NUMBER;} + else return c; + } + } + return 0; +} + +int yyerror(char *s) +{ fprintf(stderr,"%s\n",s); + return 0; +} +RECLASS make_reclass_table(EPP *infile,int (*recl_getc)()) +{ int size=epp_table_size(infile); + + return parse_statements(size,create_reclass_table(size),recl_getc); +} +RECLASS parse_statements(int size,RECLASS src,int (*recl_getc)()) +{ my_getc=recl_getc; + table=src; + if (size>65535)size=65535; + maxclass=size; + if (yyparse()) { free(table);return NULL;} + else return table; +} +RECLASS create_reclass_table(size) +{ RECLASS table; + int i; + if (size<=0) return NULL; + else if (size>65535) size=65535; + table=malloc((size+1)*sizeof(short int)); + for(i=0;i<=size;i++) table[i]=i; + return table; +} +RECLASS wrapped_reclass(EPP *infile,int white) +{ int i,maxclass; + RECLASS table; + maxclass=epp_table_size(infile); + table=malloc(maxclass*sizeof(short int)); + table[0]=0; + for(i=1;i<=maxclass;i++) table[i]=(i-1)%(white-1)+1; + table[infile->offsite]=white; + return table; +} diff --git a/lib/reclass.y b/lib/reclass.y new file mode 100644 index 0000000..8bf9b94 --- /dev/null +++ b/lib/reclass.y @@ -0,0 +1,131 @@ +%{ +#include +#include +#include "reclass.h" +#include "epp.h" +#define YYSTYPE int +int yylex(); +int yyerror(); + RECLASS table; + int curval,startval,endval,loop_var; + int maxclass; + int interactive_parser=0; +%} +%expect 2 +%token NUMBER +%% +list: + statement + | list eol statement + ; + +statement: /* empty */ + | dest range + | map_statement + | error { if (interactive_parser) + yyerrok; + else + YYABORT; + } + +dest: value '=' { curval=$1; } + | '(' value ':' value ')' '=' { curval=-1; startval=$2 ; endval = $4; + loop_var=startval;} +eol: '\n' + | '\r' '\n' +range:subrange + |range subrange +subrange:value { + if (curval>=0) table[$1]=curval; + else {table[$1]=loop_var++; + if (loop_var>endval) + loop_var=startval; + } + } + + | value ':' value { int i; for(i=$1;i<=$3;i++) + if (curval>=0) table[i]=curval; + else {table[i]=loop_var++; + if (loop_var>endval) + loop_var=startval; + } + } + ; +value: NUMBER {if ($1>65535) + { yyerror("Class value out of range\n"); + return 1;YYERROR; + } + } +map_statement: value ':' value '=' value ':' value { + int i,start,stop,startv,stopv; + if ($5>$7) {start=$7;startv=$3;stop=$5;stopv=$1;} + else {start=$5;startv=$1;stop=$7;stopv=$3;} + for (i=start;i<=stop;i++) + table[i]=(i-start)*(stopv-startv)/(start-stop)+startv; + } +; + +%% +int (*my_getc)(); +int yylex() +{ int c,numb=0,isnumb=0; + static char unget_buf=0; + while ((c=unget_buf?unget_buf:(*my_getc)())!=EOF) + { unget_buf=0; + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': {isnumb=1; numb=numb*10+c-'0'; break;} + case ' ': + case '\t': {if (isnumb) { yylval=numb; return NUMBER; } break;} + default: if (isnumb) { yylval=numb; unget_buf=c; return NUMBER;} + else return c; + } + } + return 0; +} + +int yyerror(char *s) +{ fprintf(stderr,"%s\n",s); + return 0; +} +RECLASS make_reclass_table(EPP *infile,int (*recl_getc)()) +{ int size=epp_table_size(infile); + + return parse_statements(size,create_reclass_table(size),recl_getc); +} +RECLASS parse_statements(int size,RECLASS src,int (*recl_getc)()) +{ my_getc=recl_getc; + table=src; + if (size>65535)size=65535; + maxclass=size; + if (yyparse()) { free(table);return NULL;} + else return table; +} +RECLASS create_reclass_table(size) +{ RECLASS table; + int i; + if (size<=0) return NULL; + else if (size>65535) size=65535; + table=malloc((size+1)*sizeof(short int)); + for(i=0;i<=size;i++) table[i]=i; + return table; +} +RECLASS wrapped_reclass(EPP *infile,int white) +{ int i,maxclass; + RECLASS table; + maxclass=epp_table_size(infile); + table=malloc(maxclass*sizeof(short int)); + table[0]=0; + for(i=1;i<=maxclass;i++) table[i]=(i-1)%(white-1)+1; + table[infile->offsite]=white; + return table; +} diff --git a/lib/test/Makefile b/lib/test/Makefile new file mode 100644 index 0000000..ba6b6e6 --- /dev/null +++ b/lib/test/Makefile @@ -0,0 +1,26 @@ +# +# Makefile for test directory +# compilies test programs and performs tests on major functions +# of libepp +# + +# +# which library to link to extended mallock debugging +# +MEM_DEBUG=-lefence +# +# define MEM_DEBUG_LOCATION if your memory debugging library +# lives somewhere in non-standard place +#MEM_DEBUG_LOCATION=/usr/local/lib +# +# We use real compilier flags +# +CFLAGS=-g -O2 -I ../../include +LDFLAGS=-static -L.. ${MEM_DEBUG_LOCATION} +LOADLIBES=-lepp -lm ${MEM_DEBUG} + +test: test_epplib testdata.dat test256.epp run_test.sh + run_test.sh +test_epplib: test_epplib.o ../libepp.a + +test_epplib.o: test_epplib.c diff --git a/lib/test/recltest.c b/lib/test/recltest.c new file mode 100644 index 0000000..5484eae --- /dev/null +++ b/lib/test/recltest.c @@ -0,0 +1,17 @@ +#include +#include +int mygetc() +{ + return getc(stdin); +} +int main(int argc,char **argv) +{ RECLASS src,dest; + int i; + src=create_reclass_table(65536); + dest=parse_statements(65536,src,mygetc); + if (dest) + for (i=0;i<65536;i++) + if (dest[i]!=i) printf("%d reclassed to %d\n",i,dest[i]); + +} + diff --git a/lib/test/test8.epp b/lib/test/test8.epp new file mode 100644 index 0000000000000000000000000000000000000000..fe8f37d5dbe31739bb446152465b857c28a14d45 GIT binary patch literal 640 zcmZQ%NMT?EVhDI(52h6&9nkq4K!Fs7{}5q@5BAJJmI#9!gHk3N2Z(K8sc&GeZ)vUo z1x7|zhCpP@029DLGm0erXOvC(Pd&&e!ttL`B#MeAg51XWKTwW~NHZDbfPRwH`1yao zV-*|68hHi>E?@|)0P?p8vT}gfAh9Pv{ +#include +#include +char filename[1024]; /* name of currently used epp-file */ +FILE *f; /*file with test command. */ +char *error_code[]={"OK","ME_POINT_OUTSIDE","ME_INVALID_MODE", + "ME_READ_ERROR","ME_WRITE_ERROR","ME_INVALID_PUT","ME_OUT_OF_MEMORY", + "ME_ACCESS_DENIED","ME_NO_FILE","ME_INVALID_FILE","ME_CREATE_ERROR",NULL}; +/* prints value of global map_error varable. If it is + related with file-system error, also + prints system error description */ +void print_result() +{ + if (map_error>ME_OUT_OF_MEMORY) { + perror(error_code[map_error]); + } else { + printf("%s\n",error_code[map_error]); + } + map_error=0; +} +/* + * Prints verbosely mode field of EPP structure. + * Note: if it prints something hexadecimal, it should be considered + * error in library! + */ +char *epp_flags[]={"MAP_INPUT","MAP_OUTPUT","MAP_LOADED","MAP_CACHED", + NULL,NULL,NULL,"MAP_MODIFIED", + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, +}; +/* + * Prints verbosely mode field of EPP structure. + * Note: if it prints something hexadecimal, it should be considered + * error in library! + */ +void print_flags(EPP *epp) +{ int i, mask; + char separator=':'; + printf("EPP mode"); + for(i=0,mask=1;i<32;i++,mask<<=1) { + if (epp->mode&mask) { + if (!epp_flags[i]) { + printf("%c 0x%X",separator,mask); + } else { + printf("%c %s",separator,epp_flags[i]); + } + separator=','; + } + } + printf("\n"); +} +/*************************************************************************/ +/* individual test procedures begin here */ +/************************************************************************/ + +/* + * testing epp_put + */ +void test_put(EPP *epp) +{ int row,col,value; + if (!epp) { + fprintf(stderr,"Invalid test case - put before open"); + exit(2); + } + if (fscanf(f,"%d %d %d",&col,&row,&value)!=3) { + fprintf(stderr,"Invalid line in input file\n"); + exit(2); + } + printf("epp_put(%d,%d,%d):",col,row,value); + epp_put(epp, col, row, value); + printf("max=%d,min=%d ",epp->max, epp->min); +} +/* + * testing epp_putline + */ +void test_putline(EPP *epp) +{ int row,col,col2,value; + if (!epp) { + fprintf(stderr,"Invalid test case - putline before open"); + exit(2); + } + if (fscanf(f,"%d %d %d %d",&col,&col2,&row,&value)!=4) { + fprintf(stderr,"Invalid line in input file\n"); + exit(2); + } + printf("epp_putline(%d,%d,%d,%d):",col,col2,row,value); + epp_putline(epp,col,col2,row,value); + printf("max=%d,min=%d ",epp->max, epp->min); +} +/* + * testing epp_get + */ +void test_get(EPP *epp) +{ int row,col; + if (!epp) { + fprintf(stderr,"Invalid test case - get before open"); + exit(2); + } + if (fscanf(f,"%d %d",&row,&col)!=2) { + fprintf(stderr,"Invalid line in input file\n"); + exit(2); + } + printf("epp_get(%d,%d)=%d ",col,row,epp_get(epp,col,row)); +} +/* + * Testing save_epp + * + */ +void test_save(EPP* epp) +{ + if (!epp) { + fprintf(stderr,"Invalid test case - save before load"); + exit(2); + } + printf("Saving %s...",filename); + save_epp(epp); + print_result(); + print_flags(epp); +} +/* + * testing open_epp + * + */ + +EPP *test_read(EPP *epp) +{ + if (epp) close_epp(epp); + if (fscanf(f,"%s",filename)!=1) { + fprintf(stderr,"Missing filename for read command\n"); + exit(2); + } + printf("Opening %s in read-only mode..",filename); + epp=open_epp(filename); + print_result(); + if (!epp) { + printf("File wasn't opened.\n"); + return NULL; + } + printf("%s header information:\n bits per cell:%d\n size:%dx%d\n " + "offsite %d\n values from: %d to %d\n ",filename,epp->kind, + epp->lc-epp->fc,epp->lr-epp->fr,epp->offsite,epp->min,epp->max); + print_flags(epp); + return epp; +} +/* + * + * testing load_epp + * + */ +EPP *test_load(EPP *epp) +{ + if (epp) close_epp(epp); + if (fscanf(f,"%s",filename)!=1) { + fprintf(stderr,"Missing filename for load command\n"); + exit(2); + } + printf("Loading %s...",filename); + epp=load_epp(filename); + print_result(); + if (!epp) { + printf("File wasn't loaded.\n"); + return NULL; + } + printf("%s header information:\n bits per cell:%d\n size:%dx%d\n " + "offsite %d\n values from: %d to %d\n ",filename,epp->kind, + epp->lc-epp->fc,epp->lr-epp->fr,epp->offsite,epp->min,epp->max); + print_flags(epp); + return epp; +} +/* + * + * Test reset. Performs reset operation + * + */ +void test_reset(EPP *epp) +{ + if (!epp) { + fprintf(stderr,"Invalid test case - reset before read"); + exit(2); + } + printf("Resetting file.\n Current line was %d\n Flags was:", + epp->currentline); + print_flags(epp); + + reset_epp(epp); + print_result(); + printf("Current line now is:%d\n",epp->currentline); + printf("%s header information:\n bits per cell:%d\n size:%dx%d\n " + "offsite %d\n values from: %d to %d\n ",filename,epp->kind, + epp->lc-epp->fc,epp->lr-epp->fr,epp->offsite,epp->min,epp->max); + print_flags(epp); +} +/* + * testing creat_epp; + * + */ +EPP *test_create(EPP *epp) +{ int width,height,bits,offsite; + if (epp) close_epp(epp); + if (fscanf(f,"%s %d %d %d %d",filename,&width,&height,&offsite,&bits)!=5) { + fprintf(stderr,"Wrong arguments for create command\n"); + exit(2); + } + Create16bit= (bits!=8); + printf("Creating %d-bit file %s...",Create16bit?16:8,filename); + epp=creat_epp(filename,1,1,width,height,0.5,0.5,width+0.5,height+0.5, + 100,0,offsite); + print_result(); + if (!epp) { + fprintf(stderr,"File is not created\n"); + return NULL; + } + printf("%s header information:\n bits per cell:%d\n size:%dx%d\n " + "offsite %d\n values from: %d to %d\n ",filename,epp->kind, + epp->lc-epp->fc,epp->lr-epp->fr,epp->offsite,epp->min,epp->max); + print_flags(epp); + return epp; +} +int main (int argc, char *argv[]) +{ EPP *epp=NULL; + char command[256]; + if (argc!=2) { + fprintf(stderr,"Usage: test_load test-file"); + exit(2); + } + f=fopen(argv[1],"r"); + if (!f) { + perror(argv[0]); + exit(2); + } + while (!feof(f)) { + /* skip empty lines */ + if (fscanf(f,"%s",command)!=1) { + continue; + } + if (!strcmp(command,"put")) { + test_put(epp); + } else if (!strcmp(command,"get")) { + test_get(epp); + } else if (!strcmp(command,"reset")) { + test_reset(epp); + } else if (!strcmp(command,"save")) { + test_save(epp); + } else if (!strcmp(command,"load")) { + epp=test_load(epp); + } else if (!strcmp(command,"read")) { + epp=test_read(epp); + } else if (!strcmp(command,"create")) { + epp=test_create(epp); + } else if (!strcmp(command,"line")) { + test_putline(epp); + } else if (!strcmp(command,"#")) { + char *newline; + fgets(command,255,f); + newline=strchr(command,'\n'); + if (newline) *newline=0; + printf("*** %s ***\n",command); + continue; + } else { + fprintf(stderr,"Unknown command:%s",command); + continue; + } + print_result(); + } + fclose(f); + if (epp) close_epp(epp); + return 0; +} diff --git a/lib/test/testdata.dat b/lib/test/testdata.dat new file mode 100644 index 0000000..205ff89 --- /dev/null +++ b/lib/test/testdata.dat @@ -0,0 +1,57 @@ +# create test file +create test8.epp 100 100 255 8 +put 1 1 20 +put 100 1 29 +# get shouldn't work here +get 1 10 +put 1 40 20 +# testing if we are allowed to change values above current line +put 10 10 20 +line 10 90 80 30 +# This line should produce error +line 10 90 70 22 +# this too +line 10 90 120 22 +# this line should be drawn partially +line 90 120 85 22 +# this line too +line -20 20 86 23 +# and this wouldn't be drawn at all +line 120 180 87 23 +put 1 100 30 +put 100 100 25 +# resetting file in read mode +reset +put 1 1 10 +get 1 1 +get 100 1 +get 1 100 +get 100 100 +get 1 40 +get 1 30 +load test8.epp +# testing if file is loaded correc +# testing decrease of max when value filled with offsite +put 20 20 40 +get 5 10 +put 20 20 255 +line 10 90 80 255 +# testing if we are allowed to change values above current line +put 10 10 20 +# testing minimum support +put 40 40 1 +put 40 40 20 +put 50 50 3 +put 50 50 255 +# testing decrease of max when value filled with another value +put 10 20 50 +put 10 20 20 +# testing what happens if we are trying to work with point outside file +put 101 8 8 +get 101 8 +# do something else +put 8 8 5 +get 1 1 +get 1 100 +get 100 1 +get 100 100 diff --git a/maketar b/maketar new file mode 100755 index 0000000..2fe5885 --- /dev/null +++ b/maketar @@ -0,0 +1,16 @@ +#!/bin/sh +# @(#) maketar - packs all files, neccessary to bring source distribution +# @(#) of fGIS to another machine +# This stuff should go to toplevel Makefile eventually, when I create one + + +# year omitted, becouse file name should fit in msdos file system +tarname=`date +fgis%m%d.tgz` + +# search directories, where something like core files or object files could +# occur +files=`find lib include dll man -type f \! -name core \! -name '*.o' \! -perm +0111 \! -name '*,v' \! -name '*.a'` +tclfiles=`find tcl -type f \! -name core \! -path "*/RCS/*"` +docfiles=`find doc -type f \! -name "*.bak" \! -path "*/RCS/*" \! -name "*.bak"\ + \! -name "*.dvi" \! -name "*.aux" \! -name "*.i??" \! -name "*.log"` +tar czvf $tarname $files fgis.rc $tclfiles $docfiles colors symbols testdata pkgIndex.tcl maketar TODO Makefile diff --git a/man/border.1 b/man/border.1 new file mode 100644 index 0000000..cea9478 --- /dev/null +++ b/man/border.1 @@ -0,0 +1,60 @@ +.TH BORDER 1 "Version 1.0" "EPU" "EPU user manual" +.SH NAME +border \- plots contour boundaries of raster file into vector file +.SH SYNOPSIS +.B border +[-v] [-m] [-l] [-t +.I value +] [-o +.I output_file +] +.SH DESCRIPTION +Creates a +.B dgt +file with lines which delimit different classes in input +.B epp file. +If +.B -l +option given, puts a label point into each closed polygon. +.PP +Default output filename is constructed from name of input file, by +replacing suffix +.I .epp +by +.I .dgt +\. +.PP +Lines can be created "staircase"-like or smooth. Smoothing is controlled +by +.B tolerance +factor, which defines maximum size of line segment, which can be changed. + +.SH OPTIONS +.TP 8 +.B --help +Display brief usage information and exit successifully. +.TP 8 +.B --version +Display version number and exit successifully. +.TP 8 +.B -%, --verbose +Display progress indication. Useful on large files, but significantly +decreases performans on small ones. +.TP 8 +.B -m, --margins +Controls behavouir on file edges. By default +.B border +treats all areas outside file as +.I offsite, +but when this option given, it assumes that all classes at the file edge +are continued outside it. +.TP 8 +.B -t --tolerance +Defines tolerance value. Default is zero -- no smoothing. +.TP 8 +.B -o --output-file +Allows to specify output file name explicitly. + +.SH BUGS +Label creation is unwritten yet + diff --git a/man/clip.1 b/man/clip.1 new file mode 100644 index 0000000..5b9890d --- /dev/null +++ b/man/clip.1 @@ -0,0 +1,43 @@ +.TH CLIP 1 "Version 1.0" "EPU" "EPU user manual" +.SH NAME +clip \- clips a region from old file using mask file +.SH SYNOPSIS +.B clip +[-%] [-m number] [-o filename] [--help][--version] file mask +.SH DESCRIPTION +Clip creates new file, containing part of old file, which corresponds +to given onsite area or specified class of mask file. +.PP +Cell size of new file would be equial to cell size of mask file. +If cell sizes don't match, ``nearest neighbour'' algorithm would be used +for rescaling. + +.SH OPTIONS +.TP 8 +.B --help +displays brief usage information. +.TP 8 +.B --version +displays version number +.TP 8 +.B -% +Displays percentage of processed lines in file. +.TP 8 +.BI -o " file " --output-file= file +gives the name for output file. Defaults to +.I mosaic.out.epp +.TP 8 +.BI -m " number" --mask-value= number +Clip region which has class +.I number +in the mask file. Otherwise all onsite area of mask file would be clipped. +.SH SEE ALSO +.BR window(1), mosaic(1), eheader (1) + +.SH AUTHOR + +Victor B. Wagner + +.SH BUGS + +Should deal with different cell sizes. diff --git a/man/cluster.1 b/man/cluster.1 new file mode 100644 index 0000000..aed3b48 --- /dev/null +++ b/man/cluster.1 @@ -0,0 +1,71 @@ +.TH CLUSTER 1 "Version 1.0" "Lessa GIS" "Lessa user manual" +.SH NAME +cluster \- fills each contour on raster map with its own color +.SH SYNOPSIS +.B cluster +[-v] [-f] +.I input_file +[-o +.I output_file +] [-c +.I line_color +] [-T +.I temp_dir] +.SH DESCRIPTION +Paints each area in +.B epp +file, surrounded by color +.I line_color +by unique color from 1 to maximal contour number. Can handle up to 65535 contours in file. +.PP +Requires at least three time more space in temporary directore then input file occupies. +.PP +By default assumes that line color is 0 and output file name +.I cluster.out.epp +.PP +Performs two passes on input file and between them prints to stdout information about +number of contours in output file and temporary numbers assigned when calculating +contours. So, redirect standard output, if start cluster in background mode. +.SH OPTIONS +.TP 8 +.B \-v +Verbose mode. Information about current line in processing is printed to stderr. +.TP 8 +.BI \-c " line_color" +\- Set contour separation color to +.I " line_color". +.TP 8 +.BI \-o " output_file" +\- overrides default name of output file. +.TP 8 +.BI \-f " input_file" +\- Equivalent of simple command-line parameter without option prefix. +.TP 8 +.I "-?" " -h" +\- Print brief help message and exit successifully. +.TP 8 +.BI \-T " directory" +\- Uses +.I directory +instead of +.I /tmp +for storing temporary files + +.SH "SEE ALSO" +.BR lessa (1), +.BR mappaint (1), +.BR mapcopy (1), +.BR eheader (1), +.BR epp (5), +.BR dgt (5) + +.SH BUGS +For some unknown reason reports very strange errors (usially page faults) or +produces very strange results, when compilied under DOS. So use unix versions. +.PP +It seems obvouis, that same program must perform +.B rasterize +operation, but this still not implemented. +.SH AUTHOR +Vitus Wagner, +.B SoftWeyr. diff --git a/man/eheader.1 b/man/eheader.1 new file mode 100644 index 0000000..60c05ee --- /dev/null +++ b/man/eheader.1 @@ -0,0 +1,209 @@ +.TH EHEADER 1 "Version 1.0" "Environmental planning utilities" "EPU user manual" +.SH NAME +eheader \- display and modify headers of EPPL7 data files +.SH SYNOPSIS +.B eheader +options files +.PP +.B maplist +files +.PP +.B mapalign +base_file +.B [-v] +files +.SH DESCRIPTION +Applies given editing commands to list of +.B epp +or +.B dgt + files. +.PP +Several commands are applicable to both file types and several +to +.B epp +(raster) files only. +No warning is issued when +.B dgt +file is processed during section when epp\-specific commands used, +becouse several epp\-files can be processed at same time. +.PP +No warning is issued also when no editing commands given, therefore +this utility can be used just for viewing header information. +.PP +When invoked as +.B maplist, +simply dumps headers of given files. +.PP +when invoked as +.B mapalign +performs same operations as with +.B \-A +key, but only other option accepted is +.B -v. +This option may be given as before, as after base file. + + +.SH UNIVERSAL OPTIONS +This commands can be applied to both +.B dgt +(vector) +and +.B epp +(raster) +files. +.TP 8 +.B \-v +\- dumps file header information +.B after +applying any edit options to +.I stdout. + +.TP 8 +.B \-x increment + \- shifts alternative x by +.B increment. +Increment can be any real number, both positive and negative. +.TP 8 +.B \-y increment + \- same with alternative y +.TP 8 +.B \-s factor +\- multiplies all coordinates by factor +.PP +This commands cannot be used together with explicit settings of some +alternative coordinate limit. +.TP 8 +.BR "\-Xl value" " or " "\-XL value" +\- sets alternative x of left border to specified value +.TP 8 +.BR "\-Xr value" " or " "\-XR value" +\- same with right border +.TP 8 +.BR "\-Yb value" " or " "\-YB value" , "\-Yt value" " or " "\-YT" +\- same with bottom and top y +.TP 8 +.B \-p name + \- set projection type to name. Available projection types ( +.B EPPL7 version 3.0 +) are: +.RS +.TP 8 +.B none +\- cause EPPL ver 3 to say "No alternate coordinates" +.TP 8 +.BR utm " or " UTM +\- UTM projection +.TP 8 +.B stplate +\- state plane (projection for US state maps) +.TP 8 +.B ll +\- latitude and longitude (geographic coordinates) +.RE +.SH "EPP SPECIFIC COMMANDS" +Following is applicable to EPP files only: +.TP 8 +.B \-o n + \- set offsite value to n. Value can be in range \-32768 65535. +Negative values are equivalent to 65536\-abs(n). Values above 255, applied +to +.I 8\-bit +data files are silently translated into \-1 (no offsite) +.TP 8 +.B \-fr n +\- set first row to n and updates last row field respectively. +.TP 8 +.B \-fc n + \- set first column to n and updates last column field. +.TP 8 +.B \-A filename +\- align to specified file, i.e updates row/column coordinates +so row and column with same number have same alternative coordinates. +.TP 8 +.B \-a value +\- set cell area to value. +.TP 8 +.B \-c "string" + \- fills description field of the header. String must be single command line +argument, but not nessecary need quotes. +.TP 8 +.B \-u name +\- set area unit type, where unit type may be: +.RS +.TP 8 +.B none +\- cause EPPL ver 3 to say "No alternate coordinates" +.TP 8 +.B ft + \- square feet +.TP 8 +.B m +\- square meters +.TP 8 +.B km + \- square kilometers +.TP 8 +.B mile \- square miles +.TP 8 +.B ha + \- hectares +.TP 8 +.B acre +\- acres +.PP +This command does not perform any recalculation, it just update +unit name field. Use +.B \-a +command for change cell area value respectively. +.RE +.SH "OPTION COMPATIBILYTY" +Some options of +.B eheader +cannot coexist together in same command line. +there are two groups of options with incompatibilities between subgroup +of each group. + +First, options dealing with alternative coordinates. There are options +.B "-Xl -Xr -Yt -Yb," +which set alternative coordinates explicitely, and options +.B "-x -y -s", +which change coordinates by arithmetic calculations. +Explicit and arithmetic changes of coordinates are not allowed simulateneously, +becouse it is to hard to understand, which kind user want to apply first. + +Second, options dealing with row/column coordinates of +.B epp +files. Here there are options +.BR "-A" " and " "-fr -fc" +which performs directly opposite task. +(usially +.B -fr -lr +are used to set first row and column to one, to process file cutted from +large +.epp +file separately +and +.B -A +to change it back to +.BR mosaic (1) +file into larger one. + +.SH "SEE ALSO" +.BR lessa (1), +.BR mappaint (1), +.BR mapcopy (1) +.BR epp (5), +.BR dgt (5) +.SH BUGS +No check is performed by +.B \-fr +and +.B \-lr +command to ensure that row/column values are in valid range. +.PP +.B \-A +command sometimes miscalculates one cell. (but EPPL ver 2.1 does the same). +.SH AUTHOR +Vitus Wagner, +.B SoftWeyr. diff --git a/man/extents.1 b/man/extents.1 new file mode 100644 index 0000000..583916b --- /dev/null +++ b/man/extents.1 @@ -0,0 +1,71 @@ +.TH EXTENTS 1 "Version 1.0" "EPU" "EPU user manual" +.SH NAME +extents \- displays information about class extents in given EPP file. +.SH SYNOPSIS +.B extents +[-%ahlrtbxtA] [-o file] file.epp +.SH DESCRIPTION + +Extents calculates area extents of all classes in given file and +displays it in tabular form. + +This information includes minimal and maximal coordinates and area of +class. +.PP +By default information is printed to +.I stdout. + +It may be given in row/column and alternative coordinates. +.SH OPTIONS +.TP 8 +.B --help +displays brief usage information. +.TP 8 +.B --version +displays version number +.TP 8 +.B -% --verbose +Displays percentage of processed lines in file. +.TP 8 +.BI -o " file " --output-file= file +gives the name for output file, to write results to, instead of standard +output. +.TP 8 +.B -a --alt-coords +display coordinates in alternative system and area in real units, +insted of row/col and cell count. +.TP 8 +.B -h --header +display one-line header above table. +.TP 8 +.B -l --sort-left +sort classes by leftmost coordinate +.TP 8 +.B -r --sort-right +sort classes by rightmost coordinate +.TP 8 +.B -t --sort-top +same for topmost coordinate +.TP 8 +.B -b --sort-bottom +I'm tired with this sort orders +.TP 8 +.B -A --sort-area +Sort classes by count of cells. +.TP 8 +.B -x --sort-x-center +Sort by x-coordinate of center of rectangle, containing all cells of that class. +.B -y --sort-y-center +same, but by y-coordinate + +.SH SEE ALSO +.BR outtable (1) + +.SH AUTHOR + +Victor B. Wagner + +.SH BUGS + +??? + diff --git a/man/fgisRasterColorImage.n b/man/fgisRasterColorImage.n new file mode 100644 index 0000000..0823c20 --- /dev/null +++ b/man/fgisRasterColorImage.n @@ -0,0 +1,94 @@ +.TH palette n 1.0 Fgis "developer Tcl commands" + +.SH NAME +fgisRasterColorImage, fgisRasterBWImage \- render raster object into planchet item + +.SH SYNOPSIS +\fBfgisRasterColorImage\fI raster planchet item\fR ?\fIoption\fR? + +\fBfgisRasterBWImage\fI raster planchet item\fR ?\fIoption\fR? + +.SH DESCRIPTION + +These commands perform visualisation of fGIS raster objects in fGIS planchet +(essentially same as Tk canvas). They work on platform independent manner, +creating visible representation of layer in Tk image object, which should +be previously created. + +User (and even application writer) seldom accesses this commands directly. +Raser layer objects and planchet subcommands should be used to visualize +raster layers. + +These commands controls all attributes of layer appearance, which have no +semantic meaning. I.e. raster file class to palette index correspondence is +part of raster object, becouse it also used for access legend and GIS +operation, while palette itself appear only in call to this command, becouse +it used only to visualisation. + +.SH ARGUMENTS + +.TP 4 +\fIraster\fR - +name of fGIS raster object (see \fBraster\fR(n)). + +.TP 4 +\fIplanchet\fR - +name of fGIS planchet widget. Planchet should be mapped and have coordinate +system already defined. + +.TP 4 +\fIitem\fR - +ID of planchet item to render raster in. It should exist, be of type image +and contain valid image (photo for \fBfgisRasterColorImage\fR and bitmap for +\fBfgisRasterBWImage\fR) in its -image atribute. + +.SH OPTIONS +.TP 4 +\fB-border\fI option\fR - +specifies whether borders between raster object classes or base file classes +(polygon borders) should be drawn. \fIOption\fR can be one of \fBnone\fR, +\fByes\fR, \fBbase\fR. Abbreviations are not allowed (bug?). \fByes\fR means +that borders are drawn only between distinct classes of current raster object, +\fBbase\fR means that borders should be drawn if base file classes are distinct, +even if they are reclassed into same value. Useful for choropleth plots. + +For symbol plots option is ignored. Defaults to \fBnone\fR for color images +and \fByes\fR for BW images. +.TP 4 +\fB-color\fI color\fR +- specifies color to plot borders in color mode or +for entire image in pattern or symbol mode. \fIcolor\fR can be any form +of color specification, acceptable by Tk. Defaults to "black". +.TP 4 +\fB-map\fI option\fR - +specifies how to deal with map classes, which exceed palette or pattern range +(0\-255). Option is one of \fBwrap\fR - use symbol (color) \fIclass%255\fR for +classes which exceeds 255, \fBnone\fR - use symbol (color) 255 for all these +clases and \fInumber\fR - map range 0-\fImax class\fR to range 0-\fInumber\fR. +Defaults to \fBwrap\fR. +.TP 4 +\fB-palette \fIpalettename\fR (color only) - +specifies fGIS palette object to use for coloring of map classes. Defaults +to \fBdefaultpalette\fR. +.TP 4 +\fB-patterns \fIpatternname\fR (BW only) - +sets plotting mode to pattern and specifies pattern set to plot. In pattern +mode patterns are clipped by polygon boundaries, and thus any border modes +are allowed. Defaults to {} (empty pattern). This mode is default for +\fBfgisRasterBWImage\fR +.TP 4 +\fB-symbols \fIpatternname\fR (BW only) - +sets plotting mode to symbol and specifies pattern set to plot. In symbol +mode patterns can be drawn only at whole, so if central point of pattern +belongs to certain class, pattern for this class would be drawn on entire +rectangle. Borders are never plotted in this mode No defaults, becouse this +mode must be turned on explicitely. +.TP 4 +\fB-update \fI{x1 y1 x2 y2}\fR +- Specifies, that only part of image should be replotted. Useful for +raster editing application. Rectangle to update is given in map coordinates. +It is clipped by image boundaries. + +.SH SEE ALSO +.BR raster (n), planchet (n), palette (n), +.BR patterns (n) diff --git a/man/legend.n b/man/legend.n new file mode 100644 index 0000000..6b74d33 --- /dev/null +++ b/man/legend.n @@ -0,0 +1,85 @@ +.TH legend n 1.0 EPTcl "Environmental Planning Tcl extensions" +.SH NAME +legend \- Create and manipulate EPTcl legends + +.SH SYNOPSIS +\fBlegend read\fI filename\fR options + +\fBlegend parse\fI string\fR + +\fBlegend set\fI list\fR + +.SH DESCRIPTION + +\fBlegend\fR creates legend object, which is used to store and manipulate +descriptive information about maps. There are three ways to create legend: +.TP 4 +from file, which shoild be an EPPL7 legend file +.TP 4 +from string, which should hold content of such file +.TP 4 +from Tcl list, simular to one, used for \fBarray set\fR command +.PP +\fBlegend\fR command returns handle for legend which is unique identifier, +used for subsequent references for this legend. It creates new Tcl command +with name of this identifier, that used to manipulate legend. +.PP +Actually, legend object is combination of global array and Tcl procedure, +and legend handle is simply name of both of them. + +.SH OPTIONS +.TP 4 +\fBlegend read\fI filename\fR +Opens and reads text file in EPPL7 format. Each line of this file contain +number and descriptive text, separated by two spaces (originally, there should +be some information concering printing map on line printer (not graphical one) +between this spaces, but this format is no longer used and supported. +Numbers between 0 and 65535 are considered map classes and numbers -2 and -1 +have special meaning - they are considered legend title and subtitle respecitvely. There can be several lines with same classes in legend. They are concatenated. +Note that EPTcl never uses this line separations as line breaks when outputting +legend (may be this should go to BUGS section) +.TP 4 +\fBlegend parse\fI string\fR +Produces legend from string which should be identical to content of EPPL7 +legend file. +.TP 4 +\fBlegend set\fI list\fR +Produces legend from Tcl list. Such list can be obtained by \fBarray get +\fIlegendname\fR command. Differ from \fBarray set\fR in that finds correct +name for legend and defines object command for it. Can be used to create +empty legend for subsequentual filling by \fIlegendname \fBset\fR subcommand. +In this case empty list should be specified. + +.SH OBJECT COMMAND +.TP 4 +\fIlegendName\fB classes\fR +Return sorted list of classes defined in legend +.TP 4 +\fIlegendName\fB delete\fR +Destructor of object. Unsets all data and destroys object command. +.TP 4 +\fIlegendName\fB drawable\fI ?boolean? +if boolean specified, set legend drawmode and return nothing. +Otherwise returns 0 or 1, depending of current settings. +Drawmode controls if legend could be displayed in legend box. +.TP 4 +\fIlegendName\fB get \fI class\fR +Returns value of given class or string "Not defined",such class is not defined. +String could be changed by changing value of element \fBudefined_legend\fR of +global array \fBfgis\fR +.TP 4 +\fIlegendName\fB print\fI +Returns content of legend in form of EPPL7 legend format as string. +.TP 4 +\fIlegendName\fB set \fIclass value\fR +Changes description of given class +.TP 4 +\fIlegendName\fB subtitle\fR ?\fIstring\fR? +If no \fIstring\fR specified, returns current legend subtitle. Otherwise +replaces subtitle by given string +.TP 4 +\fIlegendName\fB title\fR ?\fIstring\fR? +If no \fIstring\fR specified, returns current legend title. Otherwise +replaces title by given string +.SH BUGS +None noticed diff --git a/man/mosaic.1 b/man/mosaic.1 new file mode 100644 index 0000000..fa626e8 --- /dev/null +++ b/man/mosaic.1 @@ -0,0 +1,62 @@ +.TH MOSAIC 1 "Version 1.0" "EPU" "EPU user manual" +.SH NAME +mosaic \- merges several epp files together +.SH SYNOPSIS +.B mosaic +[-%RA] [-O number] [-o filename] [--help][--version]files +.SH DESCRIPTION +Mosaic merges several +.IR epp -files +into one. If some cell has non-offsite value in several files, +value from last files would be used. +.PP +Cell sizes of all old files must be equial. Usially +.B mosaic +deals with properly aligned files, but it can deal with misaligned files, +taking into account row/column or alternative coordinates regarding to +command-line options. +.PP +If +.I offsite +value is not explicitely given in command line, it defaults to +offsite of first (base) file if it is not used as data class in one +of overlay files. In last case offsite would be set to 255 for 8-bit and +to 65535 to 16-bit files. +.SH OPTIONS + +.SH OPTIONS +.TP 8 +.B --help +displays brief usage information. +.TP 8 +.B --version +displays version number +.TP 8 +.B -% +Displays percentage of processed lines in file. +.TP 8 +.BI -o " file " --output-file= file +gives the name for output file. Defaults to +.I mosaic.out.epp +.TP 8 +.B -A --force-alt +Do not complain, if files are misaligned. Use alternate coordinates to +reference them. +.TP 8 +.B -R --force-row +Same, but use row/col cordinates. + +.TP 8 +.BI -O " value " --offsite= value +specifies offsite value of new file. + +.SH SEE ALSO +.BR eheader (1), window (1) + +.SH AUTHOR + +Victor B. Wagner + +.SH BUGS + +??? diff --git a/man/neighbours.1 b/man/neighbours.1 new file mode 100644 index 0000000..07165ea --- /dev/null +++ b/man/neighbours.1 @@ -0,0 +1,43 @@ +.TH NEIGHBOURS 1 "Version 1.0" "Environmental planning utilities" "EPU user manual" +.SH NAME +neighbours \- prints list of neighbouring clasees in epp-file +.SH SYNOPSIS +.B neighbours [-%][-d] file +.SH DESCRIPTION +This command searches +.IR epp -file +for all class boundaries and print a table of class pair which +are neighbouring at least in one place. +DO NOT MIX it with EPPL7 NEIGHBOUR command, which is part of +.BR evaluate (1) +in EPU. + +It prints pairs of classes to stdout, one per line separated by commas. + +Each pair of classes can be printed once or twice, first among neighbours +of first class in pair, than neighbours of second. + +.SH OPTIONS +.TP 8 +.B --help +displays brief usage information. +.TP 8 +.B --version +displays version number +.TP 8 +.B --verbose -% +Displays percentage of processed lines in file. +.TP 8 +.B -d --double +print each pair twice. + +.SH SEE ALSO +.BR outtable (1), mapcolor (1), evaluate (1), extents (1). + +.SH AUTHOR + +Victor B. Wagner + +.SH BUGS + +??? diff --git a/man/outtable.1 b/man/outtable.1 new file mode 100644 index 0000000..44fcdb1 --- /dev/null +++ b/man/outtable.1 @@ -0,0 +1,153 @@ +.TH OUTTABLE 1 "Version 1.0" "Environmental planning utilities" "EPU user manual" +.SH NAME +outtable \- computes table of statistics from several epp files. +.SH SYNOPSIS +.B outtable +.RI [ options ] +.RI [ function "] file [ [" function "] file ...]" + +.SH DESCRIPTION +.B outtable +takes several +.IR epp -files +counts all possible combinations of classes in them and produces +table of them. +.PP +Some files can be preceded by +.I function +Such files wouldn't be used to define new combination. Instead, corresponding +column of table would contain value of function, computed from this file for +area, defined by combination of classes of all "function-less" files. +.PP +All files, used to define combination, should be specified before first +file with function. +.PP +If no function defined, table would be appended by column, containing area +of each combination. +.PP +If all files have function, table would contain only one row, containing +values of the functions for all area. +.PP +If files have different cell size and limits, limits and coordinate systems +of the first file are used, unless overriden by +.B +--base +option. +.PP +By default, semantic value of classes are considered equial to values of +classes. This can be overridden by specifying parameters of linear mapping +function using + +.BR -z " and " -Z " options." +This option can be specified only once per invocation, becouse usially +.B outtable +is used to calculate statistics for one file in combinations, given by +several other files. +.PP +By default, all area-related values are calculated in alternative coordinate +units. It can be overriden using +.B -c +option. +.SH OPTIONS +.TP 8 +.B --help +displays brief usage information. +.TP 8 +.B --version +displays version number +.TP 8 +.B --verbose -% +Displays percentage of processed lines in file. +.TP 8 +.B -u --union +Take into account all cells, where at least one of output files is not offsite. +By default, only cells where all input files are onsite are taken into account. +.TP 8 +.B -c --cells +Output areas in cells. By default map units as specified in file header +are used to compute areas. +.TP 8 +.BI -d "char " --delimiter= char +sets table column separator to +.I char. Defaults to comma. +.TP 8 +.BI -b " file" --base " file" +Specifies epp file, used as reference grid. Cell area and cell size of this +file, as well as its coordinate limits would be used for processing. +Defaults to first file in the command line. +.TP 8 +.BI -z " value" +Specifies multiplier for calculating semantic value from class value. +.TP 8 +.BI -Z " value" +Specifies offset of semantic values, i.e. semantic value of class 0. +.SH FUNCTIONS +.TP 8 +.B -sum +Sum of classes in given file for combination, multiplied by cell area. +.TP 8 +.B -cnt +Count of onsite cells of given file. +.TP 8 +.B -avg +Average cell value +.TP 8 +.B -min +Minimum cell value +.TP 8 +.B -nmin +Area of cells with minimum value + +.TP 8 +.B -max +Maximum cell value +.TP 8 +.B -nmax +Area of cells with maximum value +.TP 8 +.B -mode +Modal value (value of most cells) +.TP 8 +.B -nmode +Area of cells with modal value +.TP 8 +.B -fewest +Class with fewest cells +.TP 8 +.B -nfewest +Area of cells in fewest class +.TP 8 +.B -range +Range of classes (maximum-minimum) +.TP 8 +.B -classes +Number of different classes +.TP 8 +.B -or +Bitwise or of all cells (values of +.BR -z " and " -Z +options are not used) +.TP 8 +.B -and +Bitwise and of all cells (values of +.BR -z " and " -Z +options are not used) +.TP 8 +.B -std +Standard deviation of classes +.TP 8 +.B -var +Variance of classes +.TP 8 +.B -corr +Correlation coefficient between two files. Requires two arguments. +.SH SEE ALSO +.BR intable (1), reclass (1), evaluate (1), resample (1), eheader (1) + +.SH AUTHOR + +Victor B. Wagner + +.SH BUGS + +??? diff --git a/man/palette.n b/man/palette.n new file mode 100644 index 0000000..c67ae7b --- /dev/null +++ b/man/palette.n @@ -0,0 +1,67 @@ +.TH palette n 1.0 Fgis "user Tcl commands" + +.SH NAME +palette \- Create and manipulate color palettes + +.SH SYNOPSIS +\fB palette \fIoption\fR ?\fIarg\fR? + +.SH DESCRIPTION +.PP +This command creates palette object, which is used for map visualisation. Palette is +array of 256 RGB color specifications, indexed by integers from 0 to 255. +Typically palette entry N is used for displaying map class N. +Upon creation of object new Tcl command with same name as object is defined +and can be used for manipulating palette. \fBpalette\fR command returns +name of created object. One palette, named \fBdefaultpalette\fR is created +during initialization of fGIS. In difference of user-created palettes it +cannot be modified. + +.SH OPTIONS +.TP 4 +\fBpalette read \fIfilename\fR +- reads palette from specified file. File should confirm EPPL7 clr file +syntax. +.TP 4 +\fBpalette parse \fIstring\fR +- reads palette from string. String should have same format as EPPL7 clr file. +.TP 4 +\fBpalette set \fIlist\fR +- creates palette from list of color specification. Each element of list +should have format \#rrggbb. Color names are not supported by palettes. +Color specifications are assigned to palette indices in sequentual order. +.TP 4 +\fBpalette blank\fR +- creates new palette with all entries set to white (#ffffff). + +.TP 4 +\fBpalette copy \fIpaletteName\fR +- creates a copy of existing palette. This allows to create modifable copy +of default palette. +.SH OBJECT COMMAND +Palette object names can be used as command names. They support folowing +options: +.TP 4 +\fIpaletteName\fB delete\fR - +destroys palette object. +.TP 4 +\fIpaletteName\fB get\fI index\fR +- return color for given index in palette. Color is returned as \#rrggbb, +and can be used as color specification in Tk commands. +.TP 4 +\fIpaletteName\fB list\fR +- return list of all colors in palette. This list always contains 256 +elements. This list can be used as argument for \fBpalette set\fR command, +to create same palette. +.TP 4 +\fIpaletteName\fB print\fR +- returns string, containing content of valid EPPL7 clr file, which can +be used to reproduce this palette. +.TP 4 +\fIpaletteName\fB set\fI index value\fR +- changes contents of given entry to \fIvalue\fR. Value should be in form +\#rrggbb. Other forms of colors, supported by Tk are not supported by +palettes. +.SH SEE ALSO +.BR patterns (n), fgisRasterColorImage (n). + diff --git a/man/planchet.n b/man/planchet.n new file mode 100644 index 0000000..3b92b8c --- /dev/null +++ b/man/planchet.n @@ -0,0 +1,535 @@ +'\" Stuff below is shamelessly borrowed from canvas(n) manual page, and +'\" therefore shares its copyright +.if t .wh -1.3i ^B +.nr ^l \n(.l +.ad b +'\" # Start an argument description +.de AP +.ie !"\\$4"" .TP \\$4 +.el \{\ +. ie !"\\$2"" .TP \\n()Cu +. el .TP 15 +.\} +.ie !"\\$3"" \{\ +.ta \\n()Au \\n()Bu +\&\\$1 \\fI\\$2\\fP (\\$3) +.\".b +.\} +.el \{\ +.br +.ie !"\\$2"" \{\ +\&\\$1 \\fI\\$2\\fP +.\} +.el \{\ +\&\\fI\\$1\\fP +.\} +.\} +.. +'\" # define tabbing values for .AP +.de AS +.nr )A 10n +.if !"\\$1"" .nr )A \\w'\\$1'u+3n +.nr )B \\n()Au+15n +.\" +.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n +.nr )C \\n()Bu+\\w'(in/out)'u+2n +.. +.AS Tcl_Interp Tcl_CreateInterp in/out +'\" # BS - start boxed text +'\" # ^y = starting y location +'\" # ^b = 1 +.de BS +.br +.mk ^y +.nr ^b 1u +.if n .nf +.if n .ti 0 +.if n \l'\\n(.lu\(ul' +.if n .fi +.. +'\" # BE - end boxed text (draw box now) +.de BE +.nf +.ti 0 +.mk ^t +.ie n \l'\\n(^lu\(ul' +.el \{\ +.\" Draw four-sided box normally, but don't draw top of +.\" box if the box started on an earlier page. +.ie !\\n(^b-1 \{\ +\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' +.\} +.el \}\ +\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' +.\} +.\} +.fi +.br +.nr ^b 0 +.. +'\" # VS - start vertical sidebar +'\" # ^Y = starting y location +'\" # ^v = 1 (for troff; for nroff this doesn't matter) +.de VS +.if !"\\$1"" .br +.mk ^Y +.ie n 'mc \s12\(br\s0 +.el .nr ^v 1u +.. +'\" # VE - end of vertical sidebar +.de VE +.ie n 'mc +.el \{\ +.ev 2 +.nf +.ti 0 +.mk ^t +\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' +.sp -1 +.fi +.ev +.\} +.nr ^v 0 +.. +'\" # Special macro to handle page bottom: finish off current +'\" # box/sidebar if in box/sidebar mode, then invoked standard +'\" # page bottom macro. +.de ^B +.ev 2 +'ti 0 +'nf +.mk ^t +.if \\n(^b \{\ +.\" Draw three-sided box if this is the box's first page, +.\" draw two sides but no top otherwise. +.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c +.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c +.\} +.if \\n(^v \{\ +.nr ^x \\n(^tu+1v-\\n(^Yu +\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c +.\} +.bp +'fi +.ev +.if \\n(^b \{\ +.mk ^y +.nr ^b 2 +.\} +.if \\n(^v \{\ +.mk ^Y +.\} +.. +'\" # DS - begin display +.de DS +.RS +.nf +.sp +.. +'\" # DE - end display +.de DE +.fi +.RE +.sp +.. +'\" # SO - start of list of standard options +.de SO +.SH "STANDARD OPTIONS" +.LP +.nf +.ta 4c 8c 12c +.ft B +.. +'\" # SE - end of list of standard options +.de SE +.fi +.ft R +.LP +See the \\fBoptions\\fR manual entry for details on the standard options. +.. +'\" # OP - start of full description for a single option +.de OP +.LP +.nf +.ta 4c +Command-Line Name: \\fB\\$1\\fR +Database Name: \\fB\\$2\\fR +Database Class: \\fB\\$3\\fR +.fi +.IP +.. +'\" # CS - begin code excerpt +.de CS +.RS +.nf +.ta .25i .5i .75i 1i +.. +'\" # CE - end code excerpt +.de CE +.fi +.RE +.. +.de UL +\\$1\l'|0\(ul'\\$2 +.. +.TH planchet n 1.0 Fgis "user Tcl commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +planchet \- Create and manipulate planchet widgets +.SH SYNOPSIS +\fBplanchet\fI \fIpathName \fR?\fIoptions\fR? +.SO +\-background \-insertwidth \-state +\-insertbackground \-relief \-tile +\-cursor \-insertborderwidth \-selectbackground \-takefocus +\-highlightbackground \-insertofftime \-selectborderwidth \-xscrollcommand +\-highlightcolor \-insertontime \-selectforeground \-yscrollcommand +.SE +.PP +\fBNote:\fR Standard optiosn \fb\-highlightthickness\fR and \fB\-bordewidth\fR +are ignored by planchet, and set to 0. Therefore \fB\-relief\fR options have +no effect. +.SH "WIDGET-SPECIFIC OPTIONS" +.OP \-coordformat coordFormat CoordFormat +Specifies format string to display current map coordinates, if no projection +defined. Defaults to "X=%0.8g Y=%0.8g" +.OP \-orient orient Orient +Specifies printing orientation for this planchet. May be either portrait +or landscape. Defaults to landscape +.OP \-lookwidth lookWidth LookWidth +Wraplength of text in popup look window. Defaults to 200. +.OP \-shiftfactor shiftFactor ShiftFactor +Specifies share of window size to move on \fBshift\fR widget command. +Defaults to 0.75 +.OP \-resizable resizable Resizable +Specifies a boolean value that indicates whether or not should planchet +adjust its width/height ratio, when coordinate limits are first defined. +.OP \-rulerpos rulerPos RulerPos +Indicates position of scale ruler in planchet. (its left end). Should be +list of two coordinates in any form, acceptable by Tk. Positive values +are measured from top and left and negative from lower and right side +of planchet +.OP \-scalevar scaleVar Variable +Specifies the name of variable. Current scale of map would be stored in +this variable automatically upon each change of scale in form 1:denominator. +If variable doesn't exist in global scope, it would be created. +.OP \-statusline statusLine none +Specifies name of label widget which would be used for displaying status +information of planchet (i.e. current mouse pointer coordinates). +Widget should exist before creating planchet or before passing it to +planchet configure command. +.OP \-legbox legBox none +Specifies name of canvas widget which would display scrollable legend of +base layer. Note, that scrollable legend is not printed automatically by +print command. All contents of this widget would be erased each time +base layer changed in planchet. +.OP \-zoombutton zoomButton none +Specifies name of button, which is used to initiate zoom operation on +canvas. (usially via \fBzoom\fR) widget command. Planchet controls its +state, disabling it, if coordinate system is not defined. It should +exist before it passed to planchet. +.OP \-unzoombuttons unzoomButtons none +Specifies list of buttons, which are used to perform various unzoom operations +(like \fBunzoom\fR or \fBlimits default\fR widget commands). Planchet +controls their state, disabling them if such operations are impossible. +.OP \-shiftbuttons shiftButtons none +Specifies list of four buttons for perform shift operation on planchet. +Buttons are specified in following order left(west) down(south) up(north) and +right(west), the same way as vi cursor movement keys are situated on keyboard. +.OP \-zoombutton zoomButton none +Specifies name of button, which is used to initiate zoom operation on +canvas. (usially via \fBzoom\fR) widget command. Planchet controls its +state, disabling it, if coordinate system is not defined. It should +exist before it passed to planchet. +.OP \-unzoombuttons unzoomButtons none +Specifies list of buttons, which are used to perform various unzoom operations +(like \fBunzoom\fR or \fBlimits default\fR widget commands). Planchet +controls their state, disabling them if such operations are impossible. +.OP \-shiftbuttons shiftButtons none +Specifies list of four buttons for perform shift operation on planchet. +Buttons are specified in following order left(west) down(south) up(north) and +right(west), the same way as vi cursor movement keys are situated on keyboard. +This buttons should be either all be specified or all be empty, in which case +list of four empty elements should be passed. Planchet not only controls +state of buttons, but also redefines their commands. +.OP \-projection projection none +Specifies Fgis projection object which is used to convert chartographic +coordinates of planchet into geographic (latitude and longitude) and vice versa. + +.PP +In addition to these all options of \fBcanvas\fR widget are supported. +.SH INTRODUCTION +.PP +The \fBplanchet\fR command creates a new window (given by the \fIpathName\fR +argument and makes it into planchet widget. + +Additional options, described above, can be given to control its behavoir. +Currently they could be specified only in command line, not in option database, +but it shoudl change in future. + +\fBplanchet\fR command returns its \fIpathName\fR argument. At the time this +command is invoked, there must not exist a window, named \fIpathName\fR, +but \fIpathName\fR's parent must exist. +\fBplanchet\fR command also creates new Tcl command named \fIpathName\fR +which can be used to control widget. + +.PP + Planchet widget have all behavoir +supported by Tk \fBcanvas\fR widget, but, in addition it could have +chartographic coordinate system and able to visualize and manipulate maps. + +.SH COORDINATE SYSTEM + +Planchet coordinate system is real-world coordinate system. Its coordinates +should be in meters of earth surface, not in pixels, millimeters or other +map sheet or screen-related units. It can be defined either explicitely +via \fBlimits\fR widget command, or implicitely, when first map is shown +in planchet. + +There are special commands which allow to recalculate from map (realword) +coordinates to screen coordinates. Screen coordinate system of planchet is +same as of canvas. +.SH LAYERS +Planchet can visualize maps, which are represented as Fgis layer objects. +There are two ways of display layer - as base layer or as ovelay. +.PP +Base layers are opaque, they are typically raster layers, shown by colors. +There can be only one base layer in plachet in given time. If \fBlegbox\fR +helper widget is defined, and legend for base layer is drawable, it would +be displayed in this widget. +Several layer types couldn't be displayed as base layers. + +.PP +Overlay layers are transparent, although visible. There can be several +overlay layers in planchet at given time. Any layer can be displayed as +overlay. +.PP +When first layer is displayed in planchet, with undefined coordinate system, +coordinate system limits for planchet are got from limits of layer. If +layer cannot provide this information, it causes an error. + +.SH HELPER WIDGETS + +Planchet can be accompanied with several other widgets, which are used +to interact with user. If this widgets are passed to planchet via commandline +options (or via widget \fBconfigure\fR) command, it can control them +automatically and disable them, if corresponding action is impossible. +See \fBOPTIONS ABOVE\fR. + +.SH SCALE INDICATION + +There are two traditional ways of scale indication - numerical and graphical. +As numerical indication, \fB\-scalevar\fR option of planchet widget allows +to specfy Tcl global variable, which would always hold current value of map +scale. +.PP +As graphical representation of scale, +planchet can display scale ruler which shows how some realword distance +is visible in planchet. + +.SH LOOK FEATURE + +Planchet allows to collect information from several layers in given point. +By default it pops up window with this information on right button click. +Set of layers which included in this information is called \fBlook list\fR. + +.SH "WIDGET COMMAND" +.PP + +The \fBplanchet\fR command creates a new Tcl command whose name is +\fIpathName\fR. This command can be used to invoke various operaitons on +the widget. It has following general form: +.CS +\fIpathName option \fR?\fIarg arg ..\fR? +.CE +\fIOption\fR and the \fIarg\fRs +determine the exact behavior of the command. +Planchet supports all widget commands, defined for \fBcanvas\fR widget +and following special commands, specific to planchet: +.TP +\fIpathName \fBclear\fR +Removes all layers from planchet, and from look list and unsets coordinate +system +.TP +\fIpathName \fBcget\fI option\fR +Returns value of specified configuration option. In addition to standard +options and widget specific options, supports all options of canvas widget. +Several internal variables can also be obtained this way, but it is dirty +and undocumented hack. +.TP +\fIpathName \fBconfigure\fI option arg ?option arg ...?\fR +Allows to change value of one or more options. +.TP +\fIpathName \fBfit\fI x y\fR +Returns 1 if point, given in real world coordinates is inside current +planchet limits, and 0 otherwise. +.TP +\fIpathName \fBhide\fI pattern ?pattern...?\fR +Removes all layers which matches pattern from planchet. +.TP +\fIpathName \fBlayers\fR ?\fIpattern\fR? +Return list of all visible layers, either base or overlays, which match given +pattern. By default - all layers. +.TP +\fIpathName \fBlimits\fR +Used to control limits of realword coordinate system. Can have one of +following form +.RS +.TP +\fBlimits\fR +Without any arguments return list of four double values, representing real +world coordinates of window sides. They are given in folowing order: +.CS +\fIXLeft YBottom XRight YTop +.CE +.TP +\fBlimits \fIlist\fR +.TP +\fBlimits \fIxleft ybottom xright ytop\fR +Given list of four double values or four double values as separate arguments, +sets planchet limits for this value. If \fB\-resizable\fR option is true +and no coordinate system was defined before, adjusts width/height ratio +of planchet to reflect this ratio of given limits. Otherwise expands +given limits to have same width/height ratio as widget. + +If directions of axes of given limits doesn't match those of currently +defined coordinate system, silently reverts them. Therefore order +of coordinates in insignificant, once coordinate system is defined. + +If coordinate system was defined, assumes that zooming operation is +performed and stores old limits in zoom stack for subsequent unzoom +operation. If scale of given limits is smaller, then +of some limits in zoom stack, discards all elements with scale larger +than given for unzoom operation shouldn't increase scale. Nevertheless +initial limits are never discarded this way. +.TP +\fBlimits default\fR +Clears zoom stack and restores coordinate limits to their initial values. +.RE + +.TP +\fIpathName \fBlook\fR +Controls \fBLOOK FEATURE\fR of planchet. Can have one of following forms +.RS +.TP +\fBlook add \fIlayer\fR +adds layer to look list. +.TP +\fBlook list \fR?\fIpattern\fR? +Returns list of layers in look list, which match pattern. By default all layers +.TP +\fBlook remove \fIpattern\fR +removes layers which match pattern from look list +.TP +\fBlook remove all\fR +clears look list entirely +.TP +\fBlook \fIx y \fR?\fB-titled|-list|-raw\fR? +return list of information for all layers in look list at given point. +If \fB-titled\fR option is specified, each element in list is formatted +string. Otherwise it is two element list which first element - layer title, +and second - layer value. \fB-raw\fR option returns only values, without +layer title information. + +Length of this list not neccesary matches length of look list, becouse if +some layers are undefined in given point, they do not create list element. +.RE +.TP +\fIpathName \fBmapx \fIx\fR +.TP +\fIpathName \fBmapy\fR +Given screen coordinate in any form, acceptable by Tk, returns realword +coordinate. +.TP +\fIpathName \fBprint\fR ?option arg ...? +Wrapper around \fBpostscript\fR command. Uses default Fgis font mapping and +print system, also widget default orientation. By default, send output +to default Fgis printer using command, defined in fgis configuration file. + +Following options are supported: +.RS +\fB-colormode\fI mode\fR +Same as \fBcolormode\fR option in canvas \fBpostscript\fR command. +.TP +.TP +\fB-file\fI filename\fR +Write postscript representation of planchet into given file, instead of +piping it to print command. +.TP +\fB-fontmap \fIvariable\fR +array used to map screen fonts to postscript fonts. See canvas \fBpostscript\fR +command for more information. +.TP +\fB-printer \fIprintername\fR +Overrides default printer, specified in fgis.rc file. +.RE +.TP +\fIpathName \fBruler\fI ?on|off?\fR +Controls scale ruler. +.TP +\fIpathName \fBscale\fR ?\fIdenominator\fR? +With no arguments returns current scale denominator. If \fIdenominator\fR +is given, adjust coordinate limits so that scale would be as specified and +center point of widget would have same realworld coordinates as before. + +If any other arguments are specified, behaves as \fBcanvas\fR widget \fBscale\fR +command. + +.TP +\fIpathName \fBscrx \fIx\fR +.TP +\fIpathName \fBscry \fIy\fR +Given realworld coordinate, returns screen coordinate in pixels. +.TP +\fIpathName \fBsetstatus\fR +Displays message if \fB\-statusline\fR helper widget, if defined, otherwise +does nothing. Can have one of two form: +.RS +.TP +\fBsetstatus\fI message\fR +displays message as specified +.TP +\fBsetstatus\fI x y\fR +Displays given coordinates. If no projection defined, they would be displayed +using Tcl \fBformat\fR command with value of \fB\-coordformat\fR option as +first argument. Otherwise they would be displayed using \fBformat\fR object +command of current projection. +.RE +.TP +\fIpathName \fBshift \fIdirection\fR +Changes current coordinate limits so that current view shifts in specified +\fIdirection\fR by share of corresponding widget size, specified by +\fB-shiftfactor\fR option. +.TP +\fIpathName \fBshow \fIlayer \fR?\fB-base\fR|\fB-overlay\fR? +Displays specified layer. If neither \fB-base\fR nor \fB-overlay\fR is specifed, +shows layer as base if no base layer currently present and layer can be +displayed as base. Otherwise displays it as overlay. +.TP +\fIpathName \fBunzoom\fR +Pops last coordinate limits from zoom stack +.TP +\fIpathName \fBzoom\fR ?\fI x y\fR? x y\fR?? +Initiates interactive zoom operation. If no coordinates are specified, +prompts user to pick both corners of rectangle to display. If one pair +is specified, prompts only for second pair. With two pairs just converts +values from canvas to realworld coordinates and performs \fBlimits\fR command +on them. +.CS +\fIpathName \fBzoom cancel\fR +.CE +can be used to abort interactive zoom operation currently in progress. +.CS +\fIpathName \fBzoom cancel\fR +.CE +can be used to abort interactive zoom operation currently in progress. +.SH SEE ALSO +.BR layer (n) +.SH BUGS +No care taken to do something useful if interactive zoom operation is +performed on two planchets simulateously. + + + + diff --git a/man/projection.n b/man/projection.n new file mode 100644 index 0000000..1a3b4ba --- /dev/null +++ b/man/projection.n @@ -0,0 +1,85 @@ + +.TH projection n 1.0 Fgis "user Tcl commands" + +.SH NAME +projection \- Create and manipulate projection objects + +.SH SYNOPSIS +\fB projection \fItype\fR ?\fIparameters\fR? +.PP + + +.SH DESCRIPTION +.PP + +This command creates projection object, used to recalculate geographic +coordinates (latitude and longitude) into map projection coodrinates. +.PP +\fBprojection\fR command takes list of options and +returns name of newly created projection object. +Name of object can be used as Tcl command which have several subcommands +(see \fBPROJECTION SUBCOMMANDS\fR below) used for manipulation +of projections. + +.SH PROJECTION TYPES + +Most important property of projection is projection type. fGIS supports +following types of projections: + +\" list should be here + +.SH PROJECTION OPTIONS + +\" list should be here + +.SH PROJECTION SUBCOMMANDS +.TP 8 +\fIprojName \fBforward\fI long lat\fR +recieves two arguments - geographic longitude and latitude as degrees in +decimal format and returs list of two double values representing map +coordinates in meters. + +.TP 8 +\fIprojName \fBbackward\fI X Y \fR +performs backword transformation - given map coordinates in meters +returns longitude and latitude in decimal degrees, +.TP 8 +\fIprojName \fBformat\fI X Y\fR ?\fB-format\fI formatString\fR +Returns formatted representation of latitude and longitude. String +can contain following escapes sequences: +.RS +.TP +\fB%lt\fR +unsigned latitude in DDMMSS format +.TP +\fB%lg\fR +unsigned longitude in DDMMSS format +.TP +\fB%-t\fR \fB%-g\fR +optionally signed latitude and longitude in DDMMSS format +.TP +\fB%+t\fR \fB%+g\fR +explicitely signed latitude and longitude in DDMMSS format +.TP +\fB%lG %lT %-G %-T %+G %+T\fR +same as above, but in decimal fractions of degree +.TP +\fB%dl %dg\fR +direction indicator - letters N and S for latitude and E and W for +longitude (or some other national language values as defined in fgis.rc +file). +.RE +If \fIformatString\fR omitted, default "%lt%dt %lg%dg" is used. +.TP 8 +\fIprojName\fB dump\fR +returns argumets for projection command used to create this projection +object. +.TP 8 +\fIprojName\fB delete\fR +destroys projection object. + +.SH "SEE ALSO" + +.BR proj "(1), " pj_init "(3), " transform (1) + + diff --git a/man/raster.n b/man/raster.n new file mode 100644 index 0000000..353ac51 --- /dev/null +++ b/man/raster.n @@ -0,0 +1,326 @@ +.TH raster n 1.0 Fgis "developer Tcl commands" + +.SH NAME +raster \- Create and manipulate raster object + +.SH SYNOPSIS +\fB raster \fIfilename\fR ?\fIoptions\fR? + +.SH DESCRIPTION +.PP +This command allows to create raster objects. Raster objects are more low-level +concept than fGIS \fBlayers\fR. They directly correspond to raster files +in EPPL7 format. Their values are always unsigned short integer. +They even make cell size visible to user. This command returns name of +raster object which is used for manipulating this object. By default +it requires existing raster file without reclass table. + +Raster files are objects which holds information of certain integer spatial +variable in given rectangular area. Value is stored with certain granulariry. +Minimal square, which can be addressed as separate unit, is named cell. +Of course, you can specify coordinates with any precision, but while they are +in same cell, same value would be returned. Moreover, when you edit raster, +you can change values only on per cell basis. + +Raster file is always rectangular, but spatial variable can be defined on +any arbitrary area. So, special value is reserved for "undefined" areas of +raster. It is named \fBoffsite\fR value. Typically you can read raster it +any coordinates, but if no information is provided for this area, offsite +would be returned. + +There are certain limitation on raster files - file cannot contain more than +32767 cells per row or per column. Possible values of raster should be in +range 0\-65535. Rows and columns of cells can be numbered starting from +any integer, provided that no row or column in file has number out of range +-32767- 32767. fGIS, however never relies on column numbers. They are supported +only for compatibility with EPPL7. + +Raster objects differs from raster files in the way that they include +\fBreclass table\fR. This allows to store information about several +spatial variables in one file, provided that total count of value combination +doesn't exceed raster file limit. Reclass table defines correspondence +between file classes (values) and values, returned by raster object. +It can be defined by two ways - using special syntax like in EPPL7 RECLASS +command (see RECLASS SYNTAX below) or using Tcl list, each element of which +is pair of values, first base, then reclassed. + +When raster objects are accessed or created via GIS operations, user may not +be aware about underlying raster file level. But when objects are created +by interative editing, certain properties of raster (i.e. cell size) should +be specified. + +Raster objects behave like other fGIS objects - layers, legends, palettes etc. +Once object is created, new Tcl command with same name is created. This +command is used to access and modify rasters. + +.SH OPTIONS +.TP 4 +\fB-reclass \fIstatements\fR +-specifies reclass table for created raster object. \fIstatements\fR is +string, containing set of reclass statements. See \fBRECLASS SYNTAX\fR below +for details +.TP 4 +\fB-table \fIlist\fR +-specifies reclass table in form of Tcl list. Each +element of this list should be list of two integers, first of them representing +value in raster file, and second - representing value which would be value +of new raster object. +.TP 4 +\fB-new\fR +- specifies that new raster file should be created instead of +opening old. This option should be specified immediately after file name +and followed by several other options, defining properties of new raster. +All subsequent options are applicable only if \fB-new\fR is specified. +.TP 4 +\fB-like\fI rasterObject\fR +- specifies that all important properties +should be copied from existing raster object. +.TP 4 +\fB-width\fI integer\fR +- specifies how many cells should appear in each +row. Cannot be used together with \fB-like\fR +.TP 4 +\fB-height\fIinteger\fR +- specifies how many cells should be in each column. +.TP 4 +\fB-offsite\fIinteger\fR + - specifies which value would be used as "no data" +value. Default is 65535 for 16-bit files and 255 for 8-bit. Value -1 can +be specified for 8-bit files. It means that all classes are onsite. For +16-bit files it is equivalent to 65535. +.TP 4 +\fB-8bit\fR - specifies that only one byte should be used for storing +values of raster. This limits value range to 0-255, slightly decreases file +size (usially much less than two times) and makes file compatible with +EPPL7 ver. 2.1. +.TP 4 +\fB-limits\fI{x1 y1 x2 y2}\fR +- Allows to specify list of four double values, +determinig map coordinates of file. +.TP 4 +\fB-cell\fI value\fR - specifies size of cell. In conjunction with \fB-limits\fR +it gives more convinient way to create new raster, becouse limits defines +area of interest and cell size - accuracy of map. + +.SH OBJECT COMMAND +\fBraster\fR command creates new Tcl command with same name as raster object, +which can be used to manipulate this object. + +\fIrasterName\fB box\fIvalue x1 y1 x2 y2\fR - +fills rectangular region with given value. Raster should be opened in +read-write mode (either by \fB-new\fI option of object command or by +\fBload\fR object command). Returns list of four double values, specifying +region actually affected by command. (Can be less that specified region, +if it exceeds raster boundary). Value is class of base raster file, not +reclassed value. + +.TP 4 +\fIrasterName\fB bpp\fR - returns size of data in this raster file +(8 for 8-bit and 16 for 16 bit rasters). +.TP 4 +\fIrasterName\fB cache \fR?\fInew size\fR? +- controls size of cache. If raster file is accessed from disk (default +read only mode) setting sufficient cache can improve performance of operations, +which require nonsequentual access, like \fBtransect\fR. +.TP 4 +\fIrasterName \fBcell\fR ?\fB-area\fR? +- returns parameters of cell. By default, returns cell width in map +coordinates, which should be meters, and with \fB-area\fI flag returns +cell area in current units (see \fBunit\fR object command). +.TP 4 +\fIrasterName \fBcelllimit\fR +- returns list of four intergers, representig start and end numbers of cells +in order \fIfirst column\fR, \fIlast row\fR, \fIlast column\fB, \fIfirst row\fR. +(Why this order? X direction of cell numbers is same as of coordinates + (usially), and Y coodinates usially go from bottom to top, while cells - from +top to bottom. So, order of values is same as order of values in \fBlimits\fI +object command. +.TP 4 +\fIrasterName \fBclasses \fIvalue\fR +- returns list of base file classes which are mapped to specified value of +this raster object. +.TP 4 +\fIrasterName \fBcircle\fI value x y radius \fR?\fB-cells\fR? +- fills circulare region in read-write raster with given value. If \fB-cells\fR,flag is given, radius is assumed to be in raster cells. Otherwise it is assumed +to be in coordinate units. Returns list of coordinates, specifying actualy +affected region. +.TP 4 +\fIrasterName \fBcol\fI x\fR +- returns cell number corresponding to given X coordinate. Returns error, if +coordinate is out of file boundaries. +.TP 4 +\fIrasterName \fBcomment\fR ?\fIstring\fR? +- returns (or modifies) comment, stored in file header. Comment length is +limited by 32 symbols. +.TP 4 +\fIrasterName \fBcount\fR ?\fBoptions\fR? +- performs various area-calculating operation +General formats folows: +.TP 8 +\fIrasterName \fBcount\fR ?\fB--\fR? \fI varname \fR?\fIregion specification\fR? +fills dynamic array \fIvarname\fR indexed by raster classes by areas of these +classes in given region. +.TP 8 +\fIrasterName \fBcount -classes \fIlist \fR?\fIregion specification\fR? +returns area of given classes within given region. + +Region specification defaults to whole file. Other possible formats are: +.TP 8 +\fB-box\fI x1 y1 x2 y2\fR +- within given rectangular area +.TP 8 +\fB-polygon\fI x y x y ...\fR +- within polygon, given by set of coordinate pairs +.TP 8 +\fB-radius\fI distance x y ...\fR +within given distance of any of given points. +.TP 8 +\fB-mask\fI rasterObject list\fR +in areas where value of another rasterObject is in given list. + +.TP 4 +\fIrasterName \fBdelete\fR +- destroys raster object. If raster was in readwrite mode, all unsaved changes +are lost. +.TP 4 +\fIrasterName \fBextents\fI value\fR +- returns list of four coordinates, within those all values of given class +are contained. +.TP 4 +\fIrasterName \fBfilename\fR +- returns name of file, corresponding to this raster object. +.TP 4 +\fIrasterName \fBfill\fI value x y \fR?\fB-stop\fR?\fI value\fR +- fills area, starting with given coordinates with value. By default, +stops on encounter of any value other than in given point. If \fB-stop\fR +option is specified, stops only when encountering given value. Returns +list of coordinates, specifying actually affected region. +.TP 4 +\fIrasterName \fBframe\fI value x1 y1 x2 y2\fR ?\fB-width\fI cells\fR? +- a rectangle with given value, not changing inside area. By default +this rectangle is 1 cell wide. +.TP 4 +\fIrasterName \fBget\fI x y \fR?\fB-base\fR? +Returns value of raster in given point. By default returns reclassed value, +but if \fB-base\fR is specified, returns class of raster file. +.TP 4 +\fIrasterName \fBlimits\fR +Returns list of four doubles, specifying physical limits of raster file, in +order \fIXLeft\fR, \fIYBottom\fR, \fIXRight\fR, \fIYTop\fR. +.TP 4 +\fIrasterName \fBline\fI value x y x y .... \fR?\fB-width \fIcells\fR? +draws a line with given value. By default one-cell wide. Returns boundaries +of region affected. +.TP 4 +\fIrasterName \fBload\fR +Loads raster file into memory, changing it from readonly to readwrite mode, +and enabling all editing operation. (\fB-new\fR option of \fBraster\fR command +performs \fBload\fR implicitely). +.TP 4 +\fIrasterName \fBmax\fR +-returns maximal value of raster object. +.TP 4 +\fIrasterName \fBmin\fR +- returns minimal value of raster object. +.TP 4 +\fIrasterName \fBoffsite\fR ?\fIvalue\fR? +- returns offsite value for raster object, or modifies it. +.TP 4 +\fIrasterName \fBpolygon\fI value x y x y ...\fR +- fills given polygon of given value. Returns boundaries of region affected. +.TP 4 +\fIrasterName \fBput\fI value x y\fR +Changes value of individual cell. Returns nothing. +.TP 4 +\fIrasterName \fBreclass\fR ?\fIoption\fR? ?\fIarg\fR? +- manipulates reclass table. Without any options, returns reclass table as +Tcl list. +.TP 8 +\fIrasterName \fBreclass -statements\fR +option returns reclass table in form of reclass statements. (see \fB RECLASS SYNTAX\fR below). +.TP 8 +\fIrasterName \fBreclass -table\fI list\fR +modifies current reclass using given Tcl list. Values for classes given +in this list would be changed as specified, all other remains unchanged. +.TP 8 +\fIrasterName \fBreclass \fIstatements\fR +modifies reclass using specified reclass statements. As \fB-table\fR options, +applies statements to base classes and leaves all nonspecified classes as is. +.TP 8 +\fIrasterName \fBreclass -clear\fR +clears all changes in reclass table and makes reclassed classes equial to +base classes. +.TP 4 +\fIrasterName \fBrow\fI y\fR +return cell number, correspondign to given Y coordinate. Raises error, if +coodinnate is outside file limits. +.TP 4 +\fIrasterName \fBsave\fR ?\fIoptions\fR? +- saves raster file. By default, if raster is in readwrite mode, saves +changes to current filename. +.TP 8 +\fIrasterName \fBsave -as\fI filename\fR +- saves raster, open for editing into other file, and makes this file +current file of this raster object. +.TP 8 +\fB-backup\fR +option can be specified +for both \fBsave\fR and \fBsave -as \fRcommands. It makes raster object to +keep old version of file with suffix \fI.bak\fR appended to name. +.TP 8 +\fIrasterName \fBsave -to\fI filename\fR ?\fB-8bit\fR? +allows to write raster object into raster file. Reclass table is applied +to this operation, so new file would have base classes like classes of +raster object, rather than classes of its base file. + +If \fB-8bit\fR switch is specified, resulting raster will be forced to 8-bit +by discarding high-order byte, even if max value or offsite are outside +0-255 range. (in latter case offsite would be set to 65535). +.TP 4 +\fIrasterName \fBshift \fI dx dy\fR +changes origin of cell (row/column) numbers. This is required for certain +command of DOS version of EPPL7, although fGIS always uses map (alternative) +coordinates) +.TP 4 +\fIrasterName \fBtransect\fR ?\fB-count\fI varname\fR? \fIx y x y ...\fR +by default, return list consisting of pairs {value width} along the given line. +If \fB-count\fR is specified, fills dynamic array \fIvarname\fR, indexed +by classes, by total widthes of given value along this line. +.TP 4 +\fIrasterName \fBunused\fR +returns value which is never encountered in this raster. +.TP 4 +\fIrasterName \fBunit\fR ?\fInew-unit\fR? +- returns (or changes) area unit of this raster Unit can be one of +following: \fBundefined\fR,\fBft\fR.\fBm\fR,\fBkm\fR,\fBmile\fR,\fBha\fR,\fBacre\fR. All subsequent count operations would return result in given units. \fBNote:\fR map coordinates are always in meters. +.TP 4 +\fIrasterName \fBxleft\fR ?\fInew value\fR? +- returns (or modifies) left boundary coordinate.\fBNote:\fR it simply modifies +value, without appropriate changes in other limits or cell area value. +.TP 4 +\fIrasterName \fBxright\fR ?\fInew value\fR? +- returns (or modifies) right boundary coordinate. +.TP 4 +\fIrasterName \fBybottom\fR ?\fInew value\fR? +- returns (or modifies) bottom boundary coordinate. +.TP 4 +\fIrasterName \fBytop\fR ?\fInew value\fR? +- returns (or modifies) left boundary coordinate. +.SH RECLASS SYNTAX + +Syntax of reclass syntax is inherited from EPPL7. General form of reclass +statement is line, terminated by newline (\fBNote:\fR trailing newline is +obligatory), which consist of new value and list of old (base) values. New +value separated from list by equal sign. List of old values can contain +individual values and ranges, which are two values, separated by colon. + +.TP 4 +Example +1=1:10 20 +.PP +means, that all values from one to ten and value 20 should be reclassed into +1. + +Set of statements can contain arbitrary number of lines, same value can occur +on left side of several lines. If some value occur on right side more than +once, last occurence have precedence. diff --git a/man/reclass.1 b/man/reclass.1 new file mode 100644 index 0000000..a07ac59 --- /dev/null +++ b/man/reclass.1 @@ -0,0 +1,92 @@ +.TH RECLASS 1 "Version 1.0" "Environmental planning utilities" "EPU User manual".SH NAME +reclass1 \- Change classes of given EPPL7 data file +.SH SYNOPSIS +.B reclass1 [ +.I-v +] [ +.I-f +reclass_file] [ +.I -o +output_file] file +.SH DESCRIPTION +Applies given set of reclass statements to +.B epp +file. Reclass statements have simular syntax to DOS version of EPPL7 and +may be read from +.I stdin +(both from terminal or pipe) and from file. +.PP +By default, creates file named +.I reclass.out.epp +in current directory, but this behavoir can be overriden by +.I -o +option. +.PP +This version can perform only +.B one-way +reclass. +For multy-file reclass use +.BR intable (1) +instead. +.PP +Output file is created as 16-bit and if after reclass it would contain +only classes less than 255, it would be converted into 8-bit. +.PP +If offsite value of old file appears in right side of any reclass statement, +offsite value of new file would be from left side of this statement. + + + +.SH OPTIONS +.TP 8 +.B --help +\- display brief usage message and exit successifully +.TP 8 +.B --version +\- display version information and exit successifully +.TP 8 +.B -v +\- verbose. Display number of rows processed during reclass. +.TP 8 +.BR -f " reclass_file" +\- read reclass statements from given file, instead of +.B stdin +.TP 8 +.BR -o " output_file" +\- write result into given file, instead of +.B reclass.out.epp. +Suffix .epp would be substituted, if absent. + +.SH RECLASS STATEMENT SYNTAX + +Set of reclass statements consists of zero or more lines, +each of which has following structure: +.PP +new_class +.B = +list of old classes +.PP + +New class is number in range 0-65535. +List of old classes is space separated list of classes (numbers) +and ranges. Range is two numbers, separated by colon. First of them +must be less then second, or this range would have no effect. +.PP +If one old class occurs in several statements, only last occurence +would take effect, so it is possible to write: +.PP +1=1:255 +.PP +2=2 +.PP +3=12 +.PP +to reclass all classes between 1 and 255, exept 2 and 12 to 1 and reclass +12 to 3. + +.SH "SEE ALSO" +.BR eheader (1), cluster (1), rescale (1), outtab (1), intable (1) + +.SH "AUTHOR" + +Victor B. Wagner, SoftWeyr. diff --git a/man/window.1 b/man/window.1 new file mode 100644 index 0000000..2885ea5 --- /dev/null +++ b/man/window.1 @@ -0,0 +1,47 @@ +.TH WINDOW 1 "Version 1.0" "EPU" "EPU user manual" +.SH NAME +window \- cuts a portion of epp file +.SH SYNOPSIS +.B window +[-a%] [-o output_file] input_file fr lr fc lc +.SH DESCRIPTION + +Window creates new +.IR epp -file +with given limits. If new limits exceeds limits of old file, this areas +would be filled by +.I offsite +value. +.PP +By default limits are given in rows/columns, but with +.I -a +option you may use alternate coordinates. +.PP +Output file would always be properly aligned with input. +.SH OPTIONS +.TP 8 +.B --help +displays brief usage information. +.TP 8 +.B --version +displays version number +.TP 8 +.B -% +Displays percentage of processed lines in file. +.TP 8 +.BI -o " file " +gives the name for output file. Defaults to +.I window.out.epp +.TP 8 +.B -a +specifies that limits are given in alternate coordinates. +.SH SEE ALSO +.BR mosaic (1), eheader (1) + +.SH AUTHOR + +Victor B. Wagner + +.SH BUGS + +??? diff --git a/pkgIndex.tcl b/pkgIndex.tcl new file mode 100644 index 0000000..8284669 --- /dev/null +++ b/pkgIndex.tcl @@ -0,0 +1 @@ +package ifneeded Fgis 1.0 "package require Tk; [list load [file join $dir fgis.so] Fgis]" diff --git a/symbols/alpha10.sym b/symbols/alpha10.sym new file mode 100644 index 0000000..2b2cde2 --- /dev/null +++ b/symbols/alpha10.sym @@ -0,0 +1,148 @@ +-10 -10 79/11/07.ALPHANUMERIC NOT MODIFIED WITH TONES + 1 0018003C00660066007E007E006600E700000000 + 2 00FC007E0066007C00660066007E00FC00000000 + 3 003C007E0067006000600067007E003C00000000 + 4 00FC007E0066006600660066007E00FC00000000 + 5 00FE007E0062007800780062007E00FE00000000 + 6 00FE007E0062007800780060006000F000000000 + 7 003C007E00670060006F0066007E003C00000000 + 8 00E700660066007E007E0066006600E700000000 + 9 003C001800180018001800180018003C00000000 + 10 000F00060006000600060066007E003C00000000 + 11 00E70066006C0078007C0066006600E700000000 + 12 00F000600060006000600062007E00FE00000000 + 13 01C700EE00FE00BA00D600C600C601C700000000 + 14 00C700660076007E007E006E006600E300000000 + 15 003C007E0066006600660066007E003C00000000 + 16 00FC007E00660066007E007C006000F000000000 + 17 003C007E006600660066006C007E003600000000 + 18 00FC007E00660066007C007E006600E700000000 + 19 003C007E00620078001E0046007E003C00000000 + 20 00FF00FF00990018001800180018003C00000000 + 21 00E700660066006600660066007E003C00000000 + 22 00E7006600660066003C003C0018001800000000 + 23 01C700C600D600D600FE007C006C006C00000000 + 24 00E700660024001800180024006600E700000000 + 25 00E70066007E003C001800180018003C00000000 + 26 00FE00FE008C00180030006200FE00FE00000000 + 27 0018003C0066006600660066003C001800000000 + 28 0018003800380018001800180018003C00000000 + 29 003C007E00660006003C0060007E007E00000000 + 30 003C007E0066000C000E0066007E003C00000000 + 31 000C001C003C006400E400FC000C001E00000000 + 32 007E007E0060007C00060066007E003C00000000 + 33 003C007E0060007C00660066007E003C00000000 + 34 007E007E0046000C000C000C000C000C00000000 + 35 003C007E0066003C00660066007E003C00000000 + 36 003C007E00660066003E0006007E003C00000000 + 37 000000180018007E007E00180018000000000000 + 38 0000000000000000007E007E0000000000000000 + 39 000000920054003800EE00380054009200000000 + 40 00060006000C0018001800300060006000000000 + 41 000C001C0038003000300038001C000C00000000 + 42 00300038001C000C000C001C0038003000000000 + 43 0008001C002A0028001C000A002A001C00080000 + 44 0000007E007E00000000007E007E000000000000 + 46 00000000000000000000001C0014001C000C0000 + 47 0000000000000000000000000018001800000000 + 48 01FF01FF01FF01FF01FF01FF01FF01FF01FF0000 + 49 007C007C0060006000600060007C007C00000000 + 50 007C007C000C000C000C000C007C007C00000000 + 51 0000001800180000000000180018000000000000 + 52 0004007E007E00080010007E007E002000000000 + 53 00000008000C007E006C00080000000000000000 + 54 000000000000000003FF03FF0000000000000000 + 55 0030003000300030003000300030003000300030 + 56 0008001C003E0008000800080008000000000000 + 57 0008000800080008003E001C0008000000000000 + 58 00000004000C001800300018000C000400000000 + 59 0000002000300018000C00180030002000000000 + 60 0030003000300030003F003F0000000000000000 + 61 003000300030003003F003F00000000000000000 + 62 0000000000000000003F003F0030003000300030 + 63 000000000000000003F003F00030003000300030 + 64 0000000000200050008800440028001000000000 + 65 0000000000780084010201020084007800000000 + 66 0000003000480084010201020084004800300000 + 67 00000030004800B4014A014A00B4004800300000 + 68 0000003000FC00AC01C6018E00D400FC00300000 + 69 000000FC00FC00CC01A6019600CC00FC00FC0000 + 70 000000FC00FC00FC01FE01FE00FC00FC00FC0000 + 71 0000000000100000008000040000002000000000 + 72 0000013200000000013201320000000001320000 + 73 000001FE01FE018601B601B6018601FE01FE0000 + 74 0092016D016D0092016D016D0092016D016D0000 + 75 01FF0000000001FF0000000001FF000000000000 + 76 0000000000440000000000000044000000000000 + 77 01FF01FF018301BB01AB01BB018301FF01FF0000 + 78 01FF01FF0193019301FF0193019301FF01FF0000 + 79 011100AA004400000000011100AA004400000000 + 80 0000000C00E00000000F000000600000001C0000 + 81 01C701C701C700380038003801C701C701C70000 + 82 0018003C0066006600660066003C001800000000 + 83 0000000000000010000000000000000000000000 + 84 0000000000000030004800480030000000000000 + 85 0010000000000028008200280000000000100000 + 86 018300100000003800AA00380000001001830000 + 87 018300100010003800EE00380010001001830000 + 88 019300100000003801FF00380000001001930000 + 89 019301930010003801FF00380010019301930000 + 90 01FF01FF0111013901FF0139011101FF01FF0000 + 91 01FF01FF019301BB01FF01BB019301FF01FF0000 + 92 021F03EF03FF02FF03FE019B03FF03FF02FE01BF + 93 03FF02FD03FF03FF03EF03FF03FF03FF02FD03FF + 94 003F00110011001101FF01FF006000600060007C + 95 0048004800480FFF004800480FFF004800480048 + 96 007800CC01860303023102310303018600CC0078 + 97 00E700A600EC000800100037006500E700000000 + 98 0000000000240000000000240000000000000000 + 99 000000100010003800EE00380010001000000000 +100 0038004400820101010100010082004400380000 +101 0038004400820129010101290082004400380000 +102 003800540082011101AB01110082005400380000 +103 0038004400D601290155012900D6004400380000 +104 0038005400EE015501BB015500EE005400380000 +105 0038007C00FE01FF01FF01FF00FE007C00380000 +106 002C00D200A6004C00D200340030003000780000 +107 00B8007C00F800FC00FE007800B0003000780000 +108 0000000000000000003000300000000000000000 +109 02AA0155015502AA0155015502AA0155015502AA +110 01FF000001FF000001FF000001FF000001FF0000 +111 011100AA004400000000011100AA004400000000 +112 00C1000C00600100001C00C00006017100000000 +113 001000A800C400EE0129012901E9010901FF0000 +114 0000000000440000000000000000000000000000 +115 0101008200440028001000AA01C701EF01C70000 +116 0000008200000028000000280000008200000000 +117 01EF0129012901EF000001EF0129012901EF0000 +118 000002AA00000155000002AA00000155000002AA +119 0092024900920249009202490092024900920249 +120 015502AA015502AA015502AA015502AA015502AA +121 03BB02EE03BB02FE03FB02FE03FB02FE03BB02EE +122 03FF03FF03FF03FF03FF03FF03FF03FF03FF03FF +123 0000010200000000001000000000000001020000 +124 0000000000000020005000A80154000000000000 +125 010000000000000000000000000A000201000000 +126 000000200020002001FE00200020002000200000 +127 0000000000000030007800FC01FE000000000000 +128 0140004000410190000000270002000000400200 +129 00000000000000F800F800F800F800F800000000 +130 000000300030003001FE01FE0030003000300030 +131 0229004A0100000601240025001B011100080002 +132 02010302018600CC00780030007800CC01860303 +133 000001FE01FE003000300030003001FE01FE0000 +134 0053004C034000CB014603040223020202590090 +135 0201013200B4007801FE01FE007800B401320201 +136 00200020002000AA01FE03FE03FE01FC007C007C +137 0293023A00880058037A00EE0382018A00E401A6 +138 01FE02CD034B0387020102010387034B02CD01FE +139 000001FE01FE01FE01CE01CE01FE01FE01FE0000 +140 034A02EB00C103D6013B018C039701E3027A0231 +141 01FE00FD02790333038703CF03870333027900FC +142 03FF03CF03CF03CF0201020103CF03CF03CF03CF +143 01B5019302CF02BD01FC03F7001D03BE034F0361 +144 03FF03FF03FF0307030703070307030703FF03FF +145 03FF03FF0303037B037B037B037B030303FF03FF +146 03EE03DE02BF03BB017F037E021A02FF00F102FF +147 03FF03DF03DF03DF020103DF03DF03DF03DF03FF +148 03FF03FF03FF03DF03AF035702AB03FF03FF03FF diff --git a/symbols/alpha6.sym b/symbols/alpha6.sym new file mode 100644 index 0000000..fdb01e9 --- /dev/null +++ b/symbols/alpha6.sym @@ -0,0 +1,81 @@ +-6 -6 79/11/07.ALPHANUMMERICS (MODIFIED) WITH TONES + 1 00C 012 01E 012 012 000 + 2 01C 012 01C 012 01C 000 + 3 00E 010 010 010 00E 000 + 4 01C 012 012 012 01C 000 + 5 01E 010 01C 010 01E 000 + 6 01E 010 01C 010 010 000 + 7 00E 010 016 012 00E 000 + 8 012 012 01E 012 012 000 + 9 00E 004 004 004 00E 000 + 10 00E 004 004 014 008 000 + 11 012 014 018 014 012 000 + 12 010 010 010 010 01E 000 + 13 011 01B 015 011 011 000 + 14 011 019 015 013 011 000 + 15 00C 012 012 012 00C 000 + 16 01C 012 01C 010 010 000 + 17 00C 012 012 014 00A 000 + 18 01C 012 01C 012 012 000 + 19 00E 010 00C 002 01C 000 + 20 01F 004 004 004 004 000 + 21 012 012 012 012 00C 000 + 22 011 011 011 00A 004 000 + 23 011 011 015 015 00A 000 + 24 011 00A 004 00A 011 000 + 25 011 00A 004 004 004 000 + 26 01F 002 004 008 01F 000 + 27 00E 00A 00A 00A 00E 000 + 28 004 00C 004 004 00E 000 + 29 00C 002 00C 008 00E 000 + 30 00E 002 004 002 00E 000 + 31 00A 00A 00E 002 002 000 + 32 00E 008 00C 002 00C 000 + 33 008 008 00E 00A 00E 000 + 34 00E 002 002 002 002 000 + 35 00E 00A 00E 00A 00E 000 + 36 00E 00A 00E 002 002 000 + 37 004 004 01F 004 004 000 + 38 000 000 01E 000 000 000 + 39 004 00A 004 00A 004 000 + 40 002 002 004 008 008 000 + 41 002 004 004 004 002 000 + 42 008 004 004 004 008 000 + 43 00F 014 00E 005 01E 000 + 44 000 01E 000 01E 000 000 + 46 000 000 000 00C 00C 004 + 47 000 000 000 00C 00C 000 + 48 03F 03F 03F 03F 03F 03F + 49 00E 008 008 008 00E 000 + 50 01C 004 004 004 01C 000 + 51 00C 00C 000 00C 00C 000 + 52 002 01F 004 01F 008 000 + 53 007 007 007 007 007 007 + 54 007 007 00F 00F 007 007 + 55 000 000 004 006 007 007 + 56 004 00E 015 004 004 000 + 57 000 000 000 03F 03F 03F + 58 000 000 000 020 038 03E + 59 038 030 020 000 000 000 + 60 03F 03F 03F 03E 03C 038 + 61 03F 03C 038 030 030 030 + 62 030 030 030 038 03E 03F + 63 020 030 038 03C 03E 03E + 64 00D 013 00A 014 013 000 + 65 00A 00A 00A 00A 000 000 + 66 000 015 00A 000 000 000 + 67 000 003 000 00C 000 000 + 68 011 015 01F 015 011 000 + 69 01F 015 01B 015 01F 000 + 70 000 00A 000 00A 000 000 + 71 01F 011 015 011 01F 000 + 72 01F 01F 01F 01F 01F 000 + 73 000 03F 000 000 03F 000 + 74 012 012 012 012 012 012 + 75 008 010 020 001 002 004 + 76 004 002 001 020 010 008 + 77 03F 03F 03F 03F 03F 03F + 78 02A 015 02A 015 02A 015 + 79 02A 000 015 000 02A 000 + 97 009 002 004 009 000 000 + 98 000 00A 000 00A 000 000 diff --git a/symbols/digit25.sym b/symbols/digit25.sym new file mode 100644 index 0000000..78acbc6 --- /dev/null +++ b/symbols/digit25.sym @@ -0,0 +1,405 @@ +-25 -25 79/11/27. DOUBLE DIGIT NUMBERS IN BOXES + 1 01FFFFFF010000010100000101000001010000010100000101000061010000E1 + 1 010001E1010001E1010000610100006101000061010000610100006101000061 + 1 01000061010001F1010001F10100000101000001010000010100000101000001 + 1 01FFFFFF + 2 01FFFFFF0100000101000001010000010100000101000001010001F9010003FD + 2 0100038D0100030D0100030D0100001D0100003D01000079010001E1010003C1 + 2 01000381010003FD010003FD0100000101000001010000010100000101000001 + 2 01FFFFFF + 3 01FFFFFF0100000101000001010000010100000101000001010001F9010003FD + 3 0100030D0100030D0100001D0100007901000071010000790100001D0100030D + 3 0100030D010003FD010000F90100000101000001010000010100000101000001 + 3 01FFFFFF + 4 01FFFFFF01000001010000010100000101000001010000010100001D0100003D + 4 0100006D010000CD0100018D0100010D010003FD010003FD0100000D0100000D + 4 0100000D0100000D0100000D0100000101000001010000010100000101000001 + 4 01FFFFFF + 5 01FFFFFF0100000101000001010000010100000101000001010003FD010003FD + 5 0100030D0100030101000371010003F90100030D0100000D0100000D0100030D + 5 0100031D010001F9010000F10100000101000001010000010100000101000001 + 5 01FFFFFF + 6 01FFFFFF0100000101000001010000010100000101000001010000F9010001FD + 6 0100038D0100030D0100030101000371010003F90100039D0100030D0100030D + 6 0100030D010003FD010001F90100000101000001010000010100000101000001 + 6 01FFFFFF + 7 01FFFFFF0100000101000001010000010100000101000001010003FD010003FD + 7 0100030D0100001901000019010000310100006101000061010000C1010000C1 + 7 0100018101000181010001810100000101000001010000010100000101000001 + 7 01FFFFFF + 8 01FFFFFF0100000101000001010000010100000101000001010001F9010003FD + 8 0100030D0100030D0100030D010001F9010000F1010001990100030D0100030D + 8 0100030D010003FD010001F90100000101000001010000010100000101000001 + 8 01FFFFFF + 9 01FFFFFF0100000101000001010000010100000101000001010001F9010003FD + 9 0100030D0100030D0100030D0100039D010001FD010000ED0100000D0100000D + 9 0100030D010003F9010001F10100000101000001010000010100000101000001 + 9 01FFFFFF + 10 01FFFFFF0100000101000001010000010100000101000001010300F1010701F9 + 10 010F039D010F030D0103030D0103030D0103030D0103030D0103030D0103030D + 10 0103039D010F81F9010F80F10100000101000001010000010100000101000001 + 10 01FFFFFF + 11 01FFFFFF010000010100000101000001010000010100000101030061010700E1 + 11 010F01E1010F01E1010300610103006101030061010300610103006101030061 + 11 01030061010F81F1010F81F10100000101000001010000010100000101000001 + 11 01FFFFFF + 12 01FFFFFF0100000101000001010000010100000101000001010301F9010703FD + 12 010F038D010F030D0103030D0103001D0103003D01030079010301E1010303C1 + 12 01030381010F83FD010F83FD0100000101000001010000010100000101000001 + 12 01FFFFFF + 13 01FFFFFF0100000101000001010000010100000101000001010301F9010703FD + 13 010F030D010F030D0103001D0103007901030071010300790103001D0103030D + 13 0103030D010F83FD010F80F90100000101000001010000010100000101000001 + 13 01FFFFFF + 14 01FFFFFF01000001010000010100000101000001010000010103001D0107003D + 14 010F006D010F00CD0103018D0103030D010303FD010303FD0103000D0103000D + 14 0103000D010F800D010F800D0100000101000001010000010100000101000001 + 14 01FFFFFF + 15 01FFFFFF0100000101000001010000010100000101000001010303FD010703FD + 15 010F030D010F030101030371010303F90103030D0103000D0103000D0103030D + 15 0103031D010F81F9010F80F10100000101000001010000010100000101000001 + 15 01FFFFFF + 16 01FFFFFF0100000101000001010000010100000101000001010300F9010701FD + 16 010F038D010F030D0103030101030371010303F90103039D0103030D0103030D + 16 0103030D010F83FD010F81F90100000101000001010000010100000101000001 + 16 01FFFFFF + 17 01FFFFFF0100000101000001010000010100000101000001010303FD010703FD + 17 010F030D010F001901030019010300310103006101030061010300C1010300C1 + 17 01030181010F8181010F81810100000101000001010000010100000101000001 + 17 01FFFFFF + 18 01FFFFFF0100000101000001010000010100000101000001010301F9010703FD + 18 010F030D010F030D0103030D010301F9010300F1010301990103030D0103030D + 18 0103030D010F83FD010F81F90100000101000001010000010100000101000001 + 18 01FFFFFF + 19 01FFFFFF0100000101000001010000010100000101000001010301F9010703FD + 19 010F030D010F030D0103030D0103039D010301FD010300ED0103000D0103000D + 19 0103030D010F83F9010F81F10100000101000001010000010100000101000001 + 19 01FFFFFF + 20 01FFFFFF0100000101000001010000010100000101000001010FC0F1011FE1F9 + 20 011C639D0118630D0118630D0100E30D0101E30D0103C30D010F030D011E030D + 20 011C239D011FE1F9011FE0F10100000101000001010000010100000101000001 + 20 01FFFFFF + 21 01FFFFFF0100000101000001010000010100000101000001010FC061011FE0E1 + 21 011C61E1011861E1011860610100E0610101E0610103C061010F0061011E0061 + 21 011C2061011FE1F1011FE1F10100000101000001010000010100000101000001 + 21 01FFFFFF + 22 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 22 011C638D0118630D0118630D0100E01D0101E03D0103C079010F01E1011E03C1 + 22 011C2381011FE3FD011FE3FD0100000101000001010000010100000101000001 + 22 01FFFFFF + 23 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 23 011C630D0118630D0118601D0100E0790101E0710103C079010F001D011E030D + 23 011C230D011FE3FD011FE0F90100000101000001010000010100000101000001 + 23 01FFFFFF + 24 01FFFFFF0100000101000001010000010100000101000001010FC01D011FE03D + 24 011C606D011860CD0118618D0100E30D0101E3FD0103C3FD010F000D011E000D + 24 011C200D011FE00D011FE00D0100000101000001010000010100000101000001 + 24 01FFFFFF + 25 01FFFFFF0100000101000001010000010100000101000001010FC3FD011FE3FD + 25 011C630D01186301011863710100E3F90101E30D0103C00D010F000D011E030D + 25 011C231D011FE1F9011FE0F10100000101000001010000010100000101000001 + 25 01FFFFFF + 26 01FFFFFF0100000101000001010000010100000101000001010FC0F9011FE1FD + 26 011C638D0118630D011863010100E3710101E3F90103C39D010F030D011E030D + 26 011C230D011FE3FD011FE1F90100000101000001010000010100000101000001 + 26 01FFFFFF + 27 01FFFFFF0100000101000001010000010100000101000001010FC3FD011FE3FD + 27 011C630D01186019011860190100E0310101E0610103C061010F00C1011E00C1 + 27 011C2181011FE181011FE1810100000101000001010000010100000101000001 + 27 01FFFFFF + 28 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 28 011C630D0118630D0118630D0100E1F90101E0F10103C199010F030D011E030D + 28 011C230D011FE3FD011FE1F90100000101000001010000010100000101000001 + 28 01FFFFFF + 29 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 29 011C630D0118630D0118630D0100E39D0101E1FD0103C0ED010F000D011E000D + 29 011C230D011FE3F9011FE1F10100000101000001010000010100000101000001 + 29 01FFFFFF + 30 01FFFFFF0100000101000001010000010100000101000001010FC0F1011FE1F9 + 30 0118639D0118630D0100E30D0103C30D0103830D0103C30D0100E30D0118630D + 30 0118639D011FE1F90107C0F10100000101000001010000010100000101000001 + 30 01FFFFFF + 31 01FFFFFF0100000101000001010000010100000101000001010FC061011FE0E1 + 31 011861E1011861E10100E0610103C061010380610103C0610100E06101186061 + 31 01186061011FE1F10107C1F10100000101000001010000010100000101000001 + 31 01FFFFFF + 32 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 32 0118638D0118630D0100E30D0103401D0103803D0103C0790100E1E1011863C1 + 32 01186381011FE3FD0107C3FD0100000101000001010000010100000101000001 + 32 01FFFFFF + 33 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 33 0118630D0118630D0100E01D0103C079010380710103C0790100E01D0118630D + 33 0118630D191FE3FD0107C0F90100000101000001010000010100000101000001 + 33 01FFFFFF + 34 01FFFFFF0100000101000001010000010100000101000001010FC01D011FE03D + 34 0118606D011860CD0100E18D0103C30D010383FD0103C3FD0100E00D0118600D + 34 0118600D011FE00D0107C00D0100000101000001010000010100000101000001 + 34 01FFFFFF + 35 01FFFFFF0100000101000001010000010100000101000001010FC3FD011FE3FD + 35 0118630D011863010100E3710103C3F90103830D0103C00D0100E00D0118630D + 35 0118631D011FE1F90107C0F10100000101000001010000010100000101000001 + 35 01FFFFFF + 36 01FFFFFF0100000101000001010000010100000101000001010FC0F9011FE1FD + 36 0118638D0118630D0100E3010103C371010383F90103C39D0100E30D0118630D + 36 0118630D011FE3FD0107C1F90100000101000001010000010100000101000001 + 36 01FFFFFF + 37 01FFFFFF0100000101000001010000010100000101000001010FC3FD011FE3FD + 37 0118630D011860190100E0190103C031010380610103C0610100E0C1011860C1 + 37 01186181011FE1810107C1810100000101000001010000010100000101000001 + 37 01FFFFFF + 38 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 38 0118630D0118630D0100E30D0103C1F9010380F10103C1990100E30D0118630D + 38 0118630D011FE3FD0107C1F90100000101000001010000010100000101000001 + 38 01FFFFFF + 39 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 39 0118630D0118630D0100E30D0103C39D010381FD0103C0ED0100E00D0118600D + 39 0118630D011FE3F90107C1F10100000101000001010000010100000101000001 + 39 01FFFFFF + 40 01FFFFFF01000001010000010100000101000001010000010100E0F10101E1F9 + 40 0103639D0106630D010C630D0118630D191FE30D011FE30D0100630D0100630D + 40 0100639D010061F9010060F10100000101000001010000010100000101000001 + 40 01FFFFFF + 41 01FFFFFF01000001010000010100000101000001010000010100E0610101E0E1 + 41 010361E1010661E1010C606101186061011FE061011FE0610100606101006061 + 41 01006061010061F1010061F10100000101000001010000010100000101000001 + 41 01FFFFFF + 42 01FFFFFF01000001010000010100000101000001010000010100E1F90101E3FD + 42 0103638D0106630D010C630D0118601D011FE03D011FE079010061E1010063C1 + 42 01006381010063FD010063FD0100000101000001010000010100000101000001 + 42 01FFFFFF + 43 01FFFFFF01000001010000010100000101000001010000010100E1F90101E3FD + 43 0103630D0106630D010C601D01186079011FE071011FE0790100601D0100630D + 43 0100630D010063FD010060F90100000101000001010000010100000101000001 + 43 01FFFFFF + 44 01FFFFFF01000001010000010100000101000001010000010100E01D0101E03D + 44 0103606D010660CD010C618D0118630D011FE3FD011FE3FD0100600D0100600D + 44 0100600D0100600D0100600D0100000101000001010000010100000101000001 + 44 01FFFFFF + 45 01FFFFFF01000001010000010100000101000001010000010100E3FD0101E1FD + 45 0103630D01066301010C6371011863F9011FE30D011FE00D0100600D0100630D + 45 0100631D010061F9010060F10100000101000001010000010100000101000001 + 45 01FFFFFF + 46 01FFFFFF01000001010000010100000101000001010000010100E0F90101E1FD + 46 0103638D0106630D010C630101186371011FE3F9011FE39D0100630D0100630D + 46 0100630D010063FD010061F90100000101000001010000010100000101000001 + 46 01FFFFFF + 47 01FFFFFF01000001010000010100000101000001010000010100E3FD0101E3FD + 47 0103630D01066019010C601901186031011FE061011FE061010060C1010060C1 + 47 0100618101006181010061810100000101000001010000010100000101000001 + 47 01FFFFFF + 48 01FFFFFF01000001010000010100000101000001010000010100E1F90101E3FD + 48 0103630D0106630D010C630D011861F9011FE0F1011FB1990100630D0100630D + 48 0100630D010063FD010061F90100000101000001010000010100000101000001 + 48 01FFFFFF + 49 01FFFFFF01000001010000010100000101000001010000010100E1F90101E3FD + 49 0103630D0106630D010C630D0118639D011FE1FD011FE0ED0100600D0100600D + 49 0100630D010063F9010061F10100000101000001010000010100000101000001 + 49 01FFFFFF + 50 01FFFFFF0100000101000001010000010100000101000001011FE0F1011FE1F9 + 50 0118639D0118030D011B830D011FC30D0118630D0100630D0100630D0118630D + 50 0118E39D010FC1F9010780F10100000101000001010000010100000101000001 + 50 01FFFFFF + 51 01FFFFFF0100000101000001010000010100000101000001011FE061011FE0E1 + 51 011861E1011801E1011B8061011FC06101186061010060610100606101186061 + 51 0118E061010FC1F1010781F10100000101000001010000010100000101000001 + 51 01FFFFFF + 52 01FFFFFF0100000101000001010000010100000101000001011FE1F9011FE3FD + 52 0118638D0118030D011B830D011FC01D0118603D01006079010061E1011863C1 + 52 0118E381010FC3FD010783FD0100000101000001010000010100000101000001 + 52 01FFFFFF + 53 01FFFFFF0100000101000001010000010100000101000001011FE1F9011FE3FD + 53 0118630D0118030D010F801D011FC07901186071010060790100601D0118630D + 53 0118E30D010FC3FD010780F90100000101000001010000010100000101000001 + 53 01FFFFFF + 54 01FFFFFF0100000101000001010000010100000101000001011FE01D011FE03D + 54 0118606D011800CD011B818D011FC30D011863FD010063FD0100600D0118600D + 54 0118E00D010FC00D0107800D0100000101000001010000010100000101000001 + 54 01FFFFFF + 55 01FFFFFF0100000101000001010000010100000101000001011FE3FD011FE3FD + 55 0118630D01180301011B8371011FC3F90118630D0100600D0100600D0118E30D + 55 0118E31D010FC1F9010780F10100000101000001010000010100000101000001 + 55 01FFFFFF + 56 01FFFFFF0100000101000001010000010100000101000001011FE0F9011FE1FD + 56 0118638D0118030D011B8301011FC371011863F90100639D0100630D0118630D + 56 0118E30D010FC3FD010781F90100000001000001010000010100000101000001 + 56 01FFFFFF + 57 01FFFFFF0100000101000001010000010100000101000001011FE3FD011FE3FD + 57 0118630D01180019011B8019011FC0310118606101006061010060C1011860C1 + 57 0118E181010FC181010781810100000101000001010000010100000101000001 + 57 01FFFFFF + 58 01FFFFFF0100000101000001010000010100000101000001011FE1F9011FE3FD + 58 0118630D0118030D011B830D011FC1F9011860F1010061990100630D0118630D + 58 0118E30D010FC3FD010781F90100000101000001010000010100000101000001 + 58 01FFFFFF + 59 01FFFFFF0100000101000001010000010100000101000001011FE1F9011FE3FD + 59 0118630D0118030D011B830D011FC39D011861FD010060ED0100600D0118600D + 59 0118E30D010FC3F9010781F10100000101000001010000010100000101000001 + 59 01FFFFFF + 60 01FFFFFF01000001010000010100000101000001010000010107C0F1010FE1F9 + 60 011C639D0118630D0118030D011B830D011FC30D011CE30D0118630D0118630D + 60 0118639D011FE1F9010FC0F10100000101000001010000010100000101000001 + 60 01FFFFFF + 61 01FFFFFF01000001010000010100000101000001010000010107C061010FE0E1 + 61 011C61E1011861E101180061011B8061011FC061011CE0610118606101186061 + 61 01186061011FE1F1010FC1F10100000101000001010000010100000101000001 + 61 01FFFFFF + 62 01FFFFFF01000001010000010100000101000001010000010107C1F9010FE3FD + 62 011C638D0118630D0118030D011B801D011FC03D011CE079011861E1011863C1 + 62 01186381011FE3FD010FC3FD0100000101000001010000010100000101000001 + 62 01FFFFFF + 63 01FFFFFF01000001010000010100000801000001010000010107C1F9010FE3FD + 63 011C630D0118630D0118001D011B8079011FC071011CE0790118601D0118630D + 63 0118630D011FE3FD010FC0F90100000101000001010000010100000101000001 + 63 01FFFFFF + 64 01FFFFFF01000001010000010100000101000001010000010107C01D010FE03D + 64 011C606D011860CD0118018D010F830D011FC3FD011CE3FD0118600D0118600D + 64 0118600D011FE00D010FC00D0100000101000001010000010100000101000001 + 64 01FFFFFF + 65 01FFFFFF01000001010000010100000101000001010000010107C3FD010FE3FD + 65 011C630D0118630101180371011B83F9011FC30D011CE00D0118600D0118630D + 65 0118631D011FE1F9010FC0F10100000101000001010000010100000101000001 + 65 01FFFFFF + 66 01FFFFFF01000001010000010100000101000001010000010107C0F9010FE1FD + 66 011C638D0118630D01180301011B8371011FC3F9011CE39D0118630D0118630D + 66 0118630D011FE3FD010FC1F90100000101000001010000010100000101000001 + 66 01FFFFFF + 67 01FFFFFF01000001010000010100000101000001010000010107C3FD010FE3FD + 67 011C630D0118601901180019011B8031011FC061011CE061011860C1011860C1 + 67 01186181011FE181010FC1810100000101000001010000010100000101000001 + 67 01FFFFFF + 68 01FFFFFF01000001010000010100000101000001010000010107C1F9010FE3FD + 68 011C630D0118630D0118030D011B81F9011FC0F1011CE1990118630D0118630D + 68 0118630D011FE3FD010FC1F90100000101000001010000010100000101000001 + 68 01FFFFFF + 69 01FFFFFF01000001010000010100000101000001010000010107C1F9010FE3FD + 69 011C630D0118630D0118030D011B839D011FC1FD011CE0ED0118600D0118600D + 69 0118630D011FE3F9010FC1F10100000101000001010000010100000101000001 + 69 01FFFFFF + 70 01FFFFFF0100000101000001010000010100000101000001011FE0F1011FE1F9 + 70 0118639D0100C30D0100C30D0101830D0103030D0103030D0106030D0106030D + 70 010C039D010C01F9010C00F10100000101000001010000010100000101000001 + 70 01FFFFFF + 71 01FFFFFF0100000101000001010000010100000101000001011FE061011FE0E1 + 71 011861E10100C1E10100C0610101806101030061010300610106006101060061 + 71 010C0061010C01F1010C01F10100000101000001010000010100000101000001 + 71 01FFFFFF + 72 01FFFFFF0100000101000001010000010100000101000001011FE1F9011FE3FD + 72 0118638D0100C30D0100C30D0101801D0103003D01030079010601E1010603C1 + 72 010C0381010C03FD010C03FD0100000101000001010000010100000101000001 + 72 01FFFFFF + 73 01FFFFFF0100000101000001010000010100000101000001011FE1F9011FE3FD + 73 0118630D0100C30D0100C01D0101807901030071010300790106001D0106030D + 73 010C030D010C03FD010C00F90100000101000001010000010100000101000001 + 73 01FFFFFF + 74 01FFFFFF0100000101000001010000010100000101000001011FE01D011FE03D + 74 0118606D0100C0CD0100C18D0101830D010303FD010303FD0106000D0106000D + 74 010C000D010C000D010C000D0100000101000001010000010100000101000001 + 74 01FFFFFF + 75 01FFFFFF0100000101000001010000010100000101000001011FE3FD011FE3FD + 75 0118630D0100C3010100C371010183F90103030D0103000D0106000D0106030D + 75 010C031D010C01F9010C00F10100000101000001010000010100000101000001 + 75 01FFFFFF + 76 01FFFFFF0100000101000001010000010100000101000001011FE0F9011FE1FD + 76 0118638D0100C30D0100C30101018371010303F90103039D0106030D0106030D + 76 010C030D010C03FD010C01F90100000101000001010000010100000101000001 + 76 01FFFFFF + 77 01FFFFFF0100000101000001010000010100000101000001011FE3FD011FE3FD + 77 0118630D0100C0190100C019010180310103006101030061010600C1010600C1 + 77 010C0181010C0181010C01810100000101000001010000010100000101000001 + 77 01FFFFFF + 78 01FFFFFF0100000101000001010000010100000101000001011FE1F9011FE3FD + 78 0118630D0100C30D0100C30D010181F9010300F1010301990106030D0106030D + 78 010C030D010C03FD010C01F90100000101000001010000010100000101000001 + 78 01FFFFFF + 79 01FFFFFF0100000101000001010000010100000101000001011FE1F9011FE3FD + 79 0118630D0100C30D0100C30D0101839D010301FD010300ED0106000D0106000D + 79 010C030D010C03F9010C01F10100000101000001010000010100000101000001 + 79 01FFFFFF + 80 01FFFFFF0100000101000001010000010100000101000001010FC0F1011FE1F9 + 80 0118639D0118630D0118630D010FC30D0107830D010CC30D0118630D0118630D + 80 0118639D011FE1F9010FC0F10100000101000001010000010100000101000001 + 80 01FFFFFF + 81 01FFFFFF0100000101000001010000010100000101000001010FC061011FE0E1 + 81 011861E1011861E101186061010FC06101078061010CC0610118606101186061 + 81 01186061011FE1F1010FC1F10100000101000001010000010100000101000001 + 81 01FFFFFF + 82 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 82 0118638D0118630D0118630D010FC01D0107803D010CC079011861E1011863C1 + 82 01186381011FE3FD010FC3FD0100000101000001010000010100000101000001 + 82 01FFFFFF + 83 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 83 0118630D0118630D0118601D010FC07901078071010CC0790118601D0118630D + 83 0118630D011FE3FD010FC0F90100000101000001010000010100000101000001 + 83 01FFFFFF + 84 01FFFFFF0100000101000001010000010100000101000001010FC01D011FE03D + 84 0118606D011860CD0118618D010FC30D010783FD010CC3FD0118600D0118600D + 84 0118600D011FE00D010FC00D0100000101000001010000010100000101000001 + 84 01FFFFFF + 85 01FFFFFF0100000101000001010000010100000101000001010FC3FD011FE3FD + 85 0118630D0118630101186371010FC3F90107830D010CC00D0118600D0118630D + 85 0118631D011FE1F9010FC0F10100000101000001010000010100000101000001 + 85 01FFFFFF + 86 01FFFFFF0100000101000001010000010100000101000001010FC0F9011FE1FD + 86 0118638D0118630D01186301010FC371010783F9010CC39D0118630D0118630D + 86 0118630D011FE3FD010FC1F90100000101000001010000010100000101000001 + 86 01FFFFFF + 87 01FFFFFF0100000101000001010000010100000101000001010FC3FD011FE3FD + 87 0118630D0118601901186019010FC03101078061010CC061011860C1011860C1 + 87 01186181011FE181010FC1810100000101000001010000010100000101000001 + 87 01FFFFFF + 88 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 88 0118630D0118630D0118630D010FC1F9010780F1010CC1990118630D0118630D + 88 0118630D011FE3FD010FC1F90100000101000001010000010100000101000001 + 88 01FFFFFF + 89 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 89 0118630D0118630D0118630D010FC39D010781FD010CC0ED0118600D0118600D + 89 0118630D011FE3F9010FC1F10100000101000001010000010100000101000001 + 89 01FFFFFF + 90 01FFFFFF0100000101000001010000010100000101000001010FC0F1011FE1F9 + 90 0118639D0118630D0118630D011CE30D010FE30D0107630D0100630D0100630D + 90 0118E39D011FC1F9010F80F10100000101000001010000010100000101000001 + 90 01FFFFFF + 91 01FFFFFF0100000101000001010000010100000101000001010FC061011FE0E1 + 91 011861E1011861E101186061011CE061010FE061010760610100606101006061 + 91 0118E061011FC1F1010F81F10100000101000001010000010100000101000001 + 91 01FFFFFF + 92 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FD3FD + 92 0118638D0118630D0118630D011CE01D010FE03D01076079010061E1010063C1 + 92 0118E381011FC3FD010F83FD0100000101000001010000010100000101000001 + 92 01FFFFFF + 93 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 93 0118630D0118330D0118601D011CE079010FE071010760790100601D0100630D + 93 0118E30D011FC3FD010F80F90100000101000001010000010100000101000001 + 93 01FFFFFF + 94 01FFFFFF0100000101000001010000010100000101000001010FC01D011FE03D + 94 0118606D011860CD0118618D011CE30D010FE3FD010763FD0100600D0100600D + 94 0118E00D011FC00D010F800D0100000101000001010000010100000101000001 + 94 01FFFFFF + 95 01FFFFFF0100000101000001010000010100000101000001010FC3FD011FE3FD + 95 0118630D0118630101186371011CE3F9010FE30D0107600D0100600D0100630D + 95 0118E31D011FC1F9010F80F90100000101000001010000010100000101000001 + 95 01FFFFFF + 96 01FFFFFF0100000101000001010000010100000101000001010FC0F9011FE1FD + 96 0118638D0118630D01186301011CE371010FE3F90107639D0100630D0100630D + 96 0118E30D011FC3FD010F81F90100000101000001010000010100000101000001 + 96 01FFFFFF + 97 01FFFFFF0100000101000001010000010100000101000001010FC3FD011FE3FD + 97 0118630D0118601901186019011CE031010FE06101076061010060C1010060C1 + 97 0118E181011FC181010F81810100000101000001010000010100000101000001 + 97 01FFFFFF + 98 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FE3FD + 98 0118630D0118630D0118630D011CE1F9010FE0F1010761990100630D0100630D + 98 0118E30D011FC3FD010F81F90100000101000001010000010100000101000001 + 98 01FFFFFF + 99 01FFFFFF0100000101000001010000010100000101000001010FC1F9011FC3FD + 99 0118630D0118630D0118630D011CE39D010FE1FD010760ED0100600D0100600D + 99 0118E30D011FC3F9010F81F10100000101000001010000010100000101000001 + 99 01FFFFFF +100 0000380000003800000038000000380000003800000038000000380000003800 +100 0000380000003800000038000000380000003800000038000000380000003800 +100 0000380000003800000038000000380000003800000038000000380000003800 +100 00003800 +101 0000000000000000000000000000000000000000000000000000000000000000 +101 0000000000000000000000003FFFFFFF3FFFFFFF3FFFFFFF0000000000000000 +101 0000000000000000000000000000000000000000000000000000000000000000 +101 00000000 diff --git a/symbols/digit6.sym b/symbols/digit6.sym new file mode 100644 index 0000000..b8a5588 --- /dev/null +++ b/symbols/digit6.sym @@ -0,0 +1,22 @@ + -6 -6 79/11/07.OPTICALLY WEIGHTED NUMBERS LIGHT TO DARK + 1 004 004 004 004 004 000 + 2 008 004 008 008 00C 000 + 3 00C 004 008 004 00C 000 + 4 008 00A 00E 002 002 000 + 5 00C 008 00C 002 00E 000 + 6 008 008 00E 00A 00E 000 + 7 00E 006 00C 00C 00C 000 + 8 00E 00A 00E 00A 00C 000 + 9 00E 00A 00E 006 00E 000 + 10 00E 00E 00A 00E 00E 000 + 11 018 01C 01C 01C 01E 000 + 12 01C 01A 01C 01C 01E 000 + 13 01E 01A 01C 01A 01E 000 + 14 01C 01E 01E 01E 01C 000 + 15 01E 01C 01E 01E 01E 000 + 16 01C 01C 01F 01D 01F 000 + 17 01F 01D 01E 01E 01E 000 + 18 01F 01D 01F 01D 01E 000 + 19 01F 01D 01F 01B 01F 000 + 20 01F 01F 01D 01F 01F 000 + 21 01F 01F 01F 01F 01F 000 diff --git a/symbols/fort10.sym b/symbols/fort10.sym new file mode 100644 index 0000000..454c62b --- /dev/null +++ b/symbols/fort10.sym @@ -0,0 +1,12 @@ +-10 -10 79/11/16.FOREST COVER (V23) + 1 001000380038007C007C00FE00FE01FF00380000 + 2 0010001000380054009200380054019300100000 + 3 002C00FE00FE007C00FE00340030003000780000 + 4 002C00D200A6004C00D200340030003000780000 + 5 007C00FE01FF01FF01FF00AA00280028007C0000 + 6 001000A80146010200BC00500010001000380000 + 7 031100AA004400000000031100AA004400000000 + 77 03FF0303028502490231023102490285030303FF + 99 031100AA004400000000031100AA004400000000 +100 03FF03FF03FF03FF03FF03FF03FF03FF03FF03FF + \ No newline at end of file diff --git a/symbols/gray5.sym b/symbols/gray5.sym new file mode 100644 index 0000000..bcf1d01 --- /dev/null +++ b/symbols/gray5.sym @@ -0,0 +1,27 @@ + -5 -5 79/11/07.GRAY SCALE LIGHT TO DARK + 1 000 000 004 000 000 + 2 000 004 000 004 000 + 3 004 000 004 000 004 + 4 000 00A 000 00A 000 + 5 000 00A 004 00A 000 + 6 004 00A 000 00A 004 + 7 004 00A 004 00A 004 + 8 011 004 00A 004 011 + 9 004 00A 015 00A 004 + 10 00A 011 00A 011 00A + 11 011 00A 015 00A 011 + 12 00A 015 00A 015 00A + 13 015 00A 015 00A 015 + 14 00A 015 01B 015 00A + 15 01B 00A 015 00A 01B + 16 01B 015 00A 015 01B + 17 00E 01B 015 01B 00E + 18 01B 015 01B 015 01B + 19 01B 015 01F 015 01B + 20 01F 00E 01B 00E 01F + 21 01F 015 01F 015 01F + 22 01B 01F 01B 01F 01B + 23 01F 01B 01F 01B 01F + 24 01F 01F 01B 01F 01F + 25 01F 01F 01F 01F 01F + 26 00C 012 012 012 00C diff --git a/symbols/luse6.sym b/symbols/luse6.sym new file mode 100644 index 0000000..57bcae3 --- /dev/null +++ b/symbols/luse6.sym @@ -0,0 +1,18 @@ + -6 -6 79/11/07.LAND USE TONES + 7 EXTRA + 1 00D 013 00A 014 013 000 + 2 00A 00A 00A 00A 000 000 + 3 000 015 00A 000 000 000 + 4 000 003 000 00C 000 000 + 5 011 015 01F 015 011 000 + 6 01F 015 01B 015 01F 000 + 7 000 00A 000 00A 000 000 + 8 01F 011 015 011 01F 000 + 9 01F 01F 01F 01F 01F 000 + 10 000 000 004 000 000 000 + 11 000 03F 000 000 03F 000 + 12 012 012 012 012 012 012 + 13 008 010 020 001 002 004 + 14 004 002 001 020 010 008 + 15 03F 03F 03F 03F 03F 03F + 16 02A 015 02A 015 02A 015 + 17 02A 000 015 000 02A 000 diff --git a/symbols/misc14.sym b/symbols/misc14.sym new file mode 100644 index 0000000..d47870d --- /dev/null +++ b/symbols/misc14.sym @@ -0,0 +1,47 @@ + -14 -14 79/11/07.DICOMED SYMBOLS (KENS) + 1 00000000000000000000000000000000000000000000000000000000 + 2 0000000000000000000001E001E001E001E000000000000000000000 + 3 000000000000000000003FFF3FFF3FFF3FFF00000000000000000000 + 4 03F003F003F003F003F003F003F003F003F003F003F003F003F003F0 + 5 000000000FFC0FFC0FFC0FFC0FFC0FFC0FFC0FFC0FFC0FFC00000000 + 6 3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FFF + 7 00C000C000C000C000C000C03FFF3FFF00C000C000C000C000C000C0 + 8 01E001E001E001E001E03FFF3FFF3FFF3FFF01E001E001E001E001E0 + 9 3FFF3FFF3FFF380738073807380738073807380738073FFF3FFF3FFF + 10 0007000F001F003E007C00F801F003E007C00F801F003E003C003800 + 11 0000000000D00618040802000130006000C000C00040004000000000 + 12 3FFF3FFF3FFF3FFF3FFF3E1F3E1F3E1F3E1F3FFF3FFF3FFF3FFF3FFF + 13 004000C000E001E001E003F003F007F807F80FFC0040004000400040 + 14 00030007000E001C0038007000E001C0038007000E001C0038003000 + 15 31E331E30E1C0E1C0E1C31E331E331E331E30E1C0E1C0E1C31E331E3 + 16 3FFF3FFF300330033003300330C330C330033003300330033FFF3FFF + 17 3FFF3FFF300330033003300333F333F330033003300330033FFF3FFF + 18 300038001C000E000700038001C000E000700038001C000E00070003 + 19 3F803F803F803F803F803F80007F007F007F007F007F007F007F007F + 20 3F3F3F3F333333333F3F3F3F000000003F3F3F3F333333333F3F3F3F + 21 0000003800383F003F000000003F003F00000F000F00003800380000 + 22 0000000000C001E0033006180C0C0C0C0618033001E000C000000000 + 23 000000C001E0033006180C0C180618060C0C0618033001E000C00000 + 24 00000000000000C000C001E007F807F801E000C000C0000000000000 + 25 07F00FE01FC03F803F013E033C07380F301F203F007F00FE01FC03F8 + 26 0000000000C001E003F007F80FFC0FFC07F803F001E000C000000000 + 27 300338071C0E0E1C073803F00120012003F007380E1C1C0E38073003 + 28 000000C000C000C003F003301E1E1E1E033003F000C000C000C00000 + 29 00000000000007F807F8000000000000000007F807F8000000000000 + 30 000003F003F003F00FFC0FFC0FFC0FFC0FFC0FFC03F003F003F00000 + 31 00000100038006C00C6018300C18060C0306018C00D8007000200000 + 32 0618061806183FFF3FFF06180618061806183FFF3FFF061806180618 + 33 00000000000007F807F8061806180618061807F807F8000000000000 + 34 00001E1E1E1E1E1E1E1E01E001E001E001E01E1E1E1E1E1E1E1E0000 + 35 0018001800380078007800F001E001E003C007800780070006000600 + 36 000000000E1C0E1C0E1C00000000000000000E1C0E1C0E1C00000000 + 37 000001B007200C48088C091C0330074400C800C000C001E003F00000 + 38 00C000C001E003F007F80FFC1FFE00C000C000C000C000C000C00000 + 39 00000000000000C001E003F007F80FFC000000000000000000000000 + 40 00000000000000C000C000C003F003F000C000C000C0000000000000 + 41 06180618061806180618061806180618061806180618061806180618 + 42 000008C009F007E00FE00FFC07FC03F00BE40CC004C000C001E003F0 + 43 00C000C000C000C000C000C000C000C000C000C000C000C000C000C0 + 44 0000000000C000C000C000C000C000C000C000C000C000C000000000 + 46 00000000061806180618061806180618061806180618061800000000 + 47 300338071C0E0E1C073803F001E001E003F007380E1C1C0E38073003 diff --git a/symbols/misc16.sym b/symbols/misc16.sym new file mode 100644 index 0000000..debd1eb --- /dev/null +++ b/symbols/misc16.sym @@ -0,0 +1,236 @@ +-16 -16 16X16 FINAL + 1 0000018003C007E007E00FF00FF01FF81FF83FFC3FFC7FFE7FFE03C003C00000 + 2 000041806186318E318C199819980DB00DB00FF07FFE7FFE000001FE01FE0000 + 3 0000018003C007E00FF01FF83FFC3FFC3FFC3FFC3FFC3FFC3FFC3FFC00000000 + 4 000001801BC01E601C3018183F0C317C314C3F4C304C304C3FFC3FFC00000000 + 5 00000000000000000FF00FF00FF00FF00FF00FF00FF00FF00000000000000000 + 6 00000000000000000000000003C003C003C003C0000000000000000000000000 + 7 00000000018001800180018001803FFC3FFC0180018001800180018000000000 + 8 000000000000C003C003F00F300C3C3C0C300FF003C003C00000000000000000 + 9 00000000300030003C000C000F00030003CC00CC00FC003C00FC00FC00000000 + 10 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 11 0000666666660000000066666666000000006666666600000000666666660000 + 12 00007FFE7FFE000000007FFE7FFE000000007FFE7FFE000000007FFE7FFE0000 + 13 0000000000000000000000003FFC3FFC3FFC3FFC000000000000000000000000 + 14 0842042182104108208410420821841042082104108208418420421021081084 + 15 084314A3A3144308A49418631863A4944308A31414A3084394A46318631894A4 + 16 3333333333333333333333333333333333333333333333333333333333333333 + 17 3333333333333333333333333333333333333333333333333333333333333333 + 18 FFFFFFFF33333333FFFFFFFF33333333FFFFFFFF33333333FFFFFFFF33333333 + 19 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 20 4208841008211042208441088210042108421084210842108420084110822104 + 21 630CC6188C31186330C6618CC31886310C6318C6318C6318C6308C6118C33186 + 22 738EE71CCE399C7338E771CEE39CC7398E731CE739CE739CE738CE719CE339C7 + 23 000E001C0038007000E001C0038007000E001C0038007000E000C00180030007 + 24 0180018001800180018001800180FFFFFFFF0180018001800180018001800180 + 25 4208841000000000208441080000000008421084000000008420084100000000 + 26 4208A514000000002084514A00000000084294A40000000084204A5100000000 + 27 4208A514420800002084514A20840000084294A40842000084204A5184200000 + 28 528AA5144208841028A5514A208441088A5214A508421084A5284A5184200841 + 29 738EE71C4208841038E771CE208441088E731CE708421084E738CE7184200841 + 30 FFFFE71C4208FFFFFFFF71CE2084FFFFFFFF9CE70842FFFFFFFFCE718420FFFF + 31 FFFFE71C4208E71CFFFF71CE208471CEFFFF9CE708429CE7FFFFCE718420CE71 + 32 FFFFFFFF4208FFFFFFFFFFFF2084FFFFFFFFFFFF0842FFFFFFFFFFFF0421FFFF + 33 FFFFFFFF4208FFFFFFFFFFFF2084FFFFFFFFFFFF0842FFFFFFFFFFFF0421FFFF + 34 FFFF3333CCCC3333CCCC3333CCCC3333FFFF3333CCCC3333FFFF3333CCCC3333 + 35 FFFF3333FFFF3333CCCC3333FFFF3333FFFF3333FFFF3333FFFF3333FFFF3333 + 36 FFFF3333CCCC3333CCCC3333CCCC3333FFFF3333CCCC3333FFFF3333CCCC3333 + 37 797B3232C4CC0313848423234CCC31307B793232CCC41303B7972323CC4C3031 + 38 797B3232C4CC0313848423234CCC31307B793232CCC41303B7972323CC4C3031 + 39 FFFF3232C4CCFFFF84842323FFFF3130FFFF3232FFFE1303FFFF2323FFFF3031 + 40 ECF33232C4CCFC7F84842323FFFF3130C1E33232FFFE1302FE3F2323FFC73031 + 41 ECF37672E6EEFD7F8C8C6767FFFF3131C9EB7676FFFE1313FEBF6727FFC73131 + 42 ECF7767BE6FEFD7F8CDC67F7FFFF33F1CDEB7F76FFFE3F13FEBFF727FFC7F133 + 43 EEF7F67BEEFFFD7FACDC67FFFFFF33F5CDEB7FF6FFFE3F53FEBFFF67FFC7F533 + 44 FFFFF67BEEFFFD7FACDC67FFFFFF33F5CDEB7FF6FFFEFFFFFEBFFF67FFC7F533 + 45 FFFFF67BEEFFFD7FECDC67FFFFFFFFFFCDEB7FF6FFFEFFFFFEBFFFFFFFFFF533 + 46 000007C00FE01FF03FF83FF81FF00FE00380038003800380038007C000000000 + 47 00000000000007801F80070001000100017801FC00F800700020002000600000 + 48 00000000618073807F806D8061806180000001FC01FC0180018001FC01FC0000 + 49 00000000618073807F806D8061806180000001FC018C018C01FC018C018C01FC + 50 000000003FE03FE0070007000700070007000700000000000000000000000000 + 51 0000000000001F80100010001F80008000801F800000007C00400040007C0000 + 52 000000003F002000200020003F000000000003F8004000400040004000400000 + 53 000000003E00220022003E0028002400220001F00110011001F0014001200110 + 54 000000000000FFFFFFFFFFFFFFFFCCE6FFFFFFFFFFFFFFFF0000000000000000 + 55 000000000000FFFFFFFFFFFFFFFFCCE6FFFFFFFFFFFFFFFF0000000000000000 + 56 0000000021020000000000002102000000000000208400000000000020840000 + 57 4208000000000000208400000000000008420000000000000000000000000000 + 58 C0030000000000000000000003C003C003C003C000000000000000000000C003 + 59 80010000000000000000000003C003C003C003C0000000000000000000008001 + 60 0000000000000FF00FF00C000C000FF00FF0003000300FF00FF0000000000000 + 61 00003F8004000400058005000580000000FE0010001000100016001400160000 + 62 00000E001F003F801F000E0004000438047C043804100E380000000000000000 + 63 000000000400061006180618041804100510069014942C1A24100E3800000000 + 64 300030002600261824D824D0649024907490059014942DDA04100E3800000000 + 65 300030002600261824D824D0249064902490359024942CD824907FFC52240000 + 66 0000000000000000200024D0249064902490359024942CD824907FFC52240000 + 67 0000038003800380011001280148018023225555898801000100010003800000 + 68 000007C001002AA81550010001000100012001500190011001001FF800000000 + 69 00000000202024202420242022201240114011401150095029507FF800001FF0 + 70 00000000100038007C00FE0010001020107010F8102010F87C00000000000000 + 71 000000000300C103C103F38F300C3C3C0C300FF003C003C00000000000000000 + 72 000001C00040C083C103F1CF300C3C3C0C300FF003C003C00000000000000000 + 73 000001C00040C1C3C043F1CF300C3C3C0C300FF003C003C00000000000000000 + 74 000001400140C1C3C043F04F300C3C3C0C300FF003C003C00000000000000000 + 75 000001C00100C1C3C043F1CF300C3C3C0C300FF003C003C00000000000000000 + 76 000001C00100C1C3C143F1CF300C3C3C0C300FF003C003C00000000000000000 + 77 000001C00040C083C083F10F300C3C3C0C300FF003C003C00000000000000000 + 78 000001C00140C1C3C143F1CF300C3C3C0C300FF003C003C00000000000000000 + 79 000001C00140C1C3C043F1CF300C3C3C0C300FF003C003C00000000000000000 + 80 0000666666660000000066666666000000006666666600000000666666660000 + 81 000001801BC01E601C3018183F0C317C314C3F4C304C304C3FFC3FFC00000000 + 82 FFFF2448FFFF244824482448FFFF2448FFFF24482448FFFF2448FFFF24482448 + 83 FFFF2549FFFF2549FFFF2549FFFF2549FFFF25492549FFFF2549FFFF25492549 + 84 00000000231013200B4007803CF807800B401320231003000000000000000000 + 85 00004210222012400A8007007FF807000A801240222042100000000000000000 + 86 00000000102038707CF83870102000000000102038707CF83870102000000000 + 87 FFFF3333CCCC3333CCCC3333CCCC3333FFFF3333CCCC3333FFFF3333CCCC3333 + 88 FFFF3333FFFF3333CCCC3333FFFF3333FFFF3333FFFF3333FFFF3333FFFF3333 + 89 738EE71CCE399C7338E771CEE39CC7398E731CE739CE739CE738CE719CE339C7 + 90 FFFFFFFF33333333FFFFFFFF33333333FFFFFFFF33333333FFFFFFFF33333333 + 91 3333333333333333333333333333333333333333333333333333333333333333 + 92 0000249200002492000024920000249200002492000024920000249200002492 + 93 00007FFE7FFE000000007FFE7FFE000000007FFE7FFE000000007FFE7FFE0000 + 94 0000000000000000000000003FFC3FFC3FFC3FFC000000000000000000000000 + 95 0000000022221414080814142222000022221414080814142222000000000000 + 96 00000000300030003C000C000F00030003CC00CC00FC003C00FC00FC00000000 + 97 AAAA000055550000AAAA000055550000AAAA000055550000AAAA000055550000 + 98 0000000010202850448828501020000000001020285044882850102000000000 + 99 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +100 B6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DB +101 B6DB0000B6DBB6DB0000B6DBB6DB0000B6DBB6DB0000B6DBB6DB0000B6DBB6DB +102 7BDF7BDF7BDF7BDF7BDF00007BDF7BDF7BDF7BDF00007BDF7BDF7BDF7BDF0000 +103 7BDF4A594A597BDF7BDF00007BDF4A594A597BDF00007BDF4A594A597BDF0000 +104 7BDF4A514A514A517BDF00007BDF4A514A517BDF00007BDF4A514A517BDF0000 +105 7F7F7F7F7F7F7F7F7F7F7F7F7F7F00007F7F7F7F7F7F7F7F7F7F7F7F7F7F0000 +106 7F7F414141414141414141417F7F00007F7F414141414141414141417F7F0000 +107 7F7F414141414141414141417F7F00007F7F414141414141414141417F7F0000 +108 7F7F41415D5D5D5D5D5D41417F7F00007F7F41415D5D5D5D5D5D41417F7F0000 +109 7F7F41415D5D55555D5D41417F7F00007F7F41415D5D55555D5D41417F7F0000 +110 BEBE41415D5D55555D5D4141BEBE8080BEBE41415D5D55555D5D4141BEBE8080 +111 A2A241411C1C14141C1C4141A2A28080A2A241411C1C14141C1C4141A2A28080 +112 A2A241410808141408084141A2A28080A2A241410808141408084141A2A28080 +113 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +114 FFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAA +115 FFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAA +116 FFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAA +117 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +118 7577AEEEDD5DABBB7757EAEEDDD5BABB7775EEAE5DDDBBAB5777EEEAD5DDBBBA +119 6167A6E6C95989B936566A6E9D949A996761E6A659C9B98956366E6A949D999A +120 EEEE5555BBBB5555EEEE5555BBBB5555EEEE5555BBBB5555EEEE5555BBBB5555 +121 084314A3A3144308A49418631863A4944308A31414A3084394A46318631894A4 +122 0000000021020000000000002102000000000000208400000000000020840000 +123 4208841008211042208441088210042108421084210842108420084110822104 +124 7F7F7F7F7F7F7F7F7F7F7F7F7F7F00007F7F7F7F7F7F7F7F7F7F7F7F7F7F0000 +125 7F7F414141414141414141417F7F00007F7F414141414141414141417F7F0000 +126 7F7F414141414141414141417F7F00007F7F414141414141414141417F7F0000 +127 7F7F41415D5D5D5D5D5D41417F7F00007F7F41415D5D5D5D5D5D41417F7F0000 +128 7F7F41415D5D55555D5D41417F7F00007F7F41415D5D55555D5D41417F7F0000 +129 BEBE41415D5D55555D5D4141BEBE8080BEBE41415D5D55555D5D4141BEBE8080 +130 A2A241411C1C14141C1C4141A2A28080A2A241411C1C14141C1C4141A2A28080 +131 A2A241410808141408084141A2A28080A2A241410808141408084141A2A28080 +132 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +133 FFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAA +134 FFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAA +135 FFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAA +136 0000666666660000000066666666000000006666666600000000666666660000 +137 000001801BC01E601C3018183F0C317C314C3F4C304C304C3FFC3FFC00000000 +138 FFFF2448FFFF244824482448FFFF2448FFFF24482448FFFF2448FFFF24482448 +139 FFFF2549FFFF2549FFFF2549FFFF2549FFFF25492549FFFF2549FFFF25492549 +140 00000000231013200B4007803CF807800B401320231003000000000000000000 +141 00004210222012400A8007007FF807000A801240222042100000000000000000 +142 00000000102038707CF83870102000000000102038707CF83870102000000000 +143 FFFF3333CCCC3333CCCC3333CCCC3333FFFF3333CCCC3333FFFF3333CCCC3333 +144 FFFF3333FFFF3333CCCC3333FFFF3333FFFF3333FFFF3333FFFF3333FFFF3333 +145 738EE71CCE399C7338E771CEE39CC7398E731CE739CE739CE738CE719CE339C7 +146 FFFFFFFF33333333FFFFFFFF33333333FFFFFFFF33333333FFFFFFFF33333333 +147 3333333333333333333333333333333333333333333333333333333333333333 +148 0000249200002492000024920000249200002492000024920000249200002492 +149 00007FFE7FFE000000007FFE7FFE000000007FFE7FFE000000007FFE7FFE0000 +150 0000000000000000000000003FFC3FFC3FFC3FFC000000000000000000000000 +151 0000000022221414080814142222000022221414080814142222000000000000 +152 00000000300030003C000C000F00030003CC00CC00FC003C00FC00FC00000000 +153 AAAA000055550000AAAA000055550000AAAA000055550000AAAA000055550000 +154 0000000010202850448828501020000000001020285044882850102000000000 +155 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +156 B6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DB +157 B6DB0000B6DBB6DB0000B6DBB6DB0000B6DBB6DB0000B6DBB6DB0000B6DBB6DB +158 7BDF7BDF7BDF7BDF7BDF00007BDF7BDF7BDF7BDF00007BDF7BDF7BDF7BDF0000 +159 7BDF4A594A597BDF7BDF00007BDF4A594A597BDF00007BDF4A594A597BDF0000 +160 7BDF4A514A514A517BDF00007BDF4A514A517BDF00007BDF4A514A517BDF0000 +161 7F7F7F7F7F7F7F7F7F7F7F7F7F7F00007F7F7F7F7F7F7F7F7F7F7F7F7F7F0000 +162 7F7F414141414141414141417F7F00007F7F414141414141414141417F7F0000 +163 7F7F414141414141414141417F7F00007F7F414141414141414141417F7F0000 +164 7F7F41415D5D5D5D5D5D41417F7F00007F7F41415D5D5D5D5D5D41417F7F0000 +165 7F7F41415D5D55555D5D41417F7F00007F7F41415D5D55555D5D41417F7F0000 +166 BEBE41415D5D55555D5D4141BEBE8080BEBE41415D5D55555D5D4141BEBE8080 +167 A2A241411C1C14141C1C4141A2A28080A2A241411C1C14141C1C4141A2A28080 +168 A2A241410808141408084141A2A28080A2A241410808141408084141A2A28080 +169 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +170 FFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAA +171 FFFF00000000FFFF00000000FFFF00000000FFFF00000000FFFF000000000000 +172 8924124924924924924824914922924424894912922424494892912422484490 +173 A9A592496CB3ED34D24A2D95DDA2DA45A5A95B92BB6C34ED4AD2952DA2DC45DB +174 FFFF0000000000000000FFFF0000000000000000FFFF00000000000000000000 +175 FFFF8420842084208420FFFF8420842084208420FFFF84208420842084208420 +176 FFFFA524A524A524A524FFFFA524A524A524A524FFFFA524A524A524A524A524 +177 8220411020881044082204118208410420821041882044102208110408820441 +178 8210042108421084210842108420084110822104420884100821104220844108 +179 8290446128621094290846148622094190826144622894100829144622864109 +180 829044612862109429084694B622094990926144622994900929144622864909 +181 8001400220041008081004200240018001800240042008101008200440028001 +182 9009481224241248899044212242118411882244442289911248242448129009 +183 90094992242412488990442122425184518A2244442289911248242449929009 +184 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +185 7577AEEEDD5DABBB7757EAEEDDD5BABB7775EEAE5DDDBBAB5777EEEAD5DDBBBA +186 6167A6E6C95989B936566A6E9D949A996761E6A659C9B98956366E6A949D999A +187 EEEE5555BBBB5555EEEE5555BBBB5555EEEE5555BBBB5555EEEE5555BBBB5555 +188 084314A3A3144308A49418631863A4944308A31414A3084394A46318631894A4 +189 0000000021020000000000002102000000000000208400000000000020840000 +190 4208841008211042208441088210042108421084210842108420084110822104 +191 0000018003C007E007E00FF00FF01FF81FF83FFC3FFC7FFE7FFE03C003C00000 +192 000041806186318E318C199819980DB00DB00FF07FFE7FFE000001FE01FE0000 +193 000E001C0038007000E001C0038007000E001C0038007000E000C00180030007 +194 0180018001800180018001800180FFFFFFFF0180018001800180018001800180 +195 000007C00FE01FF03FF83FF81FF00FE00380038003800380038007C000000000 +196 00000000202024202420242022201240114011401150095029507FF800001FF0 +197 00000000018001800180018001803FFC3FFC0180018001800180018000000000 +198 0000666666660000000066666666000000006666666600000000666666660000 +199 000001801BC01E601C3018183F0C317C314C3F4C304C304C3FFC3FFC00000000 +200 FFFF2448FFFF244824482448FFFF2448FFFF24482448FFFF2448FFFF24482448 +201 FFFF2549FFFF2549FFFF2549FFFF2549FFFF25492549FFFF2549FFFF25492549 +202 00000000231013200B4007803CF807800B401320231003000000000000000000 +203 00004210222012400A8007007FF807000A801240222042100000000000000000 +204 00000000102038707CF83870102000000000102038707CF83870102000000000 +205 FFFF3333CCCC3333CCCC3333CCCC3333FFFF3333CCCC3333FFFF3333CCCC3333 +206 FFFF3333FFFF3333CCCC3333FFFF3333FFFF3333FFFF3333FFFF3333FFFF3333 +207 738EE71CCE399C7338E771CEE39CC7398E731CE739CE739CE738CE719CE339C7 +208 FFFFFFFF33333333FFFFFFFF33333333FFFFFFFF33333333FFFFFFFF33333333 +209 3333333333333333333333333333333333333333333333333333333333333333 +210 0000249200002492000024920000249200002492000024920000249200002492 +211 00007FFE7FFE000000007FFE7FFE000000007FFE7FFE000000007FFE7FFE0000 +212 0000000000000000000000003FFC3FFC3FFC3FFC000000000000000000000000 +213 0000000022221414080814142222000022221414080814142222000000000000 +214 00000000300030003C000C000F00030003CC00CC00FC003C00FC00FC00000000 +215 AAAA000055550000AAAA000055550000AAAA000055550000AAAA000055550000 +216 0000000010202850448828501020000000001020285044882850102000000000 +217 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +218 B6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DBB6DB +219 B6DB0000B6DBB6DB0000B6DBB6DB0000B6DBB6DB0000B6DBB6DB0000B6DBB6DB +220 7BDF7BDF7BDF7BDF7BDF00007BDF7BDF7BDF7BDF00007BDF7BDF7BDF7BDF0000 +221 7BDF4A594A597BDF7BDF00007BDF4A594A597BDF00007BDF4A594A597BDF0000 +222 7BDF4A514A514A517BDF00007BDF4A514A517BDF00007BDF4A514A517BDF0000 +223 7F7F7F7F7F7F7F7F7F7F7F7F7F7F00007F7F7F7F7F7F7F7F7F7F7F7F7F7F0000 +224 7F7F414141414141414141417F7F00007F7F414141414141414141417F7F0000 +225 7F7F414141414141414141417F7F00007F7F414141414141414141417F7F0000 +226 7F7F41415D5D5D5D5D5D41417F7F00007F7F41415D5D5D5D5D5D41417F7F0000 +227 7F7F41415D5D55555D5D41417F7F00007F7F41415D5D55555D5D41417F7F0000 +228 BEBE41415D5D55555D5D4141BEBE8080BEBE41415D5D55555D5D4141BEBE8080 +229 A2A241411C1C14141C1C4141A2A28080A2A241411C1C14141C1C4141A2A28080 +230 A2A241410808141408084141A2A28080A2A241410808141408084141A2A28080 +231 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +232 FFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAA +233 FFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAAFFFFAAAAAAAAAAAA +234 FFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAAFFFFAAAA + \ No newline at end of file diff --git a/symbols/misc25.sym b/symbols/misc25.sym new file mode 100644 index 0000000..eb7c4c3 --- /dev/null +++ b/symbols/misc25.sym @@ -0,0 +1,661 @@ + -25 -25 79/11/07.92 TONES ALPHANUMERICS AND PICTURES + 1 00003C0000003C0000003C0000003C0000003C0000003C0000003C0000003C00 + 1 00003C0000003C0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00003C0000003C00 + 1 00003C0000003C0000003C0000003C0000003C0000003C0000003C0000003C00 + 1 00000000 + 2 00181818001818180018181800FFFFFF00FFFFFF001818180018181800181818 + 2 00181818001818180018181800FFFFFF00FFFFFF001818180018181800181818 + 2 00181818001818180018181800FFFFFF00FFFFFF001818180018181800181818 + 2 00000000 + 3 000618600006186000061860000618600006186000FFFFFF00FFFFFF00061860 + 3 00061860000618600006186000FFFFFF00FFFFFF000618600006186000061860 + 3 0006186000FFFFFF00FFFFFF0006186000061860000618600006186000061860 + 3 00000000 + 4 0007C3E00007C3E00007C3E00007C3E00007C3E000FFFFFF00FFFFFF00FFFFFF + 4 00FFFFFF00FFFFFF0007C3E00007C3E00007C3E00007C3E000FFFFFF00FFFFFF + 4 00FFFFFF00FFFFFF00FFFFFF0007C3E00007C3E00007C3E00007C3E00007C3E0 + 4 00000000 + 5 00000000000000000000000000FFFFFF00FFFFFF000000000000000000000000 + 5 00000000000000000000000000FFFFFF00FFFFFF000000000000000000000000 + 5 00000000000000000000000000FFFFFF00FFFFFF000000000000000000000000 + 5 00000000 + 6 0018181800181818001818180018181800181818001818180018181800181818 + 6 0018181800181818001818180018181800181818001818180018181800181818 + 6 0018181800181818001818180018181800181818001818180018181800181818 + 6 00000000 + 7 00FFFFFF0000000000000000000000000000000000FFFFFF00FFFFFF00000000 + 7 00000000000000000000000000FFFFFF00FFFFFF000000000000000000000000 + 7 0000000000FFFFFF00FFFFFF0000000000000000000000000000000000FFFFFF + 7 00000000 + 8 0086186100861861008618610086186100861861008618610086186100861861 + 8 0086186100861861008618610086186100861861008618610086186100861861 + 8 0086186100861861008618610086186100861861008618610086186100861861 + 8 00000000 + 9 00E1C38700E1C38700E1C38700E1C38700E1C38700E1C38700E1C38700E1C387 + 9 00E1C38700E1C38700E1C38700E1C38700E1C38700E1C38700E1C38700E1C387 + 9 00E1C38700E1C38700E1C38700E1C38700E1C38700E1C38700E1C38700E1C387 + 9 00000000 + 10 00FFFFFF00FFFFFF00FFFFFF0000000000000000000000000000000000FFFFFF + 10 00FFFFFF00FFFFFF0000000000000000000000000000000000FFFFFF00FFFFFF + 10 00FFFFFF0000000000000000000000000000000000FFFFFF00FFFFFF00FFFFFF + 10 00000000 + 11 00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D + 11 00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D + 11 00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D00B6DB6D + 11 00000000 + 12 00CF3CF300CF3CF300CF3CF300CF3CF300CF3CF300CF3CF300CF3CF300CF3CF3 + 12 00CF3CF300CF3CF300CF3CF300CF3CF300CF3CF300CF3CF300CF3CF300CF3CF3 + 12 00CF3CF300CF3CF300CF3CF300CF3CF300CF3CF300CF3CF300CF3CF300CF3CF3 + 12 00000000 + 13 0000000000000000000000000000000000000000000000000000000000000000 + 13 000000000000000000003C0000003C0000003C0000003C000000000000000000 + 13 0000000000000000000000000000000000000000000000000000000000000000 + 13 00000000 + 14 0000000000000000000000000000000000000000000000000000000000000000 + 14 0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00 + 14 0000000000000000000000000000000000000000000000000000000000000000 + 14 00000000 + 15 00000000000000000000000000000000000FFFF0000FFFF0000FFFF0000FFFF0 + 15 000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0 + 15 000FFFF0000FFFF0000FFFF0000FFFF000000000000000000000000000000000 + 15 00000000 + 16 00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF + 16 00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF + 16 00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF + 16 00000000 + 17 00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF + 17 0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00 + 17 00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF + 17 00000000 + 18 00F07C1F00F07C1F00F07C1F00F07C1F00F07C1F000F83E0000F83E0000F83E0 + 18 000F83E0000F83E000F07C1F00F07C1F00F07C1F00F07C1F00F07C1F000F83E0 + 18 000F83E0000F83E0000F83E0000F83E000F07C1F00F07C1F00F07C1F00F07C1F + 18 00000000 + 19 00CCCCCC00CCCCCC003333330033333300CCCCCC00CCCCCC0033333300333333 + 19 00CCCCCC00CCCCCC003333330033333300CCCCCC00CCCCCC0033333300333333 + 19 00CCCCCC00CCCCCC003333330033333300CCCCCC00CCCCCC0033333300333333 + 19 00000000 + 20 00E0000000E000000078000000780000001E0000001E00000007800000078000 + 20 0001E0000001E000000078000000780000001E0000001E000000078000000780 + 20 000001E0000001E000000078000000780000001E0000001E0000000700000007 + 20 00000000 + 21 00F0000000F0000000F0000000F0000000F00000000F8000000F8000000F8000 + 21 000F8000000F800000007C0000007C0000007C0000007C0000007C00000003E0 + 21 000003E0000003E0000003E0000003E00000001F0000001F0000001F0000001F + 21 00000000 + 22 0080200800401004002008020010040100080200000401000002008000010040 + 22 0000802000004010008020080040100400200802001004010008020000040100 + 22 0002008000010040000080200000401000802008004010040020080200100401 + 22 00000000 + 23 00C00C0000E00E000070070000380380001C01C0000E00E00007007000038038 + 23 0001C01C0000E00E000070070080380300C01C0100E00E000070070000380380 + 23 001C01C0000E00E000070070000380380001C01C0000E00E0000700700003003 + 23 00000000 + 24 0080C06000C06030006030180030180C00180C06000C06030006030100030180 + 24 000180C00000C0600080603000C030180060180C00300C0600180603000C0301 + 24 00060180000300C0000180600080C03000C060180060300C0030180600180C03 + 24 00000000 + 25 00E00E0000E00E0000E00E00001C01C0001C01C0001C01C00003803800038038 + 25 0003803800007007000070070000700700E00E0000E00E0000E00E00001C01C0 + 25 001C01C0001C01C0000380380003803800038038000070070000700700007007 + 25 00000000 + 26 00C30C3000C30C300030C30C0030C30C000C30C3000C30C300C30C3000C30C30 + 26 0030C30C0030C30C000C30C3000C30C300C30C3000C30C300030C30C0030C30C + 26 000C30C3000C30C300C30C3000C30C300030C30C0030C30C000C30C3000C30C3 + 26 00000000 + 27 000000000000000F000000FF00000FFF0000FFFF000FFFF000FFFF0000FFF000 + 27 00FF000000F00000000000000000000000000000000000000000000F000000FF + 27 00000FFF0000FFFF000FFFF000FFFF0000FFF00000FF000000F0000000000000 + 27 00000000 + 28 00C0000300C000030030000C0030000C000C0030000C0030000300C0000300C0 + 28 0000C3000000C30000003C0000003C0000003C0000003C000000C3000000C300 + 28 000300C0000300C0000C0030000C00300030000C0030000C00C0000300C00003 + 28 00000000 + 29 00E0000700E0000700E00007001C0038001C0038001C0038000381C0000381C0 + 29 000381C000007E0000007E0000007E0000007E0000007E0000007E00000381C0 + 29 000381C0000381C0001C0038001C0038001C003800E0000700E0000700E00007 + 29 00000000 + 30 0080000600C0000E00E0001C00700038001C0038000E0070000700E0000381C0 + 30 0001C3800000E70000007E0000003C0000003C0000007E000000E7000001C380 + 30 000381C0000700E0000E0070001C00380038001C0070000E00E0000700C00003 + 30 00000000 + 31 00E0000700E000070078001E0078001E001E0078001E0078000781E0000781E0 + 31 0001E7800001E78000007E0000007E0000007E0000007E000001E7800001E780 + 31 000781E0000781E0001E0078001E00780078001E0078001E00E0000700E00007 + 31 00000000 + 32 00F0001F00F0001F00F0001F00F0001F00F0001F000F83E0000F83E0000F83E0 + 32 000F83E0000F83E000007C0000007C0000007C0000007C0000007C00000F83E0 + 32 000F83E0000F83E0000F83E0000F83E000F0001F00F0001F00F0001F00F0001F + 32 00000000 + 33 00C0180300E018070070180E0038181C001C1838000E1870000718E0000399C0 + 33 0001C3800000E70000007E0000FF3CFF00FF3CFF00007E000000E7000001C380 + 33 000399C0000718E0000E1870001C18380038181C0070180E00E0180700C01803 + 33 00000000 + 34 00F0000F00F0000F0078001E0078001E003C003C003C003C001E0078001E0078 + 34 000F00F0000F00F00007FFE00007FFE00007FFE00007FFE0000F00F0000F00F0 + 34 001E0078001E0078003C003C003C003C0078001E0078001E00F0000F00F0000F + 34 00000000 + 35 009024090060180600601806009024090008421000048120000300C0000300C0 + 35 0004812000084210009024090060180600601806009024090008421000048120 + 35 000300C0000300C0000481200008421000902409006018060060180600902409 + 35 00000000 + 36 00C03C0300C03C030030C30C0030C30C000F00F0000F00F0000F00F0000F00F0 + 36 0030C30C0030C30C00C03C0300C03C0300C03C0300C03C030030C30C0030C30C + 36 000F00F0000F00F0000F00F0000F00F00030C30C0030C30C00C03C0300C03C03 + 36 00000000 + 37 0099CCE6003399CC0067379900CE6733009CCE6700399CCE0073399C0099CCE6 + 37 00CCE67300E673390073399C00399CCE009CCE6700CE673300E6733900CCE673 + 37 0099CCE6003399CC0067339900673399003399CC00673399003399CC0099CCE6 + 37 00000000 + 38 0018C3180031818C006318C600C63C63008C66310018C3180031818C006318C6 + 38 00C63C63008C66310018C3180031818C006318C600C63C63008C66310018C318 + 38 0031818C006318C600C63C63008C66310018C3180031818C006318C600C63C63 + 38 00000000 + 39 00C63C63006318C60031818C0018C318008C663100C63C63006318C60031818C + 39 0018C318008C663100C63C63006318C6006318C600C63C63008C66310018C318 + 39 0031818C006318C600C63C63008C66310018C3180031818C006318C600C63C63 + 39 00000000 + 40 00003C0000003C000000C3000000C300000300C0000300C0000C0030000C0030 + 40 0030000C0030000C00C0000300C0000300C0000300C000030030000C0030000C + 40 000C0030000C0030000300C0000300C00000C3000000C30000003C0000003C00 + 40 00000000 + 41 0000180000003C0000003C0000007E0000007E000000FF000000FF000001FF80 + 41 0001FF800003FFC00003FFC00007FFE00007FFE0000FFFF0000FFFF0001FFFF8 + 41 001FFFF8003FFFFC003FFFFC007FFFFE007FFFFE000FFFF0000FFFF0000FFFF0 + 41 00000000 + 42 00FFFFFF00FFFFFF00FFFFFF00FFBDFF00FFBDFF00FF3CFF00FF7EFF00FE7E7F + 42 00FE7E7F00FCFF3F00FCFF3F00F8FF1F00F9FF9F00F1FF8F00F1FF8F00E3FFC7 + 42 00E3FFC700C3FFC300C7FFE30087FFE10087FFE100FFFFFF00FFFFFF00FFFFFF + 42 00000000 + 43 01FFFFFF01000001010000010100000101000001010000010100000101000001 + 43 0100000101000001010000010100000101000001010000010100000101000001 + 43 0100000101000001010000010100000101000001010000010100000101000001 + 43 01FFFFFF + 44 000000000060180600601806000000000000000000000000000300C0000300C0 + 44 0000000000000000000000000060180600601806000000000000000000000000 + 44 000300C0000300C0000000000000000000000000006018060060180600000000 + 44 00000000 + 45 0000000000C30C3000C30C300000000000186186001861860000000000C30C30 + 45 00C30C300000000000186186001861860000000000C30C3000C30C3000000000 + 45 00186186001861860000000000C30C3000C30C30000000000018618600186186 + 45 00000000 + 46 00CCCCCC00CCCCCC003333330033333300CCCCCC00CCCCCC0033333300333333 + 46 00CCCCCC00CCCCCC003333330033333300CCCCCC00CCCCCC0033333300333333 + 46 00CCCCCC00CCCCCC003333330033333300CCCCCC00CCCCCC0033333300333333 + 46 00000000 + 47 00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF + 47 00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF + 47 00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF + 47 00000000 + 48 00000000000018000000180000C018060060180C003018180018183800181870 + 48 000C1870000C18E0000638E0000638E0000339C0000339C0000339C00001BB80 + 48 0001BB800001BB80003FFFF8003FFFF8000000000000000000000FFE00000FFE + 48 00000000 + 49 00000000000010000000380000007C000000FE000001FF000003FF800007FFC0 + 49 000FFFE0001FFFF0003FFFF8007FFFFC0080000200FFFFFE00FFFFFE00FFFFFE + 49 00FFF1FE00C631C600C631C600FFF1FE00FFF1FE00FFF1FE00FFF1FE00000000 + 49 00000000 + 50 00000000000010000000380000007C000000FE000001FF000003FF800007FFC0 + 50 000FFFE0001FFFF0003FFFF8007FFFFC00FFFFFE00FFFFFE00FFFFFE00FFFFFE + 50 00FFFFFE00FFFFFE00FFFFFE00FFFFFE00FFFFFE00FFFFFE00FFFFFE00000000 + 50 00000000 + 51 00EEEEEE00777777007BBBBB00EEEEEE00777777007BBBFB00EEFFBE007777F7 + 51 007BBFFB00EEEFFE00777FF7007BBFFB00EEFFFE00777FF7007BBFFB00EEEFFE + 51 007777F7007BBBFB00EEEFFE007777F7007BBBFB00EEEEEE00777777007BBBBB + 51 00000000 + 52 0000180000003C0000003C0000007E0000007E000000FF000000FF000001FF80 + 52 0001FF800003FFC00003FFC00007FFE00007FFE0000FFFF0000FFFF0001FFFF8 + 52 001FFFF8003FFFFC003FFFFC007FFFFE007FFFFE000FFFF0000FFFF0000FFFF0 + 52 00000000 + 53 00E0000700E000070078001E0078001E001E0078001E0078000781E0000781E0 + 53 0001E7800001E78000007E0000007E0000007E0000007E000001E7800001E780 + 53 000781E0000781E0001E0078001E00780078001E0078001E00E0000700E00007 + 53 00000000 + 54 000000000100080001801C0101C03E0300C0360300606306006063060070E38E + 54 0039C1DC003FC1FC001F80F800060020000000000100080001801C0101C03E03 + 54 0080360300606306006063060070E38E0039C1DC003FC1FC001F80F800060020 + 54 00000000 + 55 00007E0000007E0000007E0000007E0000007E0000007E0000007E0000007E00 + 55 00007E0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00007E00 + 55 00007E0000007E0000007E0000007E0000007E0000007E0000007E0000007E00 + 55 00000000 + 56 00003C0000003C0000003C0000003C0000003C0000003C0000003C0000003C00 + 56 00003C0000003C0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00003C0000003C00 + 56 00003C0000003C0000003C0000003C0000003C0000003C0000003C0000003C00 + 56 00000000 + 57 00000000000010000000380000006C000000C6000001830000033980000644C0 + 57 000C446000184430003038180070001C00FFFFFE00B0001E00307C1800304418 + 57 0030441800304418003044180030441800304418003FFFF8003FFFF800000000 + 57 00000000 + 58 00000000000000000060000C0060000C00000000000000000000000000000000 + 58 000000000000C6000000C6000000000000000000000000000000C6000000C600 + 58 00000000000000000000000000000000000000000060000C0060000C00000000 + 58 00000000 + 59 0000000000606060006060600000000000000000000606060006060600000000 + 59 0000000000606060006060600000000000000000000606060006060600000000 + 59 0000000000606060006060600000000000000000000606060006060600000000 + 59 00000000 + 60 0088888800000000002222220000000000888888000000000022222200000000 + 60 0088888800000000002222220000000000888888000000000022222200000000 + 60 0088888800000000002222220000000000888888000000000022222200000000 + 60 00000000 + 61 0007C3E00007C3E00007C3E00007C3E00007C3E000FFFFFF00FFFFFF00FFFFFF + 61 00FFFFFF00FFFFFF0007C3E00007C3E00007C3E00007C3E000FFFFFF00FFFFFF + 61 00FFFFFF00FFFFFF00FFFFFF0007C3E00007C3E00007C3E00007C3E00007C3E0 + 61 00000000 + 62 00AAAAAA00000000005555550000000000AAAAAA000000000055555500000000 + 62 00AAAAAA00000000005555550000000000AAAAAA000000000055555500000000 + 62 00AAAAAA00000000005555550000000000AAAAAA000000000055555500000000 + 62 00000000 + 63 00AAAAAA0055555500AAAAAA0055555500AAAAAA0055555500AAAAAA00555555 + 63 00AAAAAA0055555500AAAAAA0055555500AAAAAA0055555500AAAAAA00555555 + 63 00AAAAAA0055555500AAAAAA0055555500AAAAAA0055555500AAAAAA00555555 + 63 00000000 + 64 01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF + 64 01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF + 64 01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF01FFFFFF + 64 01FFFFFF + 65 000000000000000000000000000000000000000000000000000600C0000600C0 + 65 0000000000000000000000000000000000000000000000000000000000000000 + 65 00000000000600C0000600C00000000000000000000000000000000000000000 + 65 00000000 + 66 0000000000000000000000000000000000000000000000000000000000000000 + 66 0000000000000000003FFFF8003FFFF8003FFFF8003FFFF80000000000000000 + 66 0000000000000000000000000000000000000000000000000000000000000000 + 66 00000000 + 67 00F0001F00F0001F00F0001F00F0001F00F0001F000F83E0000F83E0000F83E0 + 67 000F83E0000F83E000007C0000007C0000007C0000007C0000007C00000F83E0 + 67 000F83E0000F83E0000F83E0000F83E000F0001F00F0001F00F0001F00F0001F + 67 00000000 + 68 0000000000000000000000000000000000000000000000000000000000000000 + 68 000000000000000000003C0000003C0000003C0000003C000000000000000000 + 68 0000000000000000000000000000000000000000000000000000000000000000 + 68 00000000 + 69 0000000000000000000000000000000000000000000000000000000000000000 + 69 0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00 + 69 0000000000000000000000000000000000000000000000000000000000000000 + 69 00000000 + 70 00000000000000000000000000000000000FFFF0000FFFF0000FFFF0000FFFF0 + 70 000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0 + 70 000FFFF0000FFFF0000FFFF0000FFFF000000000000000000000000000000000 + 70 00000000 + 71 00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FC003F00FC003F + 71 00FCFF3F00FCFF3F00FCFF3F00FCFF3F00FCFF3F00FCFF3F00FCFF3F00FCFF3F + 71 00FC003F00FC003F00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF + 71 00000000 + 72 0000000000C0000600E0000E0070001C00380038001C0070000E00E0000701C0 + 72 000383800001C7000000EE0000007C000000380000007C000010EE300039C738 + 72 007F83FC00FF01FE00FF00FE00FF81FE00FFC3FE00FF81FE00FF00FE00FE007E + 72 00000000 + 73 00C0180300E018070070180E0038181C001C1838000E1870000718E0000399C0 + 73 0001C3800000E70000007E0000FF3CFF00FF3CFF00007E000000E7000001C380 + 73 000399C0000718E0000E1870001C18380038181C0070180E00E0180700C01803 + 73 00000000 + 74 0000000000000000000000000000380000006C000000C6000001830000030180 + 74 000600C0000C006000180030003000180060000C0030001800180030000C0060 + 74 000600C000030180000183000000C60000006C00000038000000100000000000 + 74 00000000 + 75 00FFFFFF00FFFFFF00FFC3FF00FFC3FF00FFC3FF00FFC3FF00FFC3FF00FFC3FF + 75 00FFC3FF00FFC3FF00C0000300C0000300C0000300C0000300FFC3FF00FFC3FF + 75 00FFC3FF00FFC3FF00FFC3FF00FFC3FF00FFC3FF00FFC3FF00FFFFFF00FFFFFF + 75 00000000 + 76 00000000000000000000000000FFFFFF00FFFFFF000000000000000000000000 + 76 00000000000000000000000000FFFFFF00FFFFFF000000000000000000000000 + 76 00000000000000000000000000FFFFFF00FFFFFF000000000000000000000000 + 76 00000000 + 77 00003F8000003F8000003F8000003F8000003F8000003F8000003F80001FFFFF + 77 001FFFFF001FFFFF001FFFFF001FFFFF001FFFFF001FFFFF00003F8000003F80 + 77 00003F8000003F8000003F8000003F8000000000000000000000000000000000 + 77 00000000 + 78 000000000000000000000E0000008E200001CE700003EEF80001FFF00000FFE0 + 78 00007FC00007FFFC0007FFFC0007FFFC00007FC00000FFE00001FFF00003EEF8 + 78 0001CE7000008E2000000E000000000000000000000000000000000000000000 + 78 00000000 + 79 000007E0000007E0000007E0000007E000000FC000000FC000000FC000001F80 + 79 00001F8000001F8000003F0000003F0000003F0000007E0000007E0000007E00 + 79 0000FC000000FC000000FC000001F80000000000000000000000000000000000 + 79 00000000 + 80 0000040000007FC00000FFE00001FFF00003FFF80003F4F80003F4F80003F400 + 80 0003FF800003FFE00001FFF000007FF800000FF80007E5F80007E5F80007F5F8 + 80 0003FFF80003FFF00001FFE000007F8000000000000000000000000000000000 + 80 00000000 + 81 00000000000000000000000000000000001FFFFF001FFFFF001FFFFF001FFFFF + 81 001FFFFF000000000000000000000000001FFFFF001FFFFF001FFFFF001FFFFF + 81 001FFFFF00000000000000000000000000000000000000000000000000000000 + 81 00000000 + 82 0000FFC00000FFC00000FFC00000FFC00000FFC00000F8000000F8000000F800 + 82 0000F8000000F8000000F8000000F8000000F8000000F8000000F8000000F800 + 82 0000FFC00000FFC00000FFC00000FFC000000000000000000000000000000000 + 82 00000000 + 83 0000FFC00000FFC00000FFC00000FFC00000FFC0000007C0000007C0000007C0 + 83 000007C0000007C0000007C0000007C0000007C0000007C0000007C0000007C0 + 83 0000FFC00000FFC00000FFC00000FFC000000000000000000000000000000000 + 83 00000000 + 84 0000000000000000000000000000000000001F0000001F0000001F0000001F00 + 84 00001F0000000000000000000000000000001F0000001F0000001F0000001F00 + 84 00001F0000000000000000000000000000000000000000000000000000000000 + 84 00000000 + 85 0000007000000070000000E0000000E0001FFFFF001FFFFF001FFFFF001FFFFF + 85 001FFFFF0000070000000E0000000E00001FFFFF001FFFFF001FFFFF001FFFFF + 85 001FFFFF0000E0000000E0000001C00000000000000000000000000000000000 + 85 00000000 + 86 000000000000000000000000000000000000000000000300000003C00001FFF0 + 86 0001FFF80001FFF00001C3C00001C3000001C0000001C0000001C0000001C000 + 86 0000000000000000000000000000000000000000000000000000000000000000 + 86 00000000 + 87 0000000000000000000000000000000000000000000FC07E0007E0FC0003F1F8 + 87 0001FBF00000FFE000007FC000003F8000001F0000000E000000040000000000 + 87 0000000000000000000000000000000000000000000000000000000000000000 + 87 00000000 + 88 00000000000000000000000000000000000000000000040000000E0000001F00 + 88 00003F8000007FC00000FFE00001FBF00003F1F80007E0FC000FC07E00000000 + 88 0000000000000000000000000000000000000000000000000000000000000000 + 88 00000000 + 89 0000000000000000000000000000040000000E0000000E0000001F0000001F00 + 89 00003F8000003F8000000E0000000E0000000E0000000E0000000E0000000E00 + 89 00000E0000000E00000000000000000000000000000000000000000000000000 + 89 00000000 + 90 00000000000000000000000000000E0000000E0000000E0000000E0000000E00 + 90 00000E0000000E0000000E0000003F8000003F8000001F0000001F0000000E00 + 90 00000E0000000400000000000000000000000000000000000000000000000000 + 90 00000000 + 91 000000000000002000000060000000E0000001E0000003E0000007E000000FC0 + 91 00001F8000003F0000007E0000003F0000001F8000000FC0000007E0000003E0 + 91 000001E0000000E0000000600000002000000000000000000000000000000000 + 91 00000000 + 92 01FFFFFF01000001010000010100000101000001010000010100000101000001 + 92 0100000101000001010000010100000101000001010000010100000101000001 + 92 0100000101000001010000010100000101000001010000010100000101000001 + 92 01FFFFFF + 93 000000000000000000040000000E000000FBE00000F1E0000000000000000000 + 93 0000000000000000000001000000038000003EF800003C780000000000000000 + 93 000000000000000000040000000E000000FBE00000F1E0000000000000000000 + 93 00000000 + 94 0147C011004000220080002401020011000D001E0191DF07002520000022A000 + 94 004420000048407C00218000003E0000000000400007E1A000000220000005BC + 94 00000444000008A400F8090800000580000007C00000000200007C0D00000011 + 94 01C00035 + 95 0000000000000000000000000001800001E683E1001080000010800000228000 + 95 002A80000044BE1F007B000000190000002A0380004C02400048022000400290 + 95 004E0248002002680010014800080138000400A0003E0F94000000C000000100 + 95 00000200 + 96 0000000000080040007F03F80000000000000000000000000000400200307F03 + 96 38000000000000000000000000100040007F03F8000000000000000000000000 + 96 000040020183F81F00000000000000000000000000080040007F03F800000000 + 96 00000000 + 97 0080410200C840960035806C0002000000000000007C1F000000000000000000 + 97 00002C0000005A00003E653E0001C100000100800000C1000001808000009500 + 97 00004200001F1CF8000000000000000000080020003603EC00CC029400A2850A + 97 00804202 + 98 00000000000001F0003160000015C000007880000002E00001083E0F00080000 + 98 000800000000062C00000290001F0F3800000210000002E00000010000316100 + 98 001481000079C1000010800000070000000800000181F0070008000000000000 + 98 00000000 + 99 000000000003E7C0000000000010000000240000002401800018024000100240 + 99 0011F18000100100001001000010010000000100000001000000C00001F1203E + 99 000120000000C00000008000000080000000FC00003E80000000800000000000 + 99 00000000 +100 0000000C007C03E8000000080000400000028A000001240001F12E3E0003B400 +100 000258000004E1000000220001C16E030003B100000268000004300000002000 +100 003E23E00000000000000400000000420000004401E07C290000001800000008 +100 0000000A +101 0003E0A0000800A0001C02C0001C0580001C0080011C3E8F0028008000588080 +101 00094080000A0080000A7C80000A0080002C0080005800000008000000080000 +101 000BE09F000801C0000801C0000801C0000801C0007C025F000805C800000094 +101 00000080 +102 0000000000021F000017000000080004007000080028041000040300000E0320 +102 001200E00001001000008008003E07C800000010000000200000600000088000 +102 01C51F1800020000000180000000800000030000000400F80008000000000000 +102 00000000 +103 0000000000000000003E03E0000000000000000000888888000000000000F81E +103 0000000000222051000000000000000001F0F83E000000000000000000888888 +103 0000000000000000001F03E00000000000000000002222110000000001F0F83E +103 00000000 +104 00000000000F803E0000000000040000000E3E0000040000001F000000040000 +104 003F809F00040080007FC1C0000401C000FFE3E0000403E0000407F0000007F0 +104 0007CFF800000FF800001FFC0000040000000000003E03E00000000000000000 +104 00000000 +105 0000000000038000000863E0000740000030B000004BC8000029500000444800 +105 0012803E00010000000103700001014C007D02E800010E96000113F4000842D0 +105 00008888000004A00007C040000000400000004000000001003E005F00000040 +105 00000001 +106 0000000000080000009441020023A00000265000005480000023201000279000 +106 002D2040001AD0A00009E1500009423000090108001122590009021000090188 +106 00000210000002B000040530000000E000000040000000400040404200000040 +106 00000040 +107 00010060000101F00000020C000005B200204C65000000980000000000040821 +107 00000020000000200000002000000020004180620007C020000A7000000A7000 +107 0025C400001B342000600A000001000000010000000100000041100800010000 +107 00010000 +108 00000000000F810200086000000740000030B000004BC8100029600000444800 +108 0012820200010000000103700041010C000102E800010E96000113F400010A5A +108 00201111000004A0000000400000004000000040004082440000004000000040 +108 00000040 +109 00000000000000000004CC04004D308000366B0000D8CC0000AB2300016DB8C1 +109 00202300005144800088884000049000000221020001C0000000800000208810 +109 0000800000008000000080000002810000008000000080000040A00800008000 +109 00000000 +110 0000000000000000000000000040404000000000000000000004740000019800 +110 0002C600000635000002A4000010CB000001B6000082A90400010D000000FA00 +110 0008820000001000000010000000100000001000004090080000100000000000 +110 00000000 +111 0080450200C840960035806C0010000000000000004040200000000000000000 +111 00002C0000045A02000065000001C100020000800000C100004180A000009500 +111 0000404000001C00010101020000000000080020003603EC00CD829400A2850A +111 00804202 +112 00000000000000000020820400000080000001C000040882000002A0000001C0 +112 00000480000002A0004211C100070490001002A0000A81C00007008000124080 +112 000A80000007040800124000000A900000070000004200800002000000000000 +112 00004004 +113 0000075C004041F00000004000000F5E000003F800020040000A804000470000 +113 00020208001AC000000F800000020000003AE040000F800000020000007AF000 +113 001FC204000200000002004000000150002020E00000004000000358000201F0 +113 00000040 +114 000000000000004000080840000000E0000000E0000001F0004081F1000003F8 +114 000003F8000007FC000207FC01024FFE0007004000070000000F8000000F8000 +114 001FC204001FC000003FE000003FE000007FF020001000000000000000000000 +114 00101008 +115 0000000000040082000000800000014000000140002012200000022000000410 +115 00000410000088080000080800021FFC00020080004500100005000000088000 +115 0008820200104000001040000020200000202020007FF0000002000000000202 +115 00000000 +116 0000000000080000000840200014000000080000001C0000002A0000001C0402 +116 002A0000005D0000003E008000550080008A894200080080000001C0000002A0 +116 000001C0002042A1000005D0000003E00000055000020AA80000008000000000 +116 00402008 +117 000000000000000000FFFFF8009202480012024000020201000202000003FE00 +117 00040100001800800020003000401C08018066060000D2010001820000030200 +117 00020400000204000002080000023000001C4000000880000000900000028000 +117 00018000 +118 000000000000000000000000000000000000000000000018000FFFF800100038 +118 002000580040009A00FFFF390080013900800139009999390099993900999938 +118 0081810000000000000000000000000000000000000000000000000000000000 +118 00000000 +119 0000000000000000000000000000000000000000000000000000000000000000 +119 003FFFF80060000400900002010800010107FFFF010400010105EF790105EF79 +119 00C5EF790031EF790019EF790000000300000003000000000000000000000000 +119 00000000 +120 00000000000000000000000000000000000000000000000000000400000FFFE0 +120 00100050002000880040010400FFFE020080020200BE027200BEDB7200BEDA72 +120 00BEDA0200BE1800000000000000000000000000000000000000000000000000 +120 00000000 +121 000000000000000000000000000000000000FF800001C0E00003003000060030 +121 000C001800181C0C0010220C0010210C0010220C00181C0C0018000C000C000C +121 00060018000300700000FFC000000E0000000000000000000000000000000000 +121 00000000 +122 0000000000000000000000000000000000000000000000000000000000000000 +122 000000000001FF00000701C0001800600018C630001C1838003F7D9C00000000 +122 0000000000000000000000000000000000000000000000000000000000000000 +122 00000000 +123 0000000000000000000000000000000000000000000000000000280000002800 +123 0000280000001000000028000000280000004400000044000000820000008200 +123 0001110000011100000238800002388000047C4000047C40000C7E4000000000 +123 00000000 +124 000000000000000000000000000000000000000000007F800000818000010380 +124 0003FC8000020480000204800002648000026480000204800002048000020480 +124 00020500000206000003FE000000020000000200000002000000020000000200 +124 00000200 +125 000400200044422200248124001500A8000A0050001F00F8000000000003E01F +125 00000000000010010021111100409209008054050100280201807C0700000000 +125 01F00F80000400200044422200248124001500A8000A0050001F00F800000000 +125 00007C03 +126 012492490012492400924924009249240092492401B6DB6D0124924901249249 +126 01249249016DB6DB004924920049249200492492016DB6DB0124924901249249 +126 0124924901B6DB6D00924924009249240092492401B6DB6D0124924901249249 +126 01249249 +127 0000000000FFFFFE040000020080000200800002008000020083FF820083FF82 +127 008301820083018200830182008301820083FF820083FF820083000200830002 +127 0083000200830002008300020083000200830002008000020080000200FFFFFE +127 00000000 +128 0000000000000000000000000000000000000000000000000000000000000000 +128 00000010000000300000005000000090000FFFF000020210000FFFF000020010 +128 0002001000020010000000000000000000000000000000000000000000000000 +128 00000000 +129 00000000000000000000000001FFFFFF00210422004208240084104400880044 +129 0111FC8800120400000404000007FCC000040D200007FE2000040E400007FC81 +129 00040D820007FF02000C0E0400147F8C00600080007FFF000000000000000000 +129 00000000 +130 000000000000000000000000000000000000000000000000000070000000F800 +130 0000F800000000000000FFFC0000FFC00001FC000001FC000001FC000003FE00 +130 0003FE000007FF000007FF000007FF0000000000000000000000000000000000 +130 00000000 +131 002082080071C71C00FBEFBE0071C71C0020820800041041010E38E3019F7DF7 +131 0171C71C000410410061861800F3CF3C00F3CF3C0061861800000000000C30C3 +131 0112492401924924000C30C30022222A00777B77002222220088888801DDDDDD +131 00888888 +132 0022222201777777002222220088888801DDDDDD008888880186186002492491 +132 0049249101861860000000000030C30C0079E79E0079E79E0030C30C01041040 +132 018E38E101DF7DF3018E38E1010410400020820800F1C71C00FBEFBE0071C71C +132 00208208 +133 0000000000000000000000000000000000000000000000000000000000000000 +133 0000000000000000000000000000000000000000000000000000000000000000 +133 00000000000000000155555500AAAAAA00AAAAAA00AAAAAA00AAAAAA00AAAAAA +133 01555555 +134 0104000000F800000104000000F800000104000000F800000104000000F80000 +134 0104000000F800000104000000F800000104000000F800000104000000F80000 +134 0104000000F800000104000000F800000104000000F800000104000000F80000 +134 01040000 +135 015000000098000001240000004A00000193000000A480000049400000326000 +135 001490000009280000064C00000292000002A5000000C9800000524000002480 +135 0000193000000A48000004940000032600000149000000920000006400000029 +135 00000012 +136 000000140000003200000049000000A4000001930000024A0000052400000C98 +136 00001250000029200000648000009280000149000003260000049400000A4800 +136 001930000024A0000052400000C980000125000000920000004C000001280000 +136 00900000 +137 000000060000000900000015000000320000004C000000A80000019000000260 +137 0000054000000C800000130000002A0000006400000098000001500000032000 +137 0004C000000A800000190000002600000054000000C800000230000000B00000 +137 00400000 +138 0040000000A000000130000000C80000005400000026000000190000000A8000 +138 0004C0000003200000015000000098000000640000002A000000130000000C80 +138 000005400000026000000190000000A80000004C000000320000001500000009 +138 00000006 +139 0120000001E000000120000001E000000120000001E000000120000001E00000 +139 0120000001E000000120000001E000000120000001E000000120000001E00000 +139 0120000001E000000120000001E00000012000000120000001E0000001200000 +139 01E00000 +140 0000000000000000000000000000000000000000000000000000000000000000 +140 0000000000000000000000000000000000000000000000000000000000000000 +140 000000000000000000000000000000000000000001FFFFFF00AAAAAA00AAAAAA +140 01FFFFFF +141 0040000000200000011000000088000000400000002000000001000000008000 +141 0004400000022000000100000000800000000400000002000000110000000880 +141 0000040000000200000000100000000800000040000000220000001000000008 +141 00000000 +142 0000000000000008000000100000002200000044000000080000001000000200 +142 0000040000000880000011000000020000000400000080000001000000022000 +142 0004400000008000000100000020000000400000008000000110000000200000 +142 00400000 +143 0000000000000000000000000000000000000000000000000000000000000000 +143 0000000000000000000000000000000000000000000000000000000000000000 +143 000000000000000000000000000000000000000000F8F87C0000000000000000 +143 00F8F87C +144 0000000000000000012000000120000001200000012000000120000000000000 +144 0000000000000000012000000120000001200000012000000120000000000000 +144 0000000000000000000000000120000001200000012000000120000001200000 +144 00000000 +145 0000000400000008000000110000002200000044000000880000011000000220 +145 0000044000000880000011000000220000004400000088000001100000022000 +145 0004400000088000001100000022000000440000008800000110000000200000 +145 00400000 +146 0040000000200000011000000088000000440000002200000011000000088000 +146 0004400000022000000110000000880000004400000022000000110000000880 +146 0000044000000220000001100000008800000044000000220000001100000008 +146 00000004 +147 0120000001200000012000000120000001200000012000000120000001200000 +147 0120000001200000012000000120000001200000012000000120000001200000 +147 0120000001200000012000000120000001200000012000000120000001200000 +147 01200000 +148 0000000000000000000000000000000000000000000000000000000000000000 +148 0000000000000000000000000000000000000000000000000000000000000000 +148 000000000000000000000000000000000000000001FFFFFF0000000000000000 +148 01FFFFFF +149 0080000001C0000000E000000070000000380000001800000000000000000000 +149 000080000001C0000000E0000000700000003800000018000000000000000000 +149 00000080000001C0000000E00000007000000070000000180000000000000000 +149 00000000 +150 00000002000000070000000E0000001C00000038000000300000000000000000 +150 000002000000070000000E0000001C0000003800000030000000000000000000 +150 0002000000070000000E0000001C000000380000003000000000000000000000 +150 00000000 +151 0000000000000000000000000000000000000000000000000000000000000000 +151 0000000000000000000000000000000000000000000000000000000000000000 +151 00000000000000000000000000000000000000000000000001F1F9F000F8F8F8 +151 01F1F1F0 +152 0140000001C0000001C0000001C0000001C00000008000000000000000000000 +152 0140000001C0000001C0000001C0000001C00000008000000000000000000000 +152 0140000001C0000001C0000001C0000001C00000008000000000000000000000 +152 00000000 +153 010000000100000001000000010000000180000000C000000040000000400000 +153 00C000000080000000C0000000C00000004000000040000000C0000000C00000 +153 018000000180000000C0000000C0000000800000008000000180000001000000 +153 00000000 +154 0000000000000000000000000000000000000000000000000000000000000000 +154 0000000000000000000000000000000000000000000000000000000000000000 +154 000000000000000000000000000000000000000000000C0000007E000079C7CC +154 01CF007F +155 0000000100000003000000060000000C00000078000000C00000008000000080 +155 00000180000001000000070000000C00000038000000F0000000800000078000 +155 000C0000001800000010000000300000000000000020000000E0000001800000 +155 01800000 +156 010000000180000000C000000040000000700000001C00000004000000070000 +156 0001800000000000000040000000100000000400000000000000010000000180 +156 00000080000000E00000003800000008000000080000000C0000000400000007 +156 00000001 +157 0180000001800000018000000180000001800000018000000000000000000000 +157 0000000001800000018000000180000001800000018000000000000000000000 +157 0000000001800000018000000180000001800000018000000180000000000000 +157 00000000 +158 0000000000000000000000000000000000000000000000000000000000000000 +158 0000000000000000000000000000000000000000000000000007000000070000 +158 0007000000070000000200000002000000020000000200000002000001FAFC7C +158 01FAFC7C +159 00000000000000000000000C000000180000003000000060000000C000000000 +159 000700000007060000070C000007180000023000000260000002C00000020000 +159 00020000000200000002000000180000003000000060000000C0000001800000 +159 01000000 +160 0000000000000000000000000030000000180000000C00000006000000030000 +160 00000000000000E0000060E0000030E0000010E000000C400000064000000340 +160 00000040000000400000004000000040000000180000000C0000000600000003 +160 00000001 +161 0120000000940000004C00000124000000960000004D00000024800000164000 +161 000D200000049000000648E0000524E0000092E0000049E0000024C000001240 +161 00000960000004D00000024800000B20000000D2000000490000006400000052 +161 00000009 +162 00000009000000520000006400000049000000D20000016400000248000004D0 +162 00000960000E1240000E24C0000E4940000E9200000524000006480000049000 +162 000D20000016400000248000004D00000096000001240000004C000000940000 +162 01200000 +163 0000000000000000000000000000000000000000000000000000000000000000 +163 000000000000000000000000000000000000000000000000000E0000000E0000 +163 000E0000000E00000004004001FFFFFF0004004001FFFFFF0004004001FFFFFF +163 00040040 +164 00A8000000A8000000AC000000A8000000B8000000A8000000E8000000A80000 +164 01A8000000A8000000A8000000A8000000A8000000A8000000A8000000A80000 +164 00AC000000A8000000B8000000A8000000E8000000A8000001A8000000A80000 +164 00A80000 +165 0054076C0039082400154235001382AE009110740081102400A5543501C3B82E +165 008111040089110400AB554401DC3B80008811100088111000889554002AA3B8 +165 001DC11000088111008889550148883B0142AA1100E1DC150140889300408881 +165 0044AAA1 diff --git a/symbols/misc3.sym b/symbols/misc3.sym new file mode 100644 index 0000000..8eafb28 --- /dev/null +++ b/symbols/misc3.sym @@ -0,0 +1,27 @@ +-3 -3 3x3symbol-1 dot on + 1 000000020000 + 2 000500020005 + 3 000400020001 + 4 000100020004 + 5 000500000005 + 6 000500050005 + 7 000700000007 + 8 000600020003 + 9 000300020006 + 10 000700020007 + 11 000500050002 + 12 000200050005 + 13 000200050002 + 14 000700050007 + 15 000700070007 + 16 000000000000 + 17 000200020002 + 18 000000070000 + 19 000700060004 + 20 000700010001 + 21 000400040007 + 22 000600060000 + 23 000200070002 + 24 000500070005 + 25 000700010007 + 26 000700050005 diff --git a/symbols/misc8.sym b/symbols/misc8.sym new file mode 100644 index 0000000..b3af2d2 --- /dev/null +++ b/symbols/misc8.sym @@ -0,0 +1,44 @@ + -8 -8 79/11/07.SYMBOLS AND TONES + 1 081 042 024 018 018 024 042 081 + 2 018 018 018 0FF 0FF 018 018 018 + 3 055 0AA 055 0AA 055 0AA 055 0AA + 4 041 082 004 008 010 020 041 082 + 5 082 041 020 010 008 004 082 041 + 6 082 043 024 05A 05A 024 0C2 041 + 7 000 042 03C 024 024 03C 042 000 + 8 081 0FF 081 091 089 081 0FF 081 + 9 001 00E 038 0E0 001 00E 038 0E0 + 10 080 070 01C 007 080 070 01C 007 + 11 018 024 042 052 04A 042 024 018 + 12 000 03C 000 055 0AA 000 03C 000 + 13 008 010 020 041 082 004 008 010 + 14 008 014 022 041 082 044 028 010 + 15 000 03E 042 042 042 042 07C 000 + 16 0FF 081 0BD 0A5 0A5 0BD 081 0FF + 17 000 066 066 000 000 066 066 000 + 18 000 066 066 018 018 066 066 000 + 19 041 0DA 024 018 018 024 05B 082 + 20 040 0C0 020 010 008 004 003 002 + 21 002 003 004 008 010 020 0C0 040 + 22 081 081 081 0FF 0FF 081 081 081 + 23 0FF 018 018 018 018 018 018 0FF + 24 024 024 0FF 024 024 0FF 024 024 + 25 000 000 000 0FF 0FF 000 000 000 + 26 018 018 018 018 018 018 018 018 + 27 0C3 0FF 000 0DB 0DB 000 0FF 0C3 + 28 0DB 0DB 000 0DB 0DB 000 0DB 0DB + 29 000 000 000 018 018 000 000 000 + 30 0FF 0FF 0FF 0FF 0FF 0FF 0FF 0FF + 31 0FF 000 000 0FF 000 000 000 0FF + 32 089 089 089 089 089 089 089 089 + 33 0FF 000 0FF 000 0FF 000 000 0FF + 34 095 095 095 095 095 095 095 095 + 35 081 042 024 0FF 018 024 042 081 + 36 091 052 034 018 018 034 052 091 + 37 078 078 000 01E 01E 000 078 078 + 38 000 0AA 0AA 0FF 0FF 055 055 000 + 39 000 018 018 0DB 0DB 0C3 0C3 000 + 40 099 099 000 099 099 000 099 099 + 41 0FF 0E7 0E7 099 099 0E7 0E7 0FF + 42 0FF 0FF 0C3 0C3 0C3 0C3 0FF 0FF + 43 000 000 000 018 000 000 000 000 diff --git a/symbols/tone10a.sym b/symbols/tone10a.sym new file mode 100644 index 0000000..e3ebc64 --- /dev/null +++ b/symbols/tone10a.sym @@ -0,0 +1,145 @@ +-10 -10 79/11/07.MLMIS S45 TONE DECK + 1 0038004400820129010101290082004400380000 + 2 019301930010003801FF00380010019301930000 + 3 0000003000480084010201020084004800300000 + 4 000001FE01FE003000300030003001FE01FE0000 + 5 00C1000C00600100001C00C00006017100000000 + 6 0092016D016D0092016D016D0092016D016D0000 + 7 010000000000000000000000000A000201000000 + 8 01EF0129012901EF000001EF0129012901EF0000 + 9 019300100000003801FF00380000001001930000 + 10 0000003000FC00AC01C6018E00D400FC00300000 + 11 0038005400EE015501BB015500EE005400380000 + 12 002C00D200A6004C00D200340030003000780000 + 13 011100AA004400000000011100AA004400000000 + 14 0201013200B4007801FE01FE007800B401320201 + 15 003F00110011001101FF01FF006000600060007C + 16 0000010200000000001000000000000001020000 + 17 0000000000200050008800440028001000000000 + 18 0048004800480FFF004800480FFF004800480048 + 19 007800CC01860303023102310303018600CC0078 + 20 000000FC00FC00CC01A6019600CC00FC00FC0000 + 21 01FE02CD034B0387020102010387034B02CD01FE + 22 0140004000410190000000270002000000400200 + 23 000001FE01FE018601B601B6018601FE01FE0000 + 24 018300100000003800AA00380000001001830000 + 25 00E700A600EC000800100037006500E700000000 + 26 0000000000000030007800FC01FE000000000000 + 27 0000008200000028000000280000008200000000 + 28 01FF0000000001FF0000000001FF000000000000 + 29 01C701C701C700380038003801C701C701C70000 + 30 01FF01FF018301BB01AB01BB018301FF01FF0000 + 31 000000300030003001FE01FE0030003000300030 + 32 003800540082011101AB01110082005400380000 + 33 000002AA00000155000002AA00000155000002AA + 34 0229004A0100000601240025001B011100080002 + 35 0000000000780084010201020084007800000000 + 36 0038007C00FE01FF01FF01FF00FE007C00380000 + 37 03FF03CF03CF03CF0201020103CF03CF03CF03CF + 38 02010302018600CC00780030007800CC01860303 + 39 00B8007C00F800FC00FE007800B0003000780000 + 40 00000030004800B4014A014A00B4004800300000 + 41 018300100010003800EE00380010001001830000 + 42 0092024900920249009202490092024900920249 + 43 000000FC00FC00FC01FE01FE00FC00FC00FC0000 + 44 0038004400D601290155012900D6004400380000 + 45 0000000000000030004800480030000000000000 + 46 01FF01FF0193019301FF0193019301FF01FF0000 + 47 0053004C034000CB014603040223020202590090 + 48 0000000000440000000000000044000000000000 + 49 0000000C00E00000000F000000600000001C0000 + 50 01FE00FD02790333038703CF03870333027900FC + 51 0010000000000028008200280000000000100000 + 52 00000000000000F800F800F800F800F800000000 + 53 000001FE01FE01FE01CE01CE01FE01FE01FE0000 + 54 02AA0155015502AA0155015502AA0155015502AA + 55 0101008200440028001000AA01C701EF01C70000 + 56 0000013200000000013201320000000001320000 + 57 03FF03FF03FF03DF03AF035702AB03FF03FF03FF + 58 001000A800C400EE0129012901E9010901FF0000 + 59 0000000000100000008000040000002000000000 + 60 0293023A00880058037A00EE0382018A00E401A6 + 61 03FF03FF03FF0307030703070307030703FF03FF + 62 000000100010003800EE00380010001000000000 + 63 01FF01FF019301BB01FF01BB019301FF01FF0000 + 64 01FF000001FF000001FF000001FF000001FF0000 + 65 0008001C002A0028001C000A002A001C00080000 + 66 0000000000440000000000000000000000000000 + 67 000000200020002001FE00200020002000200000 + 68 0030003000300030003F003F0000000000000000 + 69 00200020002000AA01FE03FE03FE01FC007C007C + 70 015502AA015502AA015502AA015502AA015502AA + 71 007C007C0060006000600060007C007C00000000 + 72 00000008000C007E006C00080000000000000000 + 73 03FF03DF03DF03DF020103DF03DF03DF03DF03FF + 74 034A02EB00C103D6013B018C039701E3027A0231 + 75 0000007E007E00000000007E007E000000000000 + 76 000000000000000003FF03FF0000000000000000 + 77 0008001C003E0008000800080008000000000000 + 78 00000004000C001800300018000C000400000000 + 79 03EE03DE02BF03BB017F037E021A02FF00F102FF + 80 0000000000000020005000A80154000000000000 + 81 0000000000000000007E007E0000000000000000 + 82 0030003000300030003000300030003000300030 + 83 03FF03FF03FF03FF03FF03FF03FF03FF03FF03FF + 84 000C001C0038003000300038001C000C00000000 + 85 007C007C000C000C000C000C007C007C00000000 + 86 03FF03FF0303037B037B037B037B030303FF03FF + 87 0004007E007E00080010007E007E002000000000 + 88 00060006000C0018001800300060006000000000 + 89 000000920054003800EE00380054009200000000 + 90 0008000800080008003E001C0008000000000000 + 91 0000000000000000003F003F0030003000300030 + 92 03BB02EE03BB02FE03FB02FE03FB02FE03BB02EE + 93 0000001800180000000000180018000000000000 + 94 01B5019302CF02BD01FC03F7001D03BE034F0361 + 95 0000000000000000003000300000000000000000 + 96 01FF01FF01FF01FF01FF01FF01FF01FF01FF0000 + 97 00300038001C000C000C001C0038003000000000 + 98 000000180018007E007E00180018000000000000 + 99 01FF01FF0111013901FF0139011101FF01FF0000 +101 000000000000000003F003F00030003000300030 +102 021F03EF03FF02FF03FE019B03FF03FF02FE01BF +103 0000002000300018000C00180030002000000000 +104 00000000000000000000001C0014001C000C0000 +105 003000300030003003F003F00000000000000000 +106 0000000000000010000000000000000000000000 +107 03FF02FD03FF03FF03EF03FF03FF03FF02FD03FF +108 0038004400820101010100010082004400380000 +109 0000000000240000000000240000000000000000 +110 0018003C0066006600660066003C001800000000 +111 0018003800380018001800180018003C00000000 +112 003C007E00660006003C0060007E007E00000000 +113 003C007E0066000C000E0066007E003C00000000 +114 000C001C003C006400E400FC000C001E00000000 +115 007E007E0060007C00060066007E003C00000000 +116 003C007E0060007C00660066007E003C00000000 +117 007E007E0046000C000C000C000C000C00000000 +118 003C007E0066003C00660066007E003C00000000 +119 003C007E00660066003E0006007E003C00000000 +120 0018003C00660066007E007E006600E700000000 +121 00FC007E0066007C00660066007E00FC00000000 +122 003C007E0067006000600067007E003C00000000 +123 00FC007E0066006600660066007E00FC00000000 +124 00FE007E0062007800780062007E00FE00000000 +125 00FE007E0062007800780060006000F000000000 +126 003C007E00670060006F0066007E003C00000000 +127 00E700660066007E007E0066006600E700000000 +128 003C001800180018001800180018003C00000000 +129 000F00060006000600060066007E003C00000000 +130 00E70066006C0078007C0066006600E700000000 +131 00F000600060006000600062007E00FE00000000 +132 01C700EE00FE00BA00D600C600C601C700000000 +133 00C700660076007E007E006E006600E300000000 +134 003C007E0066006600660066007E003C00000000 +135 00FC007E00660066007E007C006000F000000000 +136 003C007E006600660066006C007E003600000000 +137 00FC007E00660066007C007E006600E700000000 +138 003C007E00620078001E0046007E003C00000000 +139 00FF00FF00990018001800180018003C00000000 +140 00E700660066006600660066007E003C00000000 +141 00E7006600660066003C003C0018001800000000 +142 01C700C600D600D600FE007C006C006C00000000 +143 00E700660024001800180024006600E700000000 +144 00E70066007E003C001800180018003C00000000 +145 00FE00FE008C00180030006200FE00FE00000000 diff --git a/symbols/tone10b.sym b/symbols/tone10b.sym new file mode 100644 index 0000000..b3bec56 --- /dev/null +++ b/symbols/tone10b.sym @@ -0,0 +1,19 @@ +-10 -10 79/11/07.TONES LIGHT TO DARK FOR POPULATION MAPS + 1 0000000000000000000000000018001800000000 + 2 0000000000200050008800440028001000000000 + 3 000000100010003800EE00380010001000000000 + 4 00060006000C0018001800300060006000000000 + 5 000000300030003001FE01FE0030003000300030 + 6 02010302018600CC00780030007800CC01860303 + 7 0048004800480FFF004800480FFF004800480048 + 8 01C701C701C700380038003801C701C701C70000 + 9 01EF0129012901EF000001EF0129012901EF0000 + 10 02AA0155015502AA0155015502AA0155015502AA + 11 01FE02CD034B0387020102010387034B02CD01FE + 12 000000FC00FC00FC01FE01FE00FC00FC00FC0000 + 13 03FF03FF03FF0307030703070307030703FF03FF + 14 03FF03FF0303037B037B037B037B030303FF03FF + 15 03FF03FF03FF03DF03AF035702AB03FF03FF03FF + 16 03FF03FF03FF03FF03FF03FF03FF03FF03FF03FF + 17 0000000000000000001000000000000000000000 + 18 000000000301038300C6007C0038000000000000 diff --git a/symbols/tone10c.sym b/symbols/tone10c.sym new file mode 100644 index 0000000..23c2536 --- /dev/null +++ b/symbols/tone10c.sym @@ -0,0 +1,14 @@ + -10 -10 79/11/07.DOTS LIGHT TO DARK + 1 0000000000000000003000300000000000000000 + 2 0000000000000030004800480030000000000000 + 3 0000000000200050008800440028001000000000 + 4 0000000000780084010201020084007800000000 + 5 0000003000480084010201020084004800300000 + 6 0038004400820129010101290082004400380000 + 7 00000030004800B4014A014A00B4004800300000 + 8 003800540082011101AB01110082005400380000 + 9 0038004400D601290155012900D6004400380000 + 10 0038005400EE015501BB015500EE005400380000 + 11 0000003000FC00AC01C6018E00D400FC00300000 + 12 004000C801860303023102310303018600CC0078 + 13 0038007C00FE01FF01FF01FF00FE007C00380000 diff --git a/symbols/tone10d.sym b/symbols/tone10d.sym new file mode 100644 index 0000000..a063b6d --- /dev/null +++ b/symbols/tone10d.sym @@ -0,0 +1,48 @@ + -10 -10 79/11/07.ASSORTED TONES, SYMBOLS AND PICTURES + 1 0000000000000000007E007E0000000000000000 + 2 0000007E007E00000000007E007E000000000000 + 3 0004007E007E00080010007E007E002000000000 + 4 000001FE01FE003000300030003001FE01FE0000 + 5 01FF0000000001FF0000000001FF000000000000 + 6 01FF000001FF000001FF000001FF000001FF0000 + 7 0000000000000000003000300000000000000000 + 8 0000001800180000000000180018000000000000 + 9 000000180018007E007E00180018000000000000 + 10 000000200020002001FE00200020002000200000 + 11 000000100010003800EE00380010001000000000 + 12 000000300030003001FE01FE0030003000300030 + 13 0201013200B4007801FE01FE007800B401320201 + 14 0048004800480FFF004800480FFF004800480048 + 15 01FE02CD034B0387020102010387034B02CD01FE + 16 03FF03CF03CF03CF0201020103CF03CF03CF03CF + 17 03FF03DF03DF03DF020103DF03DF03DF03DF03FF + 18 0000000000000030004800480030000000000000 + 19 0000003000480084010201020084004800300000 + 20 007800CC01860303023102310303018600CC0078 + 21 003800540082011101AB01110082005400380000 + 22 0000000000000020005000A80154000000000000 + 23 0000000000000030007800FC01FE000000000000 + 24 00000000000000F800F800F800F800F800000000 + 25 0038007C00FE01FF01FF01FF00FE007C00380000 + 26 000000FC00FC00FC01FE01FE00FC00FC00FC0000 + 27 000001FE01FE01FE01CE01CE01FE01FE01FE0000 + 28 03FF03FF03FF0307030703070307030703FF03FF + 29 03FF03FF0303037B037B037B037B030303FF03FF + 30 01FF01FF01FF01FF01FF01FF01FF01FF01FF0000 + 31 034A02EB00C103D6013B018C039701E3027A0231 + 32 02AA0155015502AA0155015502AA0155015502AA + 33 0000000000000000007E007E0000000000000000 + 34 0000000000000000003000300000000000000000 + 35 0000003000480084010201020084004800300000 + 36 0000000000200050008800440028001000000000 + 37 0000000000000020005000A80154000000000000 + 38 00000008000C007E006C00080000000000000000 + 39 0008001C002A0028001C000A002A001C00080000 + 40 0010000000000028008200280000000000100000 + 41 0008001C003E0008000800080008000000000000 + 42 000000100010003800EE00380010001000000000 + 43 003F00110011001101FF01FF006000600060007C + 44 0101008200440028001000AA01C701EF01C70000 + 45 002C00D200A6004C00D200340030003000780000 + 46 001000A800C400EE0129012901E9010901FF0000 + 47 011100AA004400000000011100AA004400000000 diff --git a/symbols/tone5.sym b/symbols/tone5.sym new file mode 100644 index 0000000..e80e955 --- /dev/null +++ b/symbols/tone5.sym @@ -0,0 +1,98 @@ +-5 -5 79/11/07.MODIFIED ALPHANUMERICS WITH TONES + 1 000 006 009 00F 009 + 2 000 00E 00E 009 00E + 3 000 007 008 008 007 + 4 000 00E 009 009 00E + 5 000 00F 00E 008 00F + 6 000 00F 008 00E 008 + 7 000 006 008 009 007 + 8 000 009 009 00F 009 + 9 000 007 002 002 007 + 10 000 007 002 002 00C + 11 000 00A 00C 00A 009 + 12 000 008 008 008 00F + 13 000 00A 015 015 015 + 14 000 009 00D 00B 009 + 15 000 006 009 009 006 + 16 000 00E 009 00E 008 + 17 000 006 009 00A 005 + 18 000 00E 009 00E 009 + 19 000 00E 00C 002 00E + 20 000 00F 004 004 004 + 21 000 009 009 009 006 + 22 000 009 009 00A 004 + 23 000 015 00A 00E 00A + 24 000 009 006 006 009 + 25 000 00A 00A 004 004 + 26 000 00F 002 004 00F + 27 000 00E 00A 00A 00E + 28 000 004 004 004 004 + 29 000 006 001 006 007 + 30 000 00E 006 002 00E + 31 000 00A 00E 002 002 + 32 000 00E 00C 002 00C + 33 000 008 00E 00A 00E + 34 000 00E 002 002 002 + 35 000 00E 00E 00A 00E + 36 000 00E 00A 00E 002 + 37 000 004 00E 004 000 + 38 000 000 00E 000 000 + 39 000 00F 00F 00F 00F + 40 000 001 002 004 008 + 41 000 004 008 008 004 + 42 000 004 002 002 004 + 43 004 00E 00C 006 00E + 44 000 00E 000 00E 000 + 46 000 000 000 00C 004 + 47 000 000 000 000 004 + 48 03F 03F 03F 03F 03F + 49 000 00C 008 008 00C + 50 000 006 002 002 006 + 51 000 004 000 004 000 + 52 002 00F 006 00F 004 + 53 007 007 007 007 007 + 54 007 007 00F 00F 007 + 55 000 000 004 006 007 + 56 004 00E 015 004 004 + 57 000 000 000 03F 03F + 58 000 000 000 020 038 + 59 038 030 020 000 000 + 60 03F 03F 03F 03E 03C + 61 03F 03C 038 030 030 + 62 030 030 030 038 03E + 63 020 030 038 03C 03E + 64 00D 013 00A 014 013 + 65 00A 00A 00A 00A 000 + 66 000 015 00A 000 000 + 67 000 003 000 00C 000 + 68 011 015 01F 015 011 + 69 01F 015 01B 015 01F + 70 000 00A 000 00A 000 + 71 01F 011 015 011 01F + 72 01F 01F 01F 01F 01F + 73 000 000 004 000 000 + 74 000 03F 000 000 03F + 75 012 012 012 012 012 + 76 008 010 020 001 002 + 77 004 002 001 020 010 + 78 03F 03F 03F 03F 03F + 79 02A 015 02A 015 02A + 80 02A 000 015 000 02A + 81 024 012 009 024 012 + 82 009 012 024 009 012 + 83 01C 038 031 023 007 + 84 00E 007 023 031 038 + 85 038 030 020 001 003 + 86 007 003 001 020 030 + 87 030 018 00C 006 003 + 88 003 006 00C 018 030 + 89 008 010 020 001 002 + 90 004 002 001 020 010 + 91 00C 018 030 021 003 + 92 00C 006 003 021 030 + 93 001 002 004 008 010 + 94 020 010 008 004 002 + 95 003 007 00E 01C 038 + 96 030 038 01C 00E 007 + 97 000 009 002 004 009 + 98 000 00A 000 00A 000 diff --git a/symbols/tone6a.sym b/symbols/tone6a.sym new file mode 100644 index 0000000..65aa2d5 --- /dev/null +++ b/symbols/tone6a.sym @@ -0,0 +1,227 @@ + -6 -6 79/11/07.ASSORTED TONES AND SYMBOLS + 1 000 01F 01F 011 01F 01F + 2 000 006 009 009 006 000 + 3 000 015 00A 00E 00E 000 + 4 000 010 00C 00C 002 000 + 5 000 01C 014 008 008 000 + 6 000 00E 00A 00A 00E 000 + 7 000 004 00E 004 000 000 + 8 000 000 01E 01E 000 000 + 9 03F 03F 03F 03F 03F 03F + 10 000 001 002 004 008 000 + 11 000 006 01E 018 01E 006 + 12 000 008 007 007 008 000 + 13 004 00E 00C 006 00E 000 + 14 000 00E 000 00E 000 000 + 15 000 01B 01B 004 01B 01B + 16 000 006 00B 019 00B 006 + 17 000 004 000 004 000 000 + 18 000 002 00F 006 00F 004 + 19 000 002 00F 00A 000 000 + 20 000 000 01F 000 000 000 + 21 000 017 007 012 007 017 + 22 000 004 01F 015 004 004 + 23 000 00A 015 015 00A 000 + 24 000 002 006 008 006 002 + 25 000 008 004 002 004 008 + 26 000 01F 00E 00F 003 000 + 27 000 003 00B 004 01A 019 + 28 000 01F 015 011 015 01F + 29 000 00A 00A 00A 00A 000 + 30 000 015 00A 000 000 000 + 31 000 003 000 00C 000 000 + 32 000 011 015 01F 015 011 + 33 000 01F 015 01B 015 01F + 34 000 01F 011 015 011 01F + 35 000 000 004 000 000 000 + 36 000 01F 000 000 01F 000 + 37 000 012 012 012 012 012 + 38 000 002 005 00A 014 008 + 39 000 008 014 00A 005 002 + 40 000 015 00A 015 00A 015 + 41 000 00B 011 015 01B 00B + 42 000 012 009 004 012 009 + 43 000 012 00C 012 00C 012 + 44 000 00E 01D 01B 017 00E + 45 000 00E 017 01B 01D 00E + 46 000 01D 01D 011 017 017 + 47 000 00E 015 01F 015 00E + 48 000 01A 017 015 015 01D + 49 000 003 006 00C 018 000 + 50 000 018 00C 006 003 000 + 51 000 00E 01B 015 01B 00E + 52 000 00A 000 00A 000 000 + 53 000 004 004 004 004 004 + 54 000 00E 006 00C 00C 00C + 55 000 00E 00A 01B 011 01F + 56 000 00E 01D 003 01D 00E + 57 000 00D 013 00A 014 013 + 58 000 01B 01F 00E 01F 01B + 59 000 004 000 004 000 004 + 60 000 004 00A 004 00A 004 + 61 000 004 00A 015 00A 004 + 62 000 009 002 004 009 000 + 64 000 01A 016 01A 016 01A + 65 000 004 01B 015 01B 004 + 66 000 012 00C 00C 012 01E + 67 000 005 00E 01F 00E 014 + 68 000 01E 002 00B 002 01E + 69 000 008 014 015 014 008 + 70 000 004 002 01D 002 004 + 71 000 004 00E 01B 00E 004 + 72 000 010 01F 013 01F 010 + 73 000 01C 01F 019 01F 01C + 74 000 01F 01F 00A 00A 000 + 75 000 00B 018 01E 018 00B + 76 000 00E 015 011 00A 004 + 77 000 01E 017 011 01F 00F + 78 000 01E 01E 019 007 000 + 79 000 01F 01B 00A 00E 004 + 80 000 018 017 00B 017 018 + 81 000 00E 001 009 006 00C + 82 000 00E 00E 00A 011 01F + 83 000 004 00E 01B 00E 004 + 84 000 00F 018 013 01E 004 + 85 000 01E 00E 00E 012 000 + 86 000 01E 006 01A 03A 030 + 87 000 004 00E 011 015 00A + 88 000 008 018 005 003 007 + 89 000 01C 014 01C 000 000 + 90 000 01F 01F 011 01F 01F + 91 000 004 01B 01B 01B 004 + 92 000 00C 01E 00C 000 000 + 93 000 00E 00E 011 00E 00E + 94 000 01C 016 01F 016 01C + 95 000 008 01F 009 009 00F + 96 000 00E 00A 00A 00A 01E + 97 000 01B 00B 00B 00B 00F + 98 000 01F 011 012 011 01F + 99 000 008 014 01C 008 00F +100 008 014 01C 008 00F 000 +101 03F 021 027 02B 02F 03F +102 03D 006 003 039 029 039 +103 03E 020 02C 024 02C 020 +104 03F 030 02E 02E 02E 021 +105 014 03E 022 03E 014 014 +106 03F 02E 02E 02E 02E 02E +108 000 03E 03A 03E 022 03E +109 020 010 008 007 03D 007 +110 000 00C 012 01B 003 000 +111 020 011 00E 00A 00E 001 +112 034 036 006 01C 01C 018 +113 004 00E 01F 004 00C 000 +114 020 013 00F 00F 01C 01D +115 03E 014 014 014 03E 000 +116 03C 03C 020 038 00C 000 +117 000 00A 015 015 015 00A +118 000 006 009 009 006 000 +119 000 010 00C 00C 002 000 +120 000 01C 014 008 008 000 +121 000 00E 00A 00A 00E 000 +122 000 004 00E 004 000 000 +123 000 000 01E 01E 000 000 +124 000 00F 00F 00F 00F 000 +125 000 001 002 004 008 000 +126 000 006 01E 018 01E 006 +127 000 008 007 007 008 000 +128 004 00E 00C 006 00E 000 +129 000 00E 000 00E 000 000 +130 020 01B 01B 004 01B 01B +131 000 00E 01E 03E 01E 00E +132 000 004 000 004 000 000 +133 002 00F 006 00F 004 000 +134 000 002 00F 00A 000 000 +135 000 000 01F 000 000 000 +136 017 007 012 007 017 000 +137 004 01F 015 004 004 000 +138 000 01C 02A 02A 01C 000 +139 002 006 008 006 002 000 +140 008 004 002 004 008 000 +141 000 03E 016 01E 006 000 +142 000 013 00F 03C 032 000 +143 020 02E 02A 02E 020 03F +144 00A 00A 00A 00A 000 000 +145 000 015 00A 000 000 000 +146 000 003 000 00C 000 000 +147 011 015 01F 015 011 000 +148 01F 015 01B 015 01F 000 +149 01F 011 015 011 01F 000 +150 000 000 004 000 000 000 +151 000 03F 000 000 03F 000 +152 012 012 012 012 012 012 +153 008 010 020 001 002 004 +154 004 002 001 020 010 008 +155 02A 015 02A 015 02A 015 +156 01C 022 02A 036 01C 000 +157 024 012 009 024 012 009 +158 000 012 00C 012 00C 012 +159 01C 038 031 023 007 00E +160 00E 007 023 031 038 01C +161 038 030 020 001 003 007 +162 00E 015 01F 015 00E 000 +163 036 021 02C 00D 02D 021 +164 003 007 00E 01C 038 030 +165 030 038 01C 00E 007 003 +166 000 009 002 004 009 000 +167 000 00A 000 00A 000 000 +168 004 004 004 004 004 000 +169 00E 006 00C 00C 00C 000 +170 01C 014 01C 02A 022 000 +171 01C 01E 01E 01E 01C 000 +172 00D 013 00A 014 013 000 +173 033 03F 01E 01E 03F 033 +174 004 000 004 000 004 000 +175 004 00A 004 00A 004 000 +176 004 00A 015 00A 004 000 +177 00E 01B 015 01B 00E 000 +180 000 01A 016 01A 016 01A +181 000 00C 033 02D 033 00C +182 000 012 00C 00C 012 01E +183 005 00E 01F 00E 014 000 +184 000 03C 004 017 004 03C +185 008 008 014 015 014 008 +186 004 002 01D 01D 002 004 +187 004 00E 01B 01B 00E 004 +188 020 038 028 028 038 020 +189 038 03E 03A 03A 03E 038 +190 03F 03F 03F 012 012 000 +191 017 030 03E 030 017 010 +192 018 02A 022 014 008 000 +193 03F 038 03F 007 03F 000 +194 03C 03C 032 00E 000 000 +195 000 03F 033 012 01E 00C +196 014 016 017 00F 016 010 +197 01C 01E 001 031 00E 00C +198 01C 01C 014 022 03E 03E +199 008 008 01C 037 01C 008 +200 000 02F 018 013 01E 004 +201 007 03F 007 00A 012 022 +202 000 01E 006 01A 03A 030 +203 008 03E 001 009 01D 023 +204 018 038 038 005 003 007 +205 000 01C 014 01C 000 000 +206 03E 03E 022 03E 03E 000 +207 008 008 036 036 036 008 +208 000 00C 01E 00C 000 000 +209 00C 00C 033 033 033 00C +210 01C 016 01F 016 01C 000 +211 008 01F 009 009 00F 000 +212 008 03B 00A 00A 00A 00E +213 01B 00B 00B 00B 00F 000 +214 03F 03F 021 022 021 03F +215 008 014 01C 008 00F 000 +216 03F 021 027 02B 02F 03F +217 03D 006 003 039 029 039 +218 03E 020 02C 024 02C 020 +219 03F 030 02E 02E 02E 021 +220 014 03E 022 03E 014 014 +221 03F 02E 02E 02E 02E 02E +222 000 03E 03A 03E 022 03E +223 020 010 008 007 03D 007 +224 000 00C 012 01B 003 000 +225 020 011 00E 00A 00E 001 +226 034 036 006 01C 01C 018 +227 004 00E 01F 004 00C 000 +228 020 013 00F 00F 01C 01D +229 03E 014 014 014 03E 000 +230 03C 03C 020 038 00C 000 diff --git a/symbols/tone6b.sym b/symbols/tone6b.sym new file mode 100644 index 0000000..6884934 --- /dev/null +++ b/symbols/tone6b.sym @@ -0,0 +1,70 @@ + -6 -6 79/11/07.ASSORTED TONES FOR PLOTTING + 1 00D 013 00A 014 013 000 + 2 00A 00A 00A 00A 000 000 + 3 000 015 00A 000 000 000 + 4 000 003 000 00C 000 000 + 5 011 015 01F 015 011 000 + 6 01F 015 01B 015 01F 000 + 7 000 00A 000 00A 000 000 + 8 01F 011 015 011 01F 000 + 9 01F 01F 01F 01F 01F 000 + 10 000 000 004 000 000 000 + 11 000 03F 000 000 03F 000 + 12 012 012 012 012 012 012 + 13 008 010 020 001 002 004 + 14 004 002 001 020 010 008 + 15 024 012 009 024 012 009 + 16 009 012 024 009 012 024 + 17 01C 038 031 023 007 00E + 18 00E 007 023 031 038 01C + 19 038 030 020 001 003 007 + 20 007 003 001 020 030 038 + 21 021 012 00C 00C 012 021 + 22 033 03F 01E 01E 03F 033 + 23 004 000 004 000 004 000 + 24 000 00A 004 00A 000 000 + 25 004 00A 000 00A 004 000 + 26 004 00A 004 00A 004 000 + 27 004 00A 015 00A 004 000 + 28 00E 01B 015 01B 00E 000 + 29 00C 012 012 012 00C 000 + 30 011 00A 015 00A 011 000 + 31 03F 03F 03F 03F 03F 03F + 32 00D 01B 036 02D 01B 036 + 33 02C 036 01B 02D 036 01B + 34 030 018 00C 006 003 001 + 35 003 006 00C 018 030 008 + 36 00C 018 030 021 003 006 + 37 00C 006 003 021 030 018 + 38 003 007 00E 01C 038 030 + 39 030 038 01C 00E 007 003 + 40 007 00F 01F 03E 03C 038 + 41 038 03C 03E 01F 00F 007 + 42 008 008 01C 01C 03E 008 + 43 02D 012 02D 02D 012 02D + 44 015 02A 015 02A 015 02A + 45 000 000 008 01C 03E 000 + 46 000 03F 000 000 03F 000 + 47 000 000 000 000 03F 000 + 48 03F 000 03F 03F 000 03F + 49 028 002 014 001 028 002 + 50 008 008 03E 008 008 000 + 51 000 002 008 000 004 000 + 52 01F 03B 02F 03E 037 03D + 54 000 01C 01C 01C 000 000 + 55 008 01C 03E 01C 008 000 + 56 020 020 010 001 008 002 + 57 003 003 00C 00C 030 030 + 58 000 01E 01E 01E 01E 000 + 59 03F 03F 021 021 03F 03F + 60 024 00A 011 024 012 029 + 61 001 000 004 000 010 020 + 62 01D 011 013 01F 007 03F + 63 03C 03C 033 033 00F 00C + 64 000 000 03F 03F 000 000 + 65 03F 020 020 020 020 020 + 66 020 020 010 001 008 002 + 67 01D 010 010 01C 000 009 + 68 03F 021 021 021 021 03F + 69 000 000 00C 00C 000 000 + 70 000 03F 000 03F 000 03F diff --git a/tcl/admin.layer b/tcl/admin.layer new file mode 100644 index 0000000..056b847 --- /dev/null +++ b/tcl/admin.layer @@ -0,0 +1,96 @@ +#fGIS Layer file. Layer type: raster +# Layer: áÄÍÉÎÉÓÔÒÁÔÉ×ÎÙÅ ÏÂÌÁÓÔÉ òæ +set _raster_ [raster ../testdata/admin.epp] +set _legend_ [legend parse {-2 áÄÍÉÎÉÓÔÒÁÔÉ×ÎÙÅ ÏÂÌÁÓÔÉ òæ +1 ›òÅÓÐÕÂÌÉËÁ âÁÛËÏÒÔÏÓÔÁÎ +2 ›òÅÓÐÕÂÌÉËÁ âÕÒÑÔÉÑ +3 ›òÅÓÐÕÂÌÉËÁ äÁÇÅÓÔÁÎ +4 ›ëÁÂÁÒÄÉÎÏ-âÁÌËÁÒÓËÁÑ òÅÓÐÕÂÌÉËÁ +5 ›òÅÓÐÕÂÌÉËÁ ëÁÌÍÙËÉÑ-èÁÌØÍÇ ôÁÎÇÞ +6 ›òÅÓÐÕÂÌÉËÁ ëÁÒÅÌÉÑ +7 ›òÅÓÐÕÂÌÉËÁ ëÏÍÉ +8 ›òÅÓÐÕÂÌÉËÁ íÁÒÉÊ üÌ +9 ›íÏÒÄÏ×ÓËÁÑ óóò +10 ›óÅ×ÅÒÏ-ïÓÅÔÉÎÓËÁÑ óóò +11 ›òÅÓÐÕÂÌÉËÁ ôÁÔÁÒÓÔÁÎ +12 ›òÅÓÐÕÂÌÉËÁ ôÕ×Á +13 ›õÄÍÕÒÔÓËÁÑ òÅÓÐÕÂÌÉËÁ +14 ›þÅÞÅÎÓËÁÑ É éÎÇÕÛÓËÁÑ ÒÅÓÐÕÂÌÉËÉ +15 ›þÕ×ÁÛÓËÁÑ òÅÓÐÕÂÌÉËÁ +16 ›òÅÓÐÕÂÌÉËÁ óÁÈÁ (ñËÕÔÉÑ) +17 ›áÌÔÁÊÓËÉÊ ËÒÁÊ +18 ›òÅÓÐÕÂÌÉËÁ áÌÔÁÊ +19 ›ëÒÁÓÎÏÄÁÒÓËÉÊ ËÒÁÊ +20 ›òÅÓÐÕÂÌÉËÁ áÄÙÇÅÑ +21 ›ëÒÁÓÎÏÑÒÓËÉÊ ËÒÁÊ +22 ›òÅÓÐÕÂÌÉËÁ èÁËÁÓÓÉÑ +23 ›ôÁÊÍÙÒÓËÉÊ Á×Ô.ÏËÒÕÇ +24 ›ü×ÅÎËÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ +25 ›ðÒÉÍÏÒÓËÉÊ ËÒÁÊ +26 ›óÔÁ×ÒÏÐÏÌØÓËÉÊ ËÒÁÊ +27 ›ëÁÒÁÞÁÅ×Ï-þÅÒËÅÓÓËÁÑ òÅÓÐÕÂÌÉËÁ +28 ›èÁÂÁÒÏ×ÓËÉÊ ËÒÁÊ +29 ›å×ÒÅÊÓËÁÑ Á×Ô.ÏÂÌÁÓÔØ +30 ›áÍÕÒÓËÁÑ +31 ›áÒÈÁÎÇÅÌØÓËÁÑ +32 ›îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ +33 ›áÓÔÒÁÈÁÎÓËÁÑ +34 ›âÅÌÇÏÒÏÄÓËÁÑ +35 ›âÒÑÎÓËÁÑ +36 ›÷ÌÁÄÉÍÉÒÓËÁÑ +37 ›÷ÏÌÇÏÇÒÁÄÓËÁÑ +38 ›÷ÏÌÏÇÏÄÓËÁÑ +39 ›÷ÏÒÏÎÅÖÓËÁÑ +40 ›îÉÖÅÇÏÒÏÄÓËÁÑ +41 ›é×ÁÎÏ×ÓËÁÑ +42 ›éÒËÕÔÓËÁÑ +43 ›õÓÔØ-ïÒÄÙÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒ +44 ›ëÁÌÉÎÉÎÇÒÁÄÓËÁÑ +45 ›ô×ÅÒÓËÁÑ +46 ›ëÁÌÕÖÓËÁÑ +47 ›ëÁÍÞÁÔÓËÁÑ +48 ›ëÏÒÑËÓËÉÊ Á×Ô.ÏËÒÕÇ +49 ›ëÅÍÅÒÏ×ÓËÁÑ +50 ›ëÉÒÏ×ÓËÁÑ +51 ›ëÏÓÔÒÏÍÓËÁÑ +52 ›óÁÍÁÒÓËÁÑ +53 ›ëÕÒÇÁÎÓËÁÑ +54 ›ëÕÒÓËÁÑ +55 ›ìÅÎÉÎÇÒÁÄÓËÁÑ +56 ›ìÉÐÅÃËÁÑ +57 ›íÁÇÁÄÁÎÓËÁÑ +58 ›þÕËÏÔÓËÉÊ Á×Ô.ÏËÒÕÇ +59 ›íÏÓËÏ×ÓËÁÑ +60 ›íÕÒÍÁÎÓËÁÑ +61 ›îÏ×ÇÏÒÏÄÓËÁÑ +62 ›îÏ×ÏÓÉÂÉÒÓËÁÑ +63 ›ïÍÓËÁÑ +64 ›ïÒÅÎÂÕÒÇÓËÁÑ +65 ›ïÒÌÏ×ÓËÁÑ +66 ›ðÅÎÚÅÎÓËÁÑ +67 ›ðÅÒÍÓËÁÑ +68 ›ëÏÍÉ-ðÅÒÍÑÃËÉÊ Á×Ô.ÏËÒÕÇ +69 ›ðÓËÏ×ÓËÁÑ +70 ›òÏÓÔÏ×ÓËÁÑ +71 ›òÑÚÁÎÓËÁÑ +72 ›óÁÒÁÔÏ×ÓËÁÑ +73 ›óÁÈÁÌÉÎÓËÁÑ +74 ›åËÁÔÅÒÉÎÂÕÒÇÓËÁÑ +75 ›óÍÏÌÅÎÓËÁÑ +76 ›ôÁÍÂÏ×ÓËÁÑ +77 ›ôÏÍÓËÁÑ +78 ›ôÕÌØÓËÁÑ +79 ›ôÀÍÅÎÓËÁÑ +80 ›èÁÎÔÙ-íÁÎÓÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ +81 ›ñÍÁÌÏ-îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ +82 ›õÌØÑÎÏ×ÓËÁÑ +83 ›þÅÌÑÂÉÎÓËÁÑ +84 ›þÉÔÉÎÓËÁÑ +85 ›áÇÉÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒÕÇ +86 ›ñÒÏÓÌÁ×ÓËÁÑ +}] +layer create raster -raster $_raster_\ + -border none -ovrborder yes -ovrcolor black\ + -title { áÄÍÉÎÉÓÔÒÁÔÉ×ÎÙÅ ÏÂÌÁÓÔÉ òæ}\ + -legend $_legend_ + diff --git a/tcl/balloonhelp.tcl b/tcl/balloonhelp.tcl new file mode 100644 index 0000000..3f0ce51 --- /dev/null +++ b/tcl/balloonhelp.tcl @@ -0,0 +1,225 @@ +## balloonhelp.tcl +## Balloon Help Routines +## +## Jeffrey Hobbs +## Initiated: 28 October 1996 +## + +##------------------------------------------------------------------------ +## PROCEDURE +## balloonhelp +## +## DESCRIPTION +## Implements a balloon help system +## +## ARGUMENTS +## balloonhelp tag, so we can highlight the text up to +# the . + +proc HMtag_a {win param text} { + upvar #0 HM$win var + + # a source + + if {[HMextract_param $param href]} { + set var(Tref) [list L:$href] + HMstack $win "" "Tlink link" + HMlink_setup $win $href + } + + # a destination + + if {[HMextract_param $param name]} { + set var(Tname) [list N:$name] + HMstack $win "" "Tanchor anchor" + $win mark set N:$name "$var(S_insert) - 1 chars" + $win mark gravity N:$name left + if {[info exists var(goto)] && $var(goto) == $name} { + unset var(goto) + set var(going) $name + } + } +} + +# The application should call here with the fragment name +# to cause the display to go to this spot. +# If the target exists, go there (and do the callback), +# otherwise schedule the goto to happen when we see the reference. + +proc HMgoto {win where {callback HMwent_to}} { + upvar #0 HM$win var + if {[regexp N:$where [$win mark names]]} { + $win see N:$where + update + eval $callback $win [list $where] + return 1 + } else { + set var(goto) $where + return 0 + } +} + +# We actually got to the spot, so highlight it! +# This should/could be replaced by the application +# We'll flash it orange a couple of times. + +proc HMwent_to {win where {count 0} {color orange}} { + upvar #0 HM$win var + if {$count > 5} return + catch {$win tag configure N:$where -foreground $color} + update + after 200 [list HMwent_to $win $where [incr count] \ + [expr {$color=="orange" ? "" : "orange"}]] +} + +proc HMtag_/a {win param text} { + upvar #0 HM$win var + if {[info exists var(Tref)]} { + unset var(Tref) + HMstack $win / "Tlink link" + } + + # goto this link, then invoke the call-back. + + if {[info exists var(going)]} { + $win yview N:$var(going) + update + HMwent_to $win $var(going) + unset var(going) + } + + if {[info exists var(Tname)]} { + unset var(Tname) + HMstack $win / "Tanchor anchor" + } +} + +# Inline Images +# This interface is subject to change +# Most of the work is getting around a limitation of TK that prevents +# setting the size of a label to a widthxheight in pixels +# +# Images have the following parameters: +# align: top,middle,bottom +# alt: alternate text +# ismap: A clickable image map +# src: The URL link +# Netscape supports (and so do we) +# width: A width hint (in pixels) +# height: A height hint (in pixels) +# border: The size of the window border + +proc HMtag_img {win param text} { + upvar #0 HM$win var + + # get alignment + array set align_map {top top middle center bottom bottom} + set align bottom ;# The spec isn't clear what the default should be + HMextract_param $param align + catch {set align $align_map([string tolower $align])} + + # get alternate text + set alt "" + HMextract_param $param alt + set alt [HMmap_esc $alt] + + # get the border width + set border 1 + HMextract_param $param border + + # see if we have an image size hint + # If so, make a frame the "hint" size to put the label in + # otherwise just make the label + set item $win.$var(tags) + # catch {destroy $item} + if {[HMextract_param $param width] && [HMextract_param $param height]} { + frame $item -width $width -height $height + pack propagate $item 0 + set label $item.label + label $label + pack $label -expand 1 -fill both + } else { + set label $item + label $label + } + + $label configure -relief ridge -fg orange -text $alt + catch {$label configure -bd $border} + $win window create $var(S_insert) -align $align -window $item -pady 2 -padx 2 + + # add in all the current tags (this is overkill) + set tags [HMcurrent_tags $win] + foreach tag $tags { + $win tag add $tag $item + } + + # set imagemap callbacks + if {[HMextract_param $param ismap]} { + # regsub -all {[^L]*L:([^ ]*).*} $tags {\1} link + set link [lindex $tags [lsearch -glob $tags L:*]] + regsub L: $link {} link + global HMevents + regsub -all {%} $link {%%} link2 + foreach i [array names HMevents] { + bind $label <$i> "catch \{%W configure $HMevents($i)\}" + } + bind $label <1> "+HMlink_callback $win $link2?%x,%y" + } + + # now callback to the application + set src "" + HMextract_param $param src + HMset_image $win $label $src + return $label ;# used by the forms package for input_image types +} + +# The app needs to supply one of these +proc HMset_image {win handle src} { + HMgot_image $handle "can't get\n$src" +} + +# When the image is available, the application should call back here. +# If we have the image, put it in the label, otherwise display the error +# message. If we don't get a callback, the "alt" text remains. +# if we have a clickable image, arrange for a callback + +proc HMgot_image {win image_error} { + # if we're in a frame turn on geometry propogation + if {[winfo name $win] == "label"} { + pack propagate [winfo parent $win] 1 + } + if {[catch {$win configure -image $image_error}]} { + $win configure -image {} + $win configure -text $image_error + } +} + +# Sample hypertext link callback routine - should be replaced by app +# This proc is called once for each tag. +# Applications can overwrite this procedure, as required, or +# replace the HMevents array +# win: The name of the text widget to render into +# href: The HREF link for this tag. + +array set HMevents { + Enter {-borderwidth 2 -relief raised } + Leave {-borderwidth 2 -relief flat } + 1 {-borderwidth 2 -relief sunken} + ButtonRelease-1 {-borderwidth 2 -relief raised} +} + +# We need to escape any %'s in the href tag name so the bind command +# doesn't try to substitute them. + +proc HMlink_setup {win href} { + global HMevents + regsub -all {%} $href {%%} href2 + foreach i [array names HMevents] { + eval {$win tag bind L:$href <$i>} \ + \{$win tag configure \{L:$href2\} $HMevents($i)\} + } +} + +# generic link-hit callback +# This gets called upon button hits on hypertext links +# Applications are expected to supply ther own HMlink_callback routine +# win: The name of the text widget to render into +# x,y: The cursor position at the "click" + +proc HMlink_hit {win x y} { + set tags [$win tag names @$x,$y] + set link [lindex $tags [lsearch -glob $tags L:*]] + # regsub -all {[^L]*L:([^ ]*).*} $tags {\1} link + regsub L: $link {} link + HMlink_callback $win $link +} + +# replace this! +# win: The name of the text widget to render into +# href: The HREF link for this tag. + +proc HMlink_callback {win href} { + puts "Got hit on $win, link $href" +} + +# extract a value from parameter list (this needs a re-do) +# returns "1" if the keyword is found, "0" otherwise +# param: A parameter list. It should alredy have been processed to +# remove any entity references +# key: The parameter name +# val: The variable to put the value into (use key as default) + +proc HMextract_param {param key {val ""}} { + + if {$val == ""} { + upvar $key result + } else { + upvar $val result + } + set ws " \n\r" + + # look for name=value combinations. Either (') or (") are valid delimeters + if { + [regsub -nocase [format {.*%s[%s]*=[%s]*"([^"]*).*} $key $ws $ws] $param {\1} value] || + [regsub -nocase [format {.*%s[%s]*=[%s]*'([^']*).*} $key $ws $ws] $param {\1} value] || + [regsub -nocase [format {.*%s[%s]*=[%s]*([^%s]+).*} $key $ws $ws $ws] $param {\1} value] } { + set result $value + return 1 + } + + # now look for valueless names + # I should strip out name=value pairs, so we don't end up with "name" + # inside the "value" part of some other key word - some day + + set bad \[^a-zA-Z\]+ + if {[regexp -nocase "$bad$key$bad" -$param-]} { + return 1 + } else { + return 0 + } +} + +# These next two routines manage the display state of the page. + +# Push or pop tags to/from stack. +# Each orthogonal text property has its own stack, stored as a list. +# The current (most recent) tag is the last item on the list. +# Push is {} for pushing and {/} for popping + +proc HMstack {win push list} { + upvar #0 HM$win var + array set tags $list + if {$push == ""} { + foreach tag [array names tags] { + lappend var($tag) $tags($tag) + } + } else { + foreach tag [array names tags] { + # set cnt [regsub { *[^ ]+$} $var($tag) {} var($tag)] + set var($tag) [lreplace $var($tag) end end] + } + } +} + +# extract set of current text tags +# tags starting with T map directly to text tags, all others are +# handled specially. There is an application callback, HMset_font +# to allow the application to do font error handling + +proc HMcurrent_tags {win} { + upvar #0 HM$win var + set font font + foreach i {family size weight style} { + set $i [lindex $var($i) end] + append font :[set $i] + } + set xfont [HMx_font $family $size $weight $style $var(S_adjust_size)] + HMset_font $win $font $xfont + set indent [llength $var(indent)] + incr indent -1 + lappend tags $font indent$indent + foreach tag [array names var T*] { + lappend tags [lindex $var($tag) end] ;# test + } + set var(font) $font + set var(xfont) [$win tag cget $font -font] + set var(level) $indent + return $tags +} + +# allow the application to do do better font management +# by overriding this procedure + +proc HMset_font {win tag font} { + catch {$win tag configure $tag -font $font} msg +} + +# generate an X font name +proc HMx_font {family size weight style {adjust_size 0}} { + catch {incr size $adjust_size} + return "-*-$family-$weight-$style-normal-*-*-${size}0-*-*-*-*-*-*" +} + +# Optimize HMrender (hee hee) +# This is experimental + +proc HMoptimize {} { + regsub -all "\n\[ \]*#\[^\n\]*" [info body HMrender] {} body + regsub -all ";\[ \]*#\[^\n]*" $body {} body + regsub -all "\n\n+" $body \n body + proc HMrender {win tag not param text} $body +} +############################################ +# Turn HTML into TCL commands +# html A string containing an html document +# cmd A command to run for each html tag found +# start The name of the dummy html start/stop tags + +proc HMparse_html {html {cmd HMtest_parse} {start hmstart}} { + regsub -all \{ $html {\&ob;} html + regsub -all \} $html {\&cb;} html + set w " \t\r\n" ;# white space + proc HMcl x {return "\[$x\]"} + set exp <(/?)([HMcl ^$w>]+)[HMcl $w]*([HMcl ^>]*)> + set sub "\}\n$cmd {\\2} {\\1} {\\3} \{" + regsub -all $exp $html $sub html + eval "$cmd {$start} {} {} \{ $html \}" + eval "$cmd {$start} / {} {}" +} + +proc HMtest_parse {command tag slash text_after_tag} { + puts "==> $command $tag $slash $text_after_tag" +} + +# Convert multiple white space into a single space + +proc HMzap_white {data} { + regsub -all "\[ \t\r\n\]+" $data " " data + return $data +} + +# find HTML escape characters of the form &xxx; + +proc HMmap_esc {text} { + if {![regexp & $text]} {return $text} + regsub -all {([][$\\])} $text {\\\1} new + regsub -all {&#([0-9][0-9]?[0-9]?);?} \ + $new {[format %c [scan \1 %d tmp;set tmp]]} new + regsub -all {&([a-zA-Z]+);?} $new {[HMdo_map \1]} new + return [subst $new] +} + +# convert an HTML escape sequence into character + +proc HMdo_map {text {unknown ?}} { + global HMesc_map + set result $unknown + catch {set result $HMesc_map($text)} + return $result +} + +# table of escape characters (ISO latin-1 esc's are in a different table) + +array set HMesc_map { + lt < gt > amp & quot \" copy \xa9 + reg \xae ob \x7b cb \x7d nbsp \xa0 +} +############################################################# +# ISO Latin-1 escape codes + +array set HMesc_map { + nbsp \xa0 iexcl \xa1 cent \xa2 pound \xa3 curren \xa4 + yen \xa5 brvbar \xa6 sect \xa7 uml \xa8 copy \xa9 + ordf \xaa laquo \xab not \xac shy \xad reg \xae + hibar \xaf deg \xb0 plusmn \xb1 sup2 \xb2 sup3 \xb3 + acute \xb4 micro \xb5 para \xb6 middot \xb7 cedil \xb8 + sup1 \xb9 ordm \xba raquo \xbb frac14 \xbc frac12 \xbd + frac34 \xbe iquest \xbf Agrave \xc0 Aacute \xc1 Acirc \xc2 + Atilde \xc3 Auml \xc4 Aring \xc5 AElig \xc6 Ccedil \xc7 + Egrave \xc8 Eacute \xc9 Ecirc \xca Euml \xcb Igrave \xcc + Iacute \xcd Icirc \xce Iuml \xcf ETH \xd0 Ntilde \xd1 + Ograve \xd2 Oacute \xd3 Ocirc \xd4 Otilde \xd5 Ouml \xd6 + times \xd7 Oslash \xd8 Ugrave \xd9 Uacute \xda Ucirc \xdb + Uuml \xdc Yacute \xdd THORN \xde szlig \xdf agrave \xe0 + aacute \xe1 acirc \xe2 atilde \xe3 auml \xe4 aring \xe5 + aelig \xe6 ccedil \xe7 egrave \xe8 eacute \xe9 ecirc \xea + euml \xeb igrave \xec iacute \xed icirc \xee iuml \xef + eth \xf0 ntilde \xf1 ograve \xf2 oacute \xf3 ocirc \xf4 + otilde \xf5 ouml \xf6 divide \xf7 oslash \xf8 ugrave \xf9 + uacute \xfa ucirc \xfb uuml \xfc yacute \xfd thorn \xfe + yuml \xff +} + +########################################################## +# html forms management commands + +# As each form element is located, it is created and rendered. Additional +# state is stored in a form specific global variable to be processed at +# the end of the form, including the "reset" and "submit" options. +# Remember, there can be multiple forms existing on multiple pages. When +# HTML tables are added, a single form could be spread out over multiple +# text widgets, which makes it impractical to hang the form state off the +# HM$win structure. We don't need to check for the existance of required +# parameters, we just "fail" and get caught in HMrender + +# This causes line breaks to be preserved in the inital values +# of text areas +array set HMtag_map { + textarea {fill 0} +} + +########################################################## +# html isindex tag. Although not strictly forms, they're close enough +# to be in this file + +# is-index forms +# make a frame with a label, entry, and submit button + +proc HMtag_isindex {win param text} { + upvar #0 HM$win var + + set item $win.$var(tags) + if {[winfo exists $item]} { + destroy $item + } + frame $item -relief ridge -bd 3 + set prompt "Enter search keywords here" + HMextract_param $param prompt + label $item.label -text [HMmap_esc $prompt] -font $var(xfont) + entry $item.entry + bind $item.entry "$item.submit invoke" + button $item.submit -text search -font $var(xfont) -command \ + [format {HMsubmit_index %s {%s} [HMmap_reply [%s get]]} \ + $win $param $item.entry] + pack $item.label -side top + pack $item.entry $item.submit -side left + + # insert window into text widget + + $win insert $var(S_insert) \n isindex + HMwin_install $win $item + $win insert $var(S_insert) \n isindex + bind $item {focus %W.entry} +} + +# This is called when the isindex form is submitted. +# The default version calls HMlink_callback. Isindex tags should either +# be deprecated, or fully supported (e.g. they need an href parameter) + +proc HMsubmit_index {win param text} { + HMlink_callback $win ?$text +} + +# initialize form state. All of the state for this form is kept +# in a global array whose name is stored in the form_id field of +# the main window array. +# Parameters: ACTION, METHOD, ENCTYPE + +proc HMtag_form {win param text} { + upvar #0 HM$win var + + # create a global array for the form + set id HM$win.form$var(tags) + upvar #0 $id form + + # missing /form tag, simulate it + if {[info exists var(form_id)]} { + puts "Missing end-form tag !!!! $var(form_id)" + HMtag_/form $win {} {} + } + catch {unset form} + set var(form_id) $id + + set form(param) $param ;# form initial parameter list + set form(reset) "" ;# command to reset the form + set form(reset_button) "" ;# list of all reset buttons + set form(submit) "" ;# command to submit the form + set form(submit_button) "" ;# list of all submit buttons +} + +# Where we're done try to get all of the state into the widgets so +# we can free up the form structure here. Unfortunately, we can't! + +proc HMtag_/form {win param text} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + + # make submit button entries for all radio buttons + foreach name [array names form radio_*] { + regsub radio_ $name {} name + lappend form(submit) [list $name \$form(radio_$name)] + } + + # process the reset button(s) + + foreach item $form(reset_button) { + $item configure -command $form(reset) + } + + # no submit button - add one + if {$form(submit_button) == ""} { + HMinput_submit $win {} + } + + # process the "submit" command(s) + # each submit button could have its own name,value pair + + foreach item $form(submit_button) { + set submit $form(submit) + catch {lappend submit $form(submit_$item)} + $item configure -command \ + [list HMsubmit_button $win $var(form_id) $form(param) \ + $submit] + } + + # unset all unused fields here + unset form(reset) form(submit) form(reset_button) form(submit_button) + unset var(form_id) +} + +################################################################### +# handle form input items +# each item type is handled in a separate procedure +# Each "type" procedure needs to: +# - create the window +# - initialize it +# - add the "submit" and "reset" commands onto the proper Q's +# "submit" is subst'd +# "reset" is eval'd + +proc HMtag_input {win param text} { + upvar #0 HM$win var + + set type text ;# the default + HMextract_param $param type + set type [string tolower $type] + if {[catch {HMinput_$type $win $param} err]} { + puts stderr $err + } +} + +# input type=text +# parameters NAME (reqd), MAXLENGTH, SIZE, VALUE + +proc HMinput_text {win param {show {}}} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + + # make the entry + HMextract_param $param name ;# required + set item $win.input_text,$var(tags) + set size 20; HMextract_param $param size + set maxlength 0; HMextract_param $param maxlength + entry $item -width $size -show $show + + # set the initial value + set value ""; HMextract_param $param value + $item insert 0 $value + + # insert the entry + HMwin_install $win $item + + # set the "reset" and "submit" commands + append form(reset) ";$item delete 0 end;$item insert 0 [list $value]" + lappend form(submit) [list $name "\[$item get]"] + + # handle the maximum length (broken - no way to cleanup bindtags state) + if {$maxlength} { + bindtags $item "[bindtags $item] max$maxlength" + bind max$maxlength "%W delete $maxlength end" + } +} + +# password fields - same as text, only don't show data +# parameters NAME (reqd), MAXLENGTH, SIZE, VALUE + +proc HMinput_password {win param} { + HMinput_text $win $param * +} + +# checkbuttons are missing a "get" option, so we must use a global +# variable to store the value. +# Parameters NAME, VALUE, (reqd), CHECKED + +proc HMinput_checkbox {win param} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + + HMextract_param $param name + HMextract_param $param value + + # Set the global variable, don't use the "form" alias as it is not + # defined in the global scope of the button + set variable $var(form_id)(check_$var(tags)) + set item $win.input_checkbutton,$var(tags) + checkbutton $item -variable $variable -off {} -on $value -text " " + if {[HMextract_param $param checked]} { + $item select + append form(reset) ";$item select" + } else { + append form(reset) ";$item deselect" + } + + HMwin_install $win $item + lappend form(submit) [list $name \$form(check_$var(tags))] +} + +# radio buttons. These are like check buttons, but only one can be selected + +proc HMinput_radio {win param} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + + HMextract_param $param name + HMextract_param $param value + + set first [expr ![info exists form(radio_$name)]] + set variable $var(form_id)(radio_$name) + set variable $var(form_id)(radio_$name) + set item $win.input_radiobutton,$var(tags) + radiobutton $item -variable $variable -value $value -text " " + + HMwin_install $win $item + + if {$first || [HMextract_param $param checked]} { + $item select + append form(reset) ";$item select" + } else { + append form(reset) ";$item deselect" + } + + # do the "submit" actions in /form so we only end up with 1 per button grouping + # contributing to the submission +} + +# hidden fields, just append to the "submit" data +# params: NAME, VALUE (reqd) + +proc HMinput_hidden {win param} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + HMextract_param $param name + HMextract_param $param value + lappend form(submit) [list $name $value] +} + +# handle input images. The spec isn't very clear on these, so I'm not +# sure its quite right +# Use std image tag, only set up our own callbacks +# (e.g. make sure ismap isn't set) +# params: NAME, SRC (reqd) ALIGN + +proc HMinput_image {win param} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + HMextract_param $param name + set name ;# barf if no name is specified + set item [HMtag_img $win $param {}] + $item configure -relief raised -bd 2 -bg blue + + # make a dummy "submit" button, and invoke it to send the form. + # We have to get the %x,%y in the value somehow, so calculate it during + # binding, and save it in the form array for later processing + + set submit $win.dummy_submit,$var(tags) + if {[winfo exists $submit]} { + destroy $submit + } + button $submit -takefocus 0;# this never gets mapped! + lappend form(submit_button) $submit + set form(submit_$submit) [list $name $name.\$form(X).\$form(Y)] + + $item configure -takefocus 1 + bind $item "catch \{$win see $item\}" + bind $item <1> "$item configure -relief sunken" + bind $item " + set $var(form_id)(X) 0 + set $var(form_id)(Y) 0 + $submit invoke + " + bind $item " + set $var(form_id)(X) %x + set $var(form_id)(Y) %y + $item configure -relief raised + $submit invoke + " +} + +# Set up the reset button. Wait for the /form to attach +# the -command option. There could be more that 1 reset button +# params VALUE + +proc HMinput_reset {win param} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + + set value reset + HMextract_param $param value + + set item $win.input_reset,$var(tags) + button $item -text [HMmap_esc $value] + HMwin_install $win $item + lappend form(reset_button) $item +} + +# Set up the submit button. Wait for the /form to attach +# the -command option. There could be more that 1 submit button +# params: NAME, VALUE + +proc HMinput_submit {win param} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + + HMextract_param $param name + set value submit + HMextract_param $param value + set item $win.input_submit,$var(tags) + button $item -text [HMmap_esc $value] -fg blue + HMwin_install $win $item + lappend form(submit_button) $item + # need to tie the "name=value" to this button + # save the pair and do it when we finish the submit button + catch {set form(submit_$item) [list $name $value]} +} + +######################################################################### +# selection items +# They all go into a list box. We don't what to do with the listbox until +# we know how many items end up in it. Gather up the data for the "options" +# and finish up in the /select tag +# params: NAME (reqd), MULTIPLE, SIZE + +proc HMtag_select {win param text} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + + HMextract_param $param name + set size 5; HMextract_param $param size + set form(select_size) $size + set form(select_name) $name + set form(select_values) "" ;# list of values to submit + if {[HMextract_param $param multiple]} { + set mode multiple + } else { + set mode single + } + set item $win.select,$var(tags) + frame $item + set form(select_frame) $item + listbox $item.list -selectmode $mode -width 0 -exportselection 0 + HMwin_install $win $item +} + +# select options +# The values returned in the query may be different from those +# displayed in the listbox, so we need to keep a separate list of +# query values. +# form(select_default) - contains the default query value +# form(select_frame) - name of the listbox's containing frame +# form(select_values) - list of query values +# params: VALUE, SELECTED + +proc HMtag_option {win param text} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + upvar $text data + set frame $form(select_frame) + + # set default option (or options) + if {[HMextract_param $param selected]} { + lappend form(select_default) [$form(select_frame).list size] + } + set value [string trimright $data " \n"] + $frame.list insert end $value + HMextract_param $param value + lappend form(select_values) $value + set data "" +} + +# do most of the work here! +# if SIZE>1, make the listbox. Otherwise make a "drop-down" +# listbox with a label in it +# If the # of items > size, add a scroll bar +# This should probably be broken up into callbacks to make it +# easier to override the "look". + +proc HMtag_/select {win param text} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + set frame $form(select_frame) + set size $form(select_size) + set items [$frame.list size] + + # set the defaults and reset button + append form(reset) ";$frame.list selection clear 0 $items" + if {[info exists form(select_default)]} { + foreach i $form(select_default) { + $frame.list selection set $i + append form(reset) ";$frame.list selection set $i" + } + } else { + $frame.list selection set 0 + append form(reset) ";$frame.list selection set 0" + } + + # set up the submit button. This is the general case. For single + # selections we could be smarter + + for {set i 0} {$i < $size} {incr i} { + set value [format {[expr {[%s selection includes %s] ? {%s} : {}}]} \ + $frame.list $i [lindex $form(select_values) $i]] + lappend form(submit) [list $form(select_name) $value] + } + + # show the listbox - no scroll bar + + if {$size > 1 && $items <= $size} { + $frame.list configure -height $items + pack $frame.list + + # Listbox with scrollbar + + } elseif {$size > 1} { + scrollbar $frame.scroll -command "$frame.list yview" \ + -orient v -takefocus 0 + $frame.list configure -height $size \ + -yscrollcommand "$frame.scroll set" + pack $frame.list $frame.scroll -side right -fill y + + # This is a joke! + + } else { + scrollbar $frame.scroll -command "$frame.list yview" \ + -orient h -takefocus 0 + $frame.list configure -height 1 \ + -yscrollcommand "$frame.scroll set" + pack $frame.list $frame.scroll -side top -fill x + } + + # cleanup + + foreach i [array names form select_*] { + unset form($i) + } +} + +# do a text area (multi-line text) +# params: COLS, NAME, ROWS (all reqd, but default rows and cols anyway) + +proc HMtag_textarea {win param text} { + upvar #0 HM$win var + upvar #0 $var(form_id) form + upvar $text data + + set rows 5; HMextract_param $param rows + set cols 30; HMextract_param $param cols + HMextract_param $param name + set item $win.textarea,$var(tags) + frame $item + text $item.text -width $cols -height $rows -wrap none \ + -yscrollcommand "$item.scroll set" -padx 3 -pady 3 + scrollbar $item.scroll -command "$item.text yview" -orient v + $item.text insert 1.0 $data + HMwin_install $win $item + pack $item.text $item.scroll -side right -fill y + lappend form(submit) [list $name "\[$item.text get 0.0 end]"] + append form(reset) ";$item.text delete 1.0 end; \ + $item.text insert 1.0 [list $data]" + set data "" +} + +# procedure to install windows into the text widget +# - win: name of the text widget +# - item: name of widget to install + +proc HMwin_install {win item} { + upvar #0 HM$win var + $win window create $var(S_insert) -window $item -align bottom + $win tag add indent$var(level) $item + set focus [expr {[winfo class $item] != "Frame"}] + $item configure -takefocus $focus + bind $item "$win see $item" +} + +##################################################################### +# Assemble and submit the query +# each list element in "stuff" is a name/value pair +# - The names are the NAME parameters of the various fields +# - The values get run through "subst" to extract the values +# - We do the user callback with the list of name value pairs + +proc HMsubmit_button {win form_id param stuff} { + upvar #0 HM$win var + upvar #0 $form_id form + set query "" + foreach pair $stuff { + set value [subst [lindex $pair 1]] + if {$value != ""} { + set item [lindex $pair 0] + lappend query $item $value + } + } + # this is the user callback. + HMsubmit_form $win $param $query +} + +# sample user callback for form submission +# should be replaced by the application +# Sample version generates a string suitable for http + +proc HMsubmit_form {win param query} { + set result "" + set sep "" + foreach i $query { + append result $sep [HMmap_reply $i] + if {$sep != "="} {set sep =} {set sep &} + } + puts $result +} + +# do x-www-urlencoded character mapping +# The spec says: "non-alphanumeric characters are replaced by '%HH'" + +set HMalphanumeric a-zA-Z0-9 ;# definition of alphanumeric character class +for {set i 1} {$i <= 256} {incr i} { + set c [format %c $i] + if {![string match \[$HMalphanumeric\] $c]} { + set HMform_map($c) %[format %.2x $i] + } +} + +# These are handled specially +array set HMform_map { + " " + \n %0d%0a +} + +# 1 leave alphanumerics characters alone +# 2 Convert every other character to an array lookup +# 3 Escape constructs that are "special" to the tcl parser +# 4 "subst" the result, doing all the array substitutions + +proc HMmap_reply {string} { + global HMform_map HMalphanumeric + regsub -all \[^$HMalphanumeric\] $string {$HMform_map(&)} string + regsub -all \n $string {\\n} string + regsub -all \t $string {\\t} string + regsub -all {[][{})\\]\)} $string {\\&} string + return [subst $string] +} + +# convert a x-www-urlencoded string int a a list of name/value pairs + +# 1 convert a=b&c=d... to {a} {b} {c} {d}... +# 2, convert + to " " +# 3, convert %xx to char equiv + +proc HMcgiDecode {data} { + set data [split $data "&="] + foreach i $data { + lappend result [cgiMap $i] + } + return $result +} + +proc HMcgiMap {data} { + regsub -all {\+} $data " " data + + if {[regexp % $data]} { + regsub -all {([][$\\])} $data {\\\1} data + regsub -all {%([0-9a-fA-F][0-9a-fA-F])} $data {[format %c 0x\1]} data + return [subst $data] + } else { + return $data + } +} + +# There is a bug in the tcl library focus routines that prevents focus +# from every reaching an un-viewable window. Use our *own* +# version of the library routine, until the bug is fixed, make sure we +# over-ride the library version, and not the otherway around + +auto_load tkFocusOK +proc tkFocusOK w { + set code [catch {$w cget -takefocus} value] + if {($code == 0) && ($value != "")} { + if {$value == 0} { + return 0 + } elseif {$value == 1} { + return 1 + } else { + set value [uplevel #0 $value $w] + if {$value != ""} { + return $value + } + } + } + set code [catch {$w cget -state} value] + if {($code == 0) && ($value == "disabled")} { + return 0 + } + regexp Key|Focus "[bind $w] [bind [winfo class $w]]" +} diff --git a/tcl/hypermap b/tcl/hypermap new file mode 100755 index 0000000..27f0bb4 --- /dev/null +++ b/tcl/hypermap @@ -0,0 +1,136 @@ +#!/usr/bin/wish8.0 + +package require Fgis + +proc loadfile {file} { + global basename namestack + if [info exist basename] { + set file [file join [file dirname $basename] $file] + if [info exist namestack] { + set namestack [concat [list $basename] $namestack] + } else { + set namestack [list $basename] + } + } + if [file exist $file] { + set f [open $file] + set text [read $f] + close $f + set basename $file + return $text + } else { + return "File not found\ +

    File not found

    File $file cannot be\ + read" + } +} +proc hyper_window {text} { + if {[wm state .hyperleg] != "normal"} { + wm deiconify .hyperleg + } else { + raise .hyperleg + } + HMreset_win .hyperleg.t + HMparse_html $text "HMrender .hyperleg.t" +} + +proc show_hyper {planchet x y} { + global main_layer basename namestack + catch { unset basename} + catch {unset namestack} + set value [$main_layer value [$planchet mapx $x] [$planchet mapy $y] -raw] + if [string length $value] { + hyper_window [loadfile $value] + } else { + hyper_window "\n\ + No info avalable\n\ + \n\ +

    No info avalable

    \n\ + There is no information on this point\n\ + \n\ + " + } +} + + +set planchet .map +option add *font -cronyx-times-bold-r-normal--10-* +frame .menu -relief raised -bd 2 +menubutton .menu.file -text "File" -menu [set m .menu.file.m] +menu $m +#$m add command -label "Open..." -command add_layer +#$m add command -label "Save..." -state disabled -command {save_layer [select_layer]} +#$m add command -label "Close..." -state disabled -command {close_layer [select_layer]} +#$m add separator +$m add command -label "Print..." -command [list fgisPrintDialog $planchet] +$m add separator +$m add command -label "Quit" -command confirmExit +menubutton .menu.layer -text "Layer" -menu [set m .menu.layer.m] +menu $m +$m add command -label "Show..." -command {show_layer [select_layer] } -state disabled +$m add command -label "Look..." -command select_layers -state disabled +#$m add command -label "Properties..." -command {edit_layer [select_layer]} -state disabled +pack .menu.file .menu.layer -side left +pack .menu -side top -expand y -fill x +label .status -anchor w +planchet $planchet -width 640 -height 480 -status .status +toolbar .tool $planchet +pack .tool -expand y -fill x +pack $planchet +pack .status -expand y -fill x + + +button .tool.layer -text "?" -command add_layer +pack .tool.layer -side left -before .tool.scale +wm protocol . WM_DELETE_WINDOW confirmExit + +toplevel .hyperleg +text .hyperleg.t -wrap word -width 80 -height 40 -yscrollcommand\ + ".hyperleg.y set" +scrollbar .hyperleg.y -orient vert -command ".hyperleg.t yview" +grid .hyperleg.t .hyperleg.y -sticky news +wm protocol .hyperleg WM_DELETE_WINDOW {wm withdraw .hyperleg} +wm withdraw .hyperleg +HMinit_win .hyperleg.t +bind $planchet {show_hyper $planchet %x %y} + +# +# Define callbacks for html library. Should be done here +# when html library alderady loaded +proc HMlink_callback {win href} { + HMreset_win $win + HMparse_html [loadfile $href ] "HMrender $win" +} +proc HMset_image {win handle src} { + global basename + if [info exist basename] { + set src [file join [file dirname $basename] $src] + } + if [file exists $src] { + set img [image create photo -file $src] + HMgot_image $handle $img + } +} + +proc hyper_layer {file legend} { + global main_layer + if ![file exists $file] { + if [file exists $file.epp] { + append file .epp + } else { + tk_messageBox -message "File $filename doesn't exists" -type ok + return + } + } + if ![file exists $legend] { + if [file exists $legend.leg] { + append legend .leg + } else { + tk_messageBox -message "File $legend doesn't exists" -type ok + return + } + } + set main_layer [layer create raster -file $file -legfile $legend] +} + +source [lindex $argv 0] diff --git a/tcl/layer.tcl b/tcl/layer.tcl new file mode 100644 index 0000000..a5d1825 --- /dev/null +++ b/tcl/layer.tcl @@ -0,0 +1,567 @@ +# +# layers.tcl +# Implements high level layer object +# This file is part of fGIS +# + +# Global variable fgisLayerTypes - keeps names of constructor procedures +# for all defined layer types + +array set fgisLayerTypes { +raster fgisCreateRaster +chart fgisCreateChart +tag fgisCreateTag +} + +# proc layer - create layer or query information about all layers +# usage: +# layer create type ?name? ?-option value...? - returns name of layer. +# layer names ?pattern? ?-type type? - returns names of all matching layers +# layer types - list available layer types +# layer type name - return type of given layer + +proc layer {option args} { +global fgisLayerTypes fgisLayerList +switch -exact -- $option { + create { + if ![llength $args] { + return -code error "usage: layer create ?name? ?options?" + } + set tname [lindex $args 0] + set type [array names fgisLayerTypes $tname*] + switch [llength $type] { + 1 { # type good - call constructor + # drop layer type from args + set args [lreplace $args 0 0] + # if layer name not supplied, generate one + if {![llength $args]||[string match -* [lindex $args 0]]} { + set args [linsert $args 0 [fgisMakeObjectName layer]] + } elseif {![fgisCheckName [lindex $args 0]]} { + return -code error "Name \"[lindex $args 0]\" already used" + } + + if [catch [concat $fgisLayerTypes($type) $args] name] { + return -code error $name + } else { + set fgisLayerList($name) $type + return $name + } + } + 0 { # No matching type found + return -code error "Invalid layer type. Should be one of\ + [join [array names fgisLayerTypes] ", "]" + } + default { # Too many matching types found + return -code error "Ambiquous layer type \"$tname\": $type" + } + } + } + types { # Return list of available types + return [array names fgisLayerTypes] + } + names { # Return list of names + if {[llength $args]&&![string match -* [lindex $args 0]]} { + # extract glob pattern from arguments + set pattern [lindex $args 0] + set args [lreplace $args 0 0] + } else { # no pattern supplied, use * + set pattern * + } + if ![llength $args] { # if no other args, return all matching names + return [array names fgisLayerList $pattern] + } elseif {[llength $args]!=2} { + #check if args are -type list + return -code error "wrong # args. should be \"layer names ?pattern?\ + ?-type type?\"" + } elseif {![string match [lindex $args 0]* -type]} { + return -code error "wrong option. should be -type" + } else { + # first, check if all types in list are good + # and create array to lookup matching types + foreach type [lindex $args 1] { + if ![info exists fgisLayerTypes($type)] { + return -code error "Invalid layer type \"$type\"" + } + set tmp($type) 1 + } + # then scan list of layers + set result {} + foreach {name type} [array get fgisLayerList $pattern] { + if [info exists tmp($type)] { + lappend result $name + } + } + return $result + } + } + type { # return type of given layer + if ![info exists fgisLayerList($args)] { + return -code error "Layer $args doesn't exists" + } else { + return $fgisLayerList($args) + } + } + exist - + exists { + if [llength $args]!=1 { + return -code error "wrong # args. should be: layer exist name" + } + return [info exists fgisLayerList([lindex $args 0])] + } + default { # unrecognized command + return -code error "Invalid option. should be one of create, exists,\ + names, type, types" + } +} +} + +# +# Calls method of layer object. Searches in the global array +# fgisLayerMethods for index "type,method", and, if found, executes it. +# +;proc fgisLayerEval {type method object args} { + global fgisLayerMethods + # get list of methods of type, which match given method name + set methods [array names fgisLayerMethods $type,$method*] + switch -exact [llength $methods] { + 0 { # no applicable methods + set msg {} + foreach i [array names fgisLayerMethods $type,*] { + lappend msg [lindex [split $i ","] 1] + } + return -code error "Unknown option. should be one of [join $msg ", "]" + } + 1 { + eval $fgisLayerMethods($methods) $object $args + } + default { + return -code error "Ambiquous option \"$method\"" + } +} +} +# +# creates instance command for layer +# +# +# +;proc fgisLayerDefine {type object} { + global fgisLayerMethods + ;proc $object {option args} " + if \[catch {eval fgisLayerEval $type \$option $object \$args} res] { + return -code error \$res + } else { + return \$res + } +" +} +# +# copies name of old object methods to new one +# +;proc fgisLayerInherit {father son} { + global fgisLayerMethods + # copy virtual method table + foreach {name value} [array get fgisLayerMethods $father,*] { + set fgisLayerMethods($son,[lindex [split $name ","] 1]) $value + } + # copy field template + global fgis${father}Fields fgis${son}Fields + array set fgis${son}Fields [array get fgis${father}Fields] +} +# +# Common methods for all layers +# + +# +# return various info for layer +# +;proc fgisLayerInfo {name args} { + upvar #0 $name data + if [llength $args]!=1 { + return -code error "wrong # of args. should be $name info option" + } + set goodopt {opaque lookable legend limits numeric dimension reclass} + if [set idx [lsearch -glob $goodopt $args*]]==-1 { + return -code error "invalid option. should be one of [join $goodopt ", "]" + } + set key [lindex $goodopt $idx] + switch -exact $key { + legend { + return [expr {[info exist data(legend)]&&[$data(legend) drawable]}] + } + default { + return $data($key) + } + } +} +# +# Two procedures, which return title and subtitle +# +;proc fgisLayerTitle {name args} { +if [llength $args] { + return -code error "wrong # args. should be $name title" +} +upvar #0 $name data +if [info exists data(title)] { + return $data(title) +} else { + return $name +} +} +;proc fgisLayerSubtitle {name args} { +if [llength $args] { + return -code error "wrong # args. should be $name title" +} +upvar #0 $name data +if [info exists data(subtitle)] { + return $data(subtitle) +} else { + return +} +} +# +# raster layers +# +# table of methods +array set fgisLayerMethods { +raster,info fgisLayerInfo +raster,dump fgisRasterDump +raster,value fgisRasterValue +raster,show fgisRasterShow +raster,hide fgisRasterHide +raster,configure fgisRasterConfigure +raster,cget fgisRasterCget +raster,legclasses fgisRasterLegClasses +raster,sample fgisRasterSample +raster,legtext fgisRasterLegtext +raster,title fgisLayerTitle +raster,subtitle fgisLayerSubtitle +raster,delete fgisRasterDelete +raster,expand fgisRasterExpand +raster,limits fgisRasterLimits +raster,redraw fgisRasterRedraw +} +# table of fields (more precisely - template of default values +array set fgisRasterFields { +opaque 1 +lookable 1 +limits 1 +numeric 0 +dimension 2 +reclass 1 +palette defaultpalette +plotmode -patterns +border none +ovrborder yes +ovrcolor black +patterns {} +title {} +subtitle {} +} +# Other fields exist only in runtime +# legend - holds name of legend object +# raster - holds name of raster object + +# constructor of raster layer. +# Options available +# to specify raster +# -raster - recieves handle of raster object +# -file - recieves epp file +# to specify reclass +# -reclass statements -recieves reclass in EPPL-like syntax +# -table list - recieves reclass as Tcl list +# to specify legend +# -legend - recieves legend object handle +# -legfile - recieves legend file +# Appearance +# -palette - recieves palette object +# -palfile - recieves palette file +# -patterns - recieves pattern object +# -symbols - recieves pattern object and switches mode do symbols +# -borders - recieves none yes or base. Controls opaque mode +# -ovrborders - same for transparent mode +# -ovrcolor - color for transparent drawing +# +# +;proc fgisCreateRaster {name args} { + upvar #0 $name data + global fgisRasterFields + array set data [array get fgisRasterFields] + eval fgisRasterConfigure $name $args + if ![info exists data(raster)] { + error "No raster specified" + } + fgisLayerDefine raster $name + return $name +} +# +# Three small procedures to create object from file. +# They are needed becouse handleopt doesn't allow ] after option value +# +;proc fgisOpenEppFile {filename} { + set raster [raster $filename] + uplevel fgisSetObj data(raster) nodefault $raster +} +;proc fgisOpenLegFile {filename} { + uplevel fgisSetObj data(legend) none [legend read $filename] +} +;proc fgisOpenClrFile {filename} { + uplevel fgisSetObj data(palette) defaultpalette [palette read $filename] +} +# +# All done via handleopt. Only validity of border flags are checked +# afterward +# +;proc fgisRasterConfigure {name args} { + upvar #0 $name data + array set handlers { + raster {set redraw 1; set data(raster) } + file {set redraw 1; fgisOpenEppFile} + reclass {set redraw 1; $data(raster) reclass} + table {set redraw 1; $data(raster) reclass -table} + legend {fgisSetObj data(legend) none} + legfile {fgisOpenLegFile} + palette {set redraw 1; fgisSetObj data(palette) defaultpalette} + palfile {set redraw 1; fgisOpenClrFile} + patterns {set redraw 1 + set data(plotmode) -patterns + fgisSetObj data(patterns) {} } + symbols {set redraw 1 + set data(plotmode) -symbols + fgisSetObj data(patterns) {}} + border {set redraw 1;fgisSetList data(border) {none yes base}} + ovrborder {set redraw 1;fgisSetList data(ovrborder) {none yes base}} + ovrcolor {set redraw 1;set data(ovrcolor)} + title {set data(title)} + subtitle {set data(subtitle)} + } + set redraw 0 + handleopt handlers $args + set data(numeric) [expr ![info exists data(legend)]] + if $redraw { + foreach planchet [array names data .*] { + fgisRasterRedraw $name $planchet + } + } + return +} +# +# Return values of certain instance variables, +# or state information, corresponding to given configuration options +# See list below. +# +;proc fgisRasterCget {name args} { +if [llength $args]!=1 { + return -code error "wrong # args. should be $name cget option" +} +if [checklistopt args {-raster -reclass -table -palette -patterns -symbols + -legend -border -ovrborder -ovrcolor -title -subtitle -file} msg] { + return -code error $msg +} +upvar #0 $name data +switch -exact -- $args { + -file { return [$data(raster) filename] } + -table { return [$data(raster) reclass]} + -reclass {return [$data(raster) reclass -statements]} + -symbols - + -patterns { + if {$data(plotmode)=="$args"} { + return $data(patterns) + } else { + return + } + } + default { + regexp -- {-(.*)} $args junk index + if [info exists data($index)] { + return $data($index) + } else { + return + } + } +} +} +# +# Returns Tcl script, which creates same layer +# +;proc fgisRasterDump {name args} { + if [llength $args] { + return -code error "wrong # args. should be $name dump" + } + upvar #0 $name data + set opts "" + append result "#fGIS Layer file. Layer type: raster\n" + if [string length $data(title)] { + append result "# Layer: $data(title)\n" + } + # dumping raster + append result "set _raster_ \[raster [$data(raster) filename]" + if [string length [set reclass [$data(raster) reclass -statements]]] { + append result " -reclass [list $reclass]" + } + append result "\]\n" + # dumping legend + if [info exists data(legend)] { + append result "set _legend_ \[legend parse [list [$data(legend) print]]]\n" + append opts "-legend \$_legend_" + } + # dumping palette + if {$data(palette)!="defaultpalette"} { + append result "set _palette_ \[palette set [list [$data(palette) list]]]\n" + append opts " -palette \$_palette_" + } + # dumping patterns + if {[string length $data(patterns)]} { + append result "set _patterns_ \[patterns set [list \ + [$data(patterns) list]]]\n" + append opts " $data(plotmode) \$_patterns_" + } + if {[info exists $data(subtitle)]&&[string length $data(subtitle)]} { + append opts " -title [list $data(subtitle)]" + } + # finally, creating layer command + append result "layer create raster -raster \$_raster_\\ + -border $data(border) -ovrborder $data(ovrborder) -ovrcolor\ + $data(ovrcolor)\\ + -title [list $data(title)]\\ + $opts\n" + return $result +} + + +# Destroys raster, destroys legend, if exists +# destroys palette, if it is not defaultpalette, +# destroys patterns if they are not empty +# +;proc fgisRasterDelete {name args} { + if [llength $args] { + return -code error "wrong # args. should be $name delete" + } + upvar #0 $name data + foreach planchet [array names data ".*"] { + $planchet hide $name + } + $data(raster) delete + if [info exists data(legend)] { + $data(legend) delete + } + if {$data(palette)!="defaultpalette"} { + $data(palette) delete + } + if [string length $data(patterns)] { + $data(patterns) delete + } + unset data + rename $name {} + uplevel #0 unset fgisLayerList($name) +} +# +# Redraws layer accodring to information, created by show +# +;proc fgisRasterRedraw {name args} { + if [llength $args]!=1 { + return -code error "Wrong # args. should be $name redraw planchet" + } + upvar #0 $name data + if {![winfo exists $args]||[winfo class $args]!="Canvas"} { + return -code error "Invalid planchet $args" + } + if ![info exists data($args)] { + return -code error "Layer $name is not shown on planchet $args" + } + eval $data($args) +} +# +# Forget, that we was visible in planchet +# +;proc fgisRasterHide {name args} { + upvar \#0 $name data + if ![info exists data($args)] { + return -code error "Layer $name is not shown on planchet $args" + } + unset data($args) +} +# +# Prepares to show itself in planchet +# +;proc fgisRasterShow {name args} { + if [llength $args]!=2 { + return -code error "Wrong # args. should be $name planchet mode" + } + set planchet [lindex $args 0] + set mode [lindex $args 1] + upvar #0 $name data + if {![winfo exists $planchet]||[winfo class $planchet]!="Canvas"} { + return -code error "Invalid planchet $args" + } + switch -exact -- $mode { + -base { + set item [$planchet create image 0 0 -anchor nw \ + -image [image create photo -width [winfo reqwidth $planchet]\ + -height [winfo reqheight $planchet]] -tags $name] + set data($planchet) "fgisRasterColorImage $data(raster) $planchet\ + $item -border \$data(border) -palette \$data(palette)" + $planchet lower $item + } + -overlay { + set item [$planchet create image 0 0 -anchor nw \ + -image [image create bitmap -width [winfo reqwidth $planchet]\ + -height [winfo reqheight $planchet]] -tags $name] + set data($planchet) "fgisRasterBWImage $data(raster) $planchet\ + $item -border \$data(ovrborder) \$data(plotmode)\ + \$data(pattern) -color $data(ovrcolor)" + } + default { + return -code error "Invalid option. should be either -base or -overlay" + } + } +} +# +# Returns value of layer (with legend etc) +# +;proc fgisRasterValue {name args} { + set n [llength $args] + if {$n<2||$n>3} { + return -code error "wrong # args. should be $name value x y ?option?" + } elseif {$n==3} { + set flag [lindex $args 2] + set goodopt {-raw -list -titled} + if [set ind [lsearch -glob $goodopt $flag*]]!=-1 { + set flag [lindex $goodopt $ind] + } else { + return -code error "invalid option. should be one of [join goodopt ","]" + } + } else { + set flag -raw + } + upvar #0 $name data + set value [$data(raster) get [lindex $args 0] [lindex $args 1]] + if {$value==[$data(raster) offsite]} return + if [info exist data(legend)] { + set value [$data(legend) get $value] + } + switch -exact -- $flag { + -raw {return $value} + -list {return [list $name $value]} + -titled {return "[fgisLayerTitle $name]: $value"} + } +} +# +# Returns limits of raster (planchets are very interested in this) +# +;proc fgisRasterLimits {name args} { + if [llength $args] { + return -code error "wrong # args. should be $name limits" + } + upvar #0 $name data + return [$data(raster) limits] +} + +# +# chart layers +# +fgisLayerInherit raster chart +array set fgisLayerMethods { +chart,dump fgisChartDump +chart,value fgisChartValue +chart,configure fgisChartConfigure +} diff --git a/tcl/legend.tcl b/tcl/legend.tcl new file mode 100644 index 0000000..fe8aeb8 --- /dev/null +++ b/tcl/legend.tcl @@ -0,0 +1,136 @@ +proc legend {command name} { +switch -exact $command { +read {set f [open $name] + set string [read -nonewline $f] + close $f + return [legend parse $string] + } +parse { set legname [fgisMakeObjectName legend "info exists"] + upvar \#0 $legname data + foreach line [split $name "\n"] { + if ![string length $line] continue + if ![regexp {^ *(-?[0-9]+) [^ ]* (.*)$} $line junk a b] { + error "Error in legend format" + } + if {$a==-1} {set a subtitle} elseif {$a==-2} {set a title + } elseif {$a<0||$a>65535} {error "Invalid class code $a"} + if [ info exists data($a)] { + append data($a) " " $b + } else { set data($a) $b } + } + } +set { + set legname [fgisMakeObjectName legend "info exists"] + upvar \#0 $legname data + array set data $name + } +default { error "Invalid option. Should be one of set read parse"} +} +proc $legname {option args} "eval fgisLegend_\$option $legname \$args" +return $legname +} +;proc fgisLegend_list {name args} { + global $name + eval array get $name $args +} +;proc fgisLegend_get {name class} { + global fgis + upvar \#0 $name data + if ![info exists data($class)] { + return $fgis(undefined_legend) + } else { + return $data($class) + } +} +;proc fgisLegend_classes {name} { + global $name + return [lsort -integer [array names $name {[0-9]*}]] + } +proc fgisLegend_title {name args} { + upvar #0 $name data + if [llength $args] { + set data(title) [lindex $args 0] + } elseif [info exists data(title)] { + return $data(title) + } else { return } +} +proc fgisLegend_subtitle {name args} { + upvar #0 $name data + if [llength $args] { + set data(subtitle) [lindex $args 0] + } elseif [info exists data(subtitle)] { + return $data(subtitle) + } else return +} +proc fgisLegend_print {name args} { +upvar \#0 $name data + if [info exists data(title)] { + set text "-2 $data(title)\n" + } + if [info exists data(subtitle)] { + append text "-1 $data(subtitle)\n" + } + foreach i [fgisLegend_classes $name] { + append text "$i $data($i)\n" + } + if {"$args"=="-nonewline"} { + return [string trim $text "\n"] + } else { + return $text + } +} +proc fgisLegend_set {name class value} { + global $name + set $name\($class) $value +} +proc fgisLegend_drawable {name args} { + global $name + if ![llength $args] { + return [expr ![info exists $name\(nodraw)]] + } else { + if [lindex $args 0] { + catch {unset $name\(nodraw)} + } else { + set $name\(nodraw) 1 + } + return + } +} + +proc fgisLegend_delete {name} { +uplevel #0 unset $name +rename $name {} +} + +proc show_legend {y canvas legend boxcmd} { +global fgis_font +set wraplength [expr [$canvas cget -width]-[$canvas canvasx 1c]] +set boxwidth [expr [$canvas canvasy 4m]-[$canvas canvasy 0m]] +global $legend +if [info exists $legend\(title)] { + set item [$canvas create text [expr [$canvas cget -width]/2] $y -anchor n\ + -justify center -width [$canvas cget -width] \ + -text [set $legend\(title)] -tags title -font $fgis_font(3)] + set y [expr [lindex [$canvas bbox $item] 3]+2] +} + +if [info exists $legend\(subtitle)] { + set item [$canvas create text 0 $y -anchor nw -justify left\ + -width [$canvas cget -width] -text [set $legend\(subtitle)]\ + -tags subtitle -font $fgis_font(2)] + set y [expr [lindex [$canvas bbox $item] 3]+2] +} + +foreach i [$legend classes] { + eval $boxcmd $canvas 0 $y 7m [expr $y+$boxwidth] $i + $canvas create text 1c $y -anchor nw -justify left -width $wraplength\ + -text [set $legend\($i)] -tags class$i -font $fgis_font(1) + set y [expr [lindex [$canvas bbox class$i] 3]+2] +} +$canvas config -scrollregion [list 0 0 [$canvas cget -width] $y] +} + +proc color_box {palette canvas x1 y1 x2 y2 class} { +$canvas create rectangle $x1 $y1 $x2 $y2 -fill \ + [palette get $palette $class] -tags class$class +} diff --git a/tcl/lesras.lay b/tcl/lesras.lay new file mode 100644 index 0000000..be7708b --- /dev/null +++ b/tcl/lesras.lay @@ -0,0 +1,30 @@ +#fGIS Layer file. Layer type: raster +# Layer: ìÅÓÏÒÁÓÔ. ÒÁÊÏÎÉÒÏ×ÁÎÉÅ +set _raster_ [raster ../testdata/lesras.epp] +set _legend_ [legend parse {-2 ìÅÓÏÒÁÓÔ. ÒÁÊÏÎÉÒÏ×ÁÎÉÅ +1 úÏÎÁ ÁÒËÔÉÞÅÓËÏÊ ÐÕÓÔÙÎÉ +2 úÏÎÁ ÔÕÎÄÒÙ -ÒÁ×ÎÉÎÎÁÑ +3 úÏÎÁ ÔÕÎÄÒÙ -ÇÏÒÎÁÑ +4 úÏÎÁ ÌÅÓÏÔÕÎÄÒÙ +5 úÏÎÁ ÌÕÇÏ× É ÌÕÇÏ×ÙÈ ÒÅÄËÏÌÅÓÉÊ +6 ðÏÄÚÏÎÁ ÒÅÄËÏÓÔÏÊÎÏÊ ÔÁÊÇÉ +7 ðÏÄÚÏÎÁ ÓÅ×ÅÒÎÏÊ ÔÁÊÇÉ +8 ðÏÄÚÏÎÁ ÓÒÅÄÎÅÊ ÔÁÊÇÉ +9 ðÏÄÚÏÎÁ ÀÖÎÏÊ ÔÁÊÇÉ +10 ÐÏÄÚÏÎÁ Ó ÐÒÅÏÂÌÁÄÁÎÉÅÍ È×ÏÊÎÙÈ +11 ÐÏÄÚÏÎÁ Ó ÏÄÉÎÁËÏ×ÙÍ ÕÞÁÓÔÉÅÍ È×ÏÊÎÙÈ É ÛÉÒÏËÏÌÉÓÔ×ÅÎÎÙÈ +12 ÐÏÄÚÏÎÁ ÍÏÎÏÄÏÍÉÎÁÎÔÎÙÈ ÌÅÓÏ× +13 ÐÏÄÚÏÎÁ ÐÏÌÉÄÏÍÉÎÁÎÔÎÙÈ-ÔÅÒÍÏÆÉÌØÎÙÈ ÌÅÓÏ× +14 ÚÏÎÁ +15 ÓÅ×ÅÒÎÙÈ ÓÔÅÐÅÊ +16 ÀÖÎÙÈ ÓÔÅÐÅÊ +17 ÓÅ×ÅÒÎÏÊ ÐÏÌÕÐÕÓÔÙÎÉ +18 ÀÖÎÏÊ ÐÏÌÕÐÕÓÔÙÎÉ +19 ÓÅ×ÅÒÎÏÊ ÐÕÓÔÙÎÉ +20 ÀÖÎÏÊ ÐÕÓÔÙÎÉ +}] +layer create raster -raster $_raster_\ + -border none -ovrborder yes -ovrcolor black\ + -title { ìÅÓÏÒÁÓÔ. ÒÁÊÏÎÉÒÏ×ÁÎÉÅ}\ + -legend $_legend_ + diff --git a/tcl/mapview b/tcl/mapview new file mode 100755 index 0000000..773297f --- /dev/null +++ b/tcl/mapview @@ -0,0 +1,35 @@ +#!/usr/bin/wish8.0 +package require Fgis +set planchet .map +option add *font -cronyx-times-bold-r-normal--10-* +frame .menu -relief raised -bd 2 +menubutton .menu.file -text "File" -menu [set m .menu.file.m] +menu $m +$m add command -label "Open..." -command add_layer +$m add command -label "Save..." -state disabled -command {save_layer [select_layer]} +$m add command -label "Close..." -state disabled -command {close_layer [select_layer]} +$m add separator +$m add command -label "Print..." -command [list fgisPrintDialog $planchet] +$m add separator +$m add command -label "Quit" -command confirmExit +menubutton .menu.layer -text "Layer" -menu [set m .menu.layer.m] +menu $m +$m add command -label "Show..." -command {show_layer [select_layer] } -state disabled +$m add command -label "Look..." -command select_layers -state disabled +$m add command -label "Properties..." -command {edit_layer [select_layer]} -state disabled +pack .menu.file .menu.layer -side left +pack .menu -side top -expand y -fill x +label .status -anchor w +planchet $planchet -width 640 -height 480 -status .status +toolbar .tool $planchet +pack .tool -expand y -fill x +pack $planchet +pack .status -expand y -fill x + + +button .tool.layer -text "?" -command add_layer +pack .tool.layer -side left -before .tool.scale +wm protocol . WM_DELETE_WINDOW confirmExit +foreach file $argv { + add_layer $file +} diff --git a/tcl/objects.tcl b/tcl/objects.tcl new file mode 100644 index 0000000..a23d392 --- /dev/null +++ b/tcl/objects.tcl @@ -0,0 +1,87 @@ +# +# objects.tcl +# some common procedures to implement fGIS objects +# This file is part of fGIS +# + + +# +# generates new unique name which starts with prefix. +# first name, which is not name of existing Tcl command and +# for which test script returns 1 would be returned +# +proc fgisMakeObjectName {prefix {test "info exists"}} { +set i 0 +while 1 { + set name $prefix$i + if {![string length [info command $prefix$i]]&& + ![uplevel #0 $test $prefix$i]} { + return $prefix$i + } + incr i +} +} +# +# returns 1 if name can be used for creation of new object +# +proc fgisCheckName {name {test "info exists"}} { + expr ![string length [info command $name]]&&![uplevel #0 $test $name] +} + +# +# Sets given variable to object value, if passed value is valid command +# name. +# Second argument specifies, how to deal with empty value. +# none - means unset variable +# nodefault - raise error +# any other value is substituted instead of empty string +# This procedure DELETES object, stored in var previously, if it is +# not eqial to default +# + +proc fgisSetObj {var default value} { + # first, check if we need to substitute defaults + if [string match {} $value] { + switch -exact -- $default { + none { + if {[uplevel info exists $var]&& + "[uplevel set $var]"!="$default"} { + [uplevel set $var] delete + } + uplevel unset $var + return + } + nodefault { + return -code error -errorcode [list BADVALUE $var] \ + "Empty value not allowed" + } + default { + set value $default + } + } + } else { + # check if passed value is valid object. Defaults are + # not subject to check - programmer knows, but user knows not + if [llength [info command $value]]!=1 { + return -code error -errorcode [list BADVALUE $var] \ + "Invalid object \"$value\"" + } + } + if {[uplevel info exists $var]&&"[uplevel set $var]"!="$default"} { + [uplevel set $var] delete + } + uplevel set $var [list $value] + return +} + +# +# fgisSetList - sets given variable to value, if value is +# one from given list. Otherwise rises error +# +proc fgisSetList {var list value} { + if [checklistopt value $list msg] { + return -code error -errorcode [list BADVALUE $var] $msg + } + uplevel set $var [list $value] + return +} diff --git a/tcl/planchet.tcl b/tcl/planchet.tcl new file mode 100644 index 0000000..953abb3 --- /dev/null +++ b/tcl/planchet.tcl @@ -0,0 +1,1011 @@ +# +# planchet.tcl +# definition of planchet widget. +# +# This file is part of fGIS tcl library +# Copyright (c) by SoftWeyr, 1997 +# + +# +# Class options +# +# +array set Planchet { +legbox {} +zoombutton {} +unzoombuttons {} +shiftbuttons {{} {} {} {}} +statusline {} +scalevar {} +rulerpos {1c -1c} +projection {} +lookwidth 200 +resizable 1 +} +#this options are got from application defaults +array set Planchet [list\ +coordformat $fgis(coordformat)\ +orient $fgis(orient)\ +shiftfactor $fgis(shift_factor)\ +] + +# This options added here to make getopt eat up them, if they specified, and +# so they would never passed to canvas command, so planchet would effectively +# ignore them +array set Planchet { +borderwidth 0 +bd 0 +highlightthickness 0 +} +# +# bindings +# + +bind Planchet "fgisPlanchet:resize %W" +bind Planchet "fgisPlanchet:destroy %W" +bind Planchet "fgisPlanchet:look %W %x %y" +bind Planchet "fgisPlanchet_setstatus %W {} {}" +bind Planchet "fgisPlanchet:setstatus %W %x %y" +bind Planchet "fgisPlanchet:setstatus %W %x %y" +bind LookToplevel "fgisPlanchet:hidelook %W" +bind LookToplevel "fgisPlanchet:hidelook %W" +bind Zoom break +bind Zoom "fgisPlanchet_zoom %W %x %y;break" +bind Zoom "fgisPlanchet_zoom %W cancel;break" +bind Zoom "fgisPlanchet_zoom %W cancel;break" +bind Zoom "break" +bind Zoom "break" +# +# create planchet widget +# +# +proc planchet {w args} { +upvar \#0 $w data +global Planchet +#parse options +array set data [array get Planchet] +set data(default) {} +if [catch {getopt data $args} err] { + unset data + return -code error $err +} +set restargs $data(default) +unset data(default) +#check helper widgets, if available +foreach t {legbox statusline shiftbuttons unzoombuttons zoombutton} { + if [catch {fgisSetHelper $w $t $data($t)} err] { + unset data + return -code error $err + } +} +#correct value of "resizable" options +if [checkbooleanopt data(resizable) err] { + return -code error $err +} +#create canvas +if [catch {eval canvas [list $w] $restargs -bd 0\ + -highlightthickness 0} err] { + unset data + return -code error $err +} +bindtags $w [list $w Planchet [winfo parent $w] all] +#create widget command +set data(cmd) .$w +rename $w $data(cmd) +;proc $w args "eval fgisPlanchet:eval [list $w] \$args" +# create look widnow + +set data(lookToplevel) [toplevel $w.look -class LookToplevel\ + -relief raised -bd 3] +set data(lookLabel) [label $w.look.label -wraplength $data(lookwidth)\ + -justify left] +pack $data(lookLabel) +wm overrideredirect $data(lookToplevel) y +wm transient $data(lookToplevel) $w +wm positionfrom $data(lookToplevel) program +wm withdraw $data(lookToplevel) +# fill placeholders for layer information +array set data { +lookable {} +overlays {} +base {} +limits {} +zoom {} +} +return $w +} + +# +# fgisPlanchet:eval +# -evaluates planchet widget command +# +;proc fgisPlanchet:eval {w option args} { + upvar \#0 $w data + if [string match {} [set arg [info command fgisPlanchet_$option]]] { + set arg [info command fgiPlanchet_$option*] + } + switch -exact [llength $arg] { + 0 { if [catch {uplevel [list $data(cmd) $option] $args} err] { + return -code error $err + } else { + return $err + } + } + 1 {return [uplevel $arg [list $w] $args] } + default { + return -code error "ambiquous option \"$option\"" + } + } +} + +# +# fgisPlanchet:destroy +# destroys planchet +# + +;proc fgisPlanchet:destroy w { + upvar \#0 $w data + foreach layer [linsert $data(overlays) end $data(base)] { + if [string length $layer] {$layer hide $w} + } + catch {rename $w {}} + #catch {rename $data(cmd) $w} + catch {unset data} + return +} +# +# releases grab and hides look window +# +;proc fgisPlanchet:hidelook {w} { + catch {grab release $w} + wm withdraw $w +} +# +# Given point in canvas coordinates, displays window with content +# of current layers +# +;proc fgisPlanchet:look {w x y} { + upvar \#0 $w data + set text [join [fgisPlanchet_look $w \ + [fgisPlanchet_mapx $w $x] [fgisPlanchet_mapy $w $y] -titled] "\n"] + if ![string length $text] { + set text "No info for this point" + } + $data(lookLabel) configure -text $text + set rootx [expr [winfo rootx $w]+$x+5] + if {$rootx>[winfo screenwidth $w]} { + set rootx [expr $rootx-10-[winfo reqwidth $data(lookToplevel)]] + } + set rooty [expr [winfo rooty $w]+$y+5] + if {$rooty>[winfo screenwidth $w]} { + set rooty [expr $rooty-10-[winfo reqheight $data(lookToplevel)]] + } + wm geometry $data(lookToplevel) +$rootx+$rooty + wm deiconify $data(lookToplevel) + raise $data(lookToplevel) + grab $data(lookToplevel) +} +# +# User visible implementation of look. Can be invoked as look planchet +# subcommand. Gets two map-coordinates and returns list of active layers +# Forms +# $planchet look x y ?-titled|-list? +# $planchet look add $layer +# $planchet look remove pattern +# $planchet look remove all +# $planchet look list ?pattern? +# legend text as layer value x y -titled returns +# +# Layers that return an empty string are ignored +# +;proc fgisPlanchet_look {w x {y {}} {flag -list}} { + upvar \#0 $w data + switch -exact -- $x { + add { + if ![string length $y] { + return -code error "Wrong # args. Should be $w look add layer" + } + if ![layer exists $y] { + return -code error "Layer \"$y\" doesn't exist" + } + if ![$y info lookable] { + return -code error "Layer \"$y\" is not lookable" + } + if [lsearch -exact $data(lookable) $y]!=-1 { + return -code error "Layer \"$y\" is already in look list of $w" + } + lappend data(lookable) $y + } + remove { + if ![string length $y] { + return -code error\ + "Wrong # args. Should be $w look remove pattern" + } + if {"$y"=="all"} { + set data(lookable) {} + } else { + if [lsearch -glob $data(lookable) $y]==-1 { + return -code error "No layers match pattern \"$y\"" + } + while {[set index [lsearch -glob $data(lookable) $y]]!=-1} { + set data(lookable) [lreplace $data(lookable) $index $index] + } + } + } + list { + set result {} + if [string match {} $y] {set y *} + foreach l $data(lookable) { + if [string match $y $l] { + lappend result $l + } + } + return $result + } + default { + set result {} + foreach layer $data(lookable) { + lappend result [$layer value $x $y $flag] + } + return $result + } + } +} +# +# Displays mouse coordinates in window. +# Recalculates pixels to meters and calls $w setstatus +# If no coordinate defined, displays "No coords" +# + +;proc fgisPlanchet:setstatus {w x y} { +upvar \#0 $w data +if ![llength $data(limits)] { + fgisPlanchet_setstatus $w "No coordinates defined" +} else { + fgisPlanchet_setstatus $w [fgisPlanchet_mapx $w $x] [fgisPlanchet_mapy $w $y] +} +} + +# +# Changes content of status window, if available +# possible variants setstatus {} - clears status line +# setstatus msg - displays $msg +# setstatus x y - displays coordinates. Map coordinates, not screen! +;proc fgisPlanchet_setstatus {w x {y {}}} { +upvar \#0 $w data +if ![string length $data(statusline)] { + return +} +if ![string length $y] { + $data(statusline) configure -text $x +} elseif ![string length $data(projection)] { + $data(statusline) configure -text [format $data(coordformat) $x $y] +} else { + $data(statusline) configure -text [$data(projection) format $x $y] +} +} + +# +# intercepts widget configure command +# +# +;proc fgisPlanchet_configure {w args} { +upvar \#0 $w data +if ![llength opt] { + return [eval $data(cmd) configure] +} +array set opt [list\ + legbox [list fgisSetHelper $w legbox]\ + zoombutton [list fgisSetHelper $w zoombutton ]\ + unzoombuttons [list fgisSetHelper $w unzoombuttons ]\ + shiftbuttons [list fgisSetHelper $w shiftbuttons]\ + statusline [list fgisSetHelper $w statusline]\ + scalevar {set data(scalevar)}\ + rulerpos [list fgisPlanchet:ruler $w]\ + projection {set data(projection)}\ + lookwidth [list $data(lookLabel) configure -wraplength]\ + coordformat "set data(coordformat)"\ + orient "set data(orient)"\ + shiftfactor "set data(shiftfactor)"\ + borderwidth {#}\ + bd 0\ + highlightthickness {#}\ + default "lappend restargs"\ +] +set restargs {} +if [catch {handleopt opt $args} res] { + return -code error $res +} +if [llength $restargs] { + if [catch {eval $data(cmd) configure $restargs}] { + return -code error $res + } +} +} +# +# Installs link to helper widget. +# Strictly internal use +# +;proc fgisSetHelper {w type widgets} { +array set CLASS { +legbox Canvas +shiftbuttons Button +zoombutton Button +unzoombuttons Button +statusline Label +} +upvar \#0 $w data +foreach i $widgets { + if ![string match {} $i] { + if {![winfo exist $i]} { + return -code error "Window $i doesn't exist" + } elseif {"[winfo class $i]"!="$CLASS($type)"} { + return -code error \ + "Wrong window $i. Should be [string tolower $CLASS($type)] widget." + } + } +} +# additional checks +switch -exact $type { + zoombutton { + if [llength $widgets]>1 { + return -code error "-zoombutton allows only one widget" + } + if {[llength $widgets]&&![llength $data(limits)]} { + $widgets configure -state disabled + } + } + shiftbuttons { + if [llength $widgets]!=4 { + return -code error "-shiftbuttons requires list of four buttons" + } + if [string length [join $widgets ""]] { + set dir {left down up right} + set j 0 + foreach i $widgets { + if [string compare {} $i] { + $i configure -command [list $w shift [lindex $dir $j]] + } else { + return -code error\ + "-shiftbuttons should all exist or all be empty" + } + incr j + } + set data(shiftbuttons) $widgets + fgisCheckShifts $w + } + } + unzoombuttons {} + default { + if [llength $widgets]>1 { + return -code error "Only one widget allowed for -$type option" + } + } +} +uplevel #0 set $w\($type) [list $widgets] +} +# +# intercert widget cget command +# +# +;proc fgisPlanchet_cget {w args} { + upvar \#0 $w data + if [llength $args]!=1 { + return -code error "Wrong # args. Should be $w cget option" + } + set arg [array names data [string trimleft $args -]] + set num [llength $arg] + if $num==1 { + return $data($arg) + } elseif $num { + return -code error "Amgiquous option \"$args\"" + } elseif [catch {$data(cmd) cget $args} result] { + return -code error $result + } else { + return $result + } +} +# +#Set up new coordinates of ruler +#or simply redraws ruler, if shown +# +;proc fgisPlanchet:ruler {w {coord {}}} { + upvar \#0 $w data + if [llength [$data(cmd) find withtag ruler]] { + fgisPlanchet_ruler off + if [string length $coord] { + set tmp $data(rulerpos) + set data(rulerpos) $coord + if [catch {fgisPlanchet_ruler on} err] { + set data(rulerpos) $tmp + fgisPlanchet_ruler on + return -code error $err + } + } else { + fgisPlanchet_ruler on + } + } +} +# +# actually implements ruler command +# +# +;proc fgisPlanchet_ruler {w {flag {}}} { +upvar \#0 $w data +switch -exact $flag { + {} { + if [llength [$data(cmd) find withtag ruler]] { + return on + } else { + return off + } + } + off { + $data(cmd) delete ruler + } + on { #here we actually draw it + # parse coordinates + global fgis_font + foreach {x y} $data(rulerpos) break + if [catch {fgisConvertCoords $data(cmd) x $x [winfo width $w]} x] { + return -code error $x + } + if [catch {fgisConvertCoords $data(cmd) y $y [winfo height $w]} y] { + return -code error $y + } + if [llength $data(limits)]!=4 { + return -code error "Coordinate system not defined for $w" + } + set origin_x [fgisPlanchet_mapx $w $x] + set origin_y [fgisPlanchet_mapy $w $y] + set meters [expr [fgisPlanchet_mapx $w 2c]-[fgisPlanchet_mapx $w 0c]] + for {set size 10;set step 2} {abs($size)<$meters } { + set size [expr $size*$step]} { + set step [expr $step==2?5:2] + } + $data(cmd) create line $x $y [$w scrx [expr $origin_x+$size]] \ + $y -width 3 -tags ruler + $data(cmd) create text $x [expr $y-5] -anchor s -text 0 -tags ruler \ + -font $fgis_font(1) + if {$size>1000} { + set msg "[expr $size/1000]km" + } else { + set msg "${size}m" + } + $data(cmd) create text [$w scrx [expr $origin_x+$size]]\ + [expr $y-5] -anchor s -text $msg -tags ruler \ + -font $fgis_font(1) + for {set xx $origin_x} {$xx<=$size+$origin_x} { + set xx [expr $xx+$size/$step]} { + $data(cmd) create line [$w scrx $xx] $y [$w scrx $xx] [expr $y-4] \ + -tags ruler + } + } +} +} +# +# Converts values given in any cordinate form into pixels +# if value is negative, corresponding window size is added +# + +;proc fgisConvertCoords {w cmd value limit} { + if [regexp -- {-(.*)} $value junk abs] { + set negate 1 + set value $abs + } else { set negate 0 } + if [catch { expr [$w canvas$cmd $value]-[$w canvas$cmd 0]} value] { + return -code error $value + } + if $negate { + return [expr $limit-$value] + } else { + return $value + } +} +# +# Sets limits of planchet coordinate system +# If limits were defined, pushes them into zoom stack and +# converts axis directions if neccessary +# +;proc fgisPlanchet_limits {w args} { + upvar \#0 $w data + if [llength $args]==1 { + eval set args $args + } elseif ![llength $args] { + return $data(limits) + } + if [string match $args* default] { + if {![llength $data(zoom)]} { + return -code error "No views stacked" + } + set data(limits) {} + set args [lindex $data(zoom) 0] + set data(zoom) {} + } + if [llength $args]!=4 { + return -code error "List of four floating point numbers expected" + } + foreach {x1 y1 x2 y2} $args break + set width [expr $x2-$x1] + set height [expr $y2-$y1] + if [llength $data(limits)] { + foreach b $data(unzoombuttons) { + $b config -state normal + } + if {$width*([lindex $data(limits) 2]-[lindex $data(limits) 0])<0} { + set tmp $x2; set x2 $x1; set x1 $tmp + set width [expr -$width] + } + if {$height*([lindex $data(limits) 3]-[lindex $data(limits) 1])<0} { + set tmp $y2;set y2 $y1;set y1 $tmp + set height [expr -$height] + } + } else { + foreach b $data(unzoombuttons) { + $b config -state disabled + } + if [string length $data(zoombutton)] { + $data(zoombutton) config -state normal + } + } + if {![llength $data(limits)]&&$data(resizable)} { + # Trying to adjust canvas size, preserving area + set area [expr [winfo reqheight $w]*[winfo reqwidth $w]] + set ratio [expr abs($width/$height)] + set hei [expr sqrt($area/$ratio)] + set wid [expr $hei*$ratio] + $data(cmd) config -width $wid -height $hei + } else { + # Trying to expand coordinate limits + if (abs($height/[winfo reqheight $w])$x2} {set dx [expr -$dx]} + set x1 [expr $x - $dx] + set x2 [expr $x + $dx] + if {$y1>$y2} {set dy [expr -$dy]} + set y1 [expr $y - $dy] + set y2 [expr $y + $dy] + fgisPlanchet_limits $w $x1 $y1 $x2 $y2 + } elseif [catch {eval $data(cmd) scale $args} err] { + return -code error $err + } +} + +# +# handles events by expanding coordinate system appropriately +# and redrawing all layers +# +;proc fgisPlanchet:resize {w} { +upvar \#0 $w data +set oldw [winfo reqwidth $w] +set oldh [winfo reqheight $w] +set nw [winfo width $w] +set nh [winfo height $w] +if {$oldw==$nw&&$oldh==$nh} return +$data(cmd) configure -width $nw -height $nh +if [llength $data(limits)]==4 { + foreach {x1 y1 x2 y2} $data(limits) break + set y2 [expr ($y2-$y1)/$oldh*$nh+$y1] + set x2 [expr ($x2-$x1)/$oldw*$nw+$x1] + set data(limits) [list $x1 $y1 $x2 $y2] + fgisCheckShifts $w + fgisPlanchet:Redraw $w +} +} + +# +# implements shift command - shifts viewport shiftfactor share in given +# direction +# + +;proc fgisPlanchet_shift {w args} { + if [llength $args]!=1 { + return -code error "Wrong # args. should be $w shift direction" + } + upvar \#0 $w data + if [llength $data(limits)]!=4 { + return -code error "Coordinate system for $w not set" + } + array set dir { + left {-1 0} + west {-1 0} + right {1 0} + east {1 0} + up {0 1} + north {0 1} + down {0 -1} + south {0 -1} + } + set d [array names dir [string tolower $args]*] + if [llength $d]>1 { + return -code error "Ambiquous direction \"$dir\"." + } elseif ![llength $d] { + return -code error \ + "Invalid direction \"$dir\". Should be one of [array names dir]" + } + set d $dir($d) + + foreach {x1 y1 x2 y2} $data(limits) break; + set dx [expr ($x2-$x1)*$data(shiftfactor)*[lindex $d 0]] + set dy [expr ($y2-$y1)*$data(shiftfactor)*[lindex $d 1]] + set data(limits) [list [expr $x1+$dx] [expr $y1+$dy] [expr $x2+$dx]\ + [expr $y2+$dy]] + fgisCheckShifts $w + fgisPlanchet:Redraw $w +} + +# +# Pops up last zoom from stack +# does call _limits to ensure that possible window size changes are haldled +# + +;proc fgisPlanchet_unzoom w { + upvar \#0 $w data + if ![set len [llength $data(zoom)]] { + return -code error "No views stacked" + } + set data(this_is_not_zoom) {} + set newlim [lindex $data(zoom) [incr len -1]] + set data(zoom) [lreplace $data(zoom) $len end] + fgisPlanchet_limits $w $newlim + unset data(this_is_not_zoom) +} + +# +# Checks it zoom stack contain some views with larger scale than current +# and discards them, becouse unzoom should never enlarge scale. +# (it was too annoying in Serge Mikhailov's eppedit +# +# Here can also be shifting of old views to make them contain new one, +# but I'm not sure that here is a good way to do so +# + +;proc fgisManageZoomList w { + upvar \#0 $w data + set zoom {} + set width [expr abs([lindex $data(limits) 2]-[lindex $data(limits) 0])] + foreach view $data(zoom) { + if {abs([lindex $view 2]-[lindex $view 0])>$width} { + lappend zoom $view + } + } + if [llength $zoom] { + set data(zoom) $zoom + } elseif [llength $data(zoom)] { + # always preserve default limits + set data(zoom) [list [lindex $data(zoom) 0]] + } + # update scale variable, if exist + if [string length $data(scalevar)] { + uplevel \#0 set $data(scalevar) "1:[fgisPlanchet_scale $w]" + } + # redraw ruler, if it is already visible + +} + +# +# Implements zoom widget command. +# with no options start interactive zooming process +# with two coords starts interactive zooming with specified point (in +# canvas coord) as one of corner. With four coords - just does it. +# with cancel flag - cancels zoom in progress +# +;proc fgisPlanchet_zoom {w args} { + upvar \#0 $w data + switch -exact [llength $args] { + 0 { + fgisPlanchet_setstatus $w \ + "Pick first corner. ESC or right button cancels" + bind Zoom "fgisPlanchet_zoom %W %x %y;break" + bind Zoom "break" + bindtags $w [linsert [bindtags $w] 0 Zoom] + } + 1 { if ![string match $args* cancel] { + return -code error "Wrong # args. Should be $w zoom ?x y ?x y?? or\ + $w zoom cancel" + } + if {![string match "Zoom*" [lindex [bindtags $w] 0]]} { + return -code error "No zoom in progress" + } + bindtags $w [lrange [bindtags $w] 1 end] + $data(cmd) delete zoomer + fgisPlanchet_setstatus {} + } + 2 { if {[lindex [bindtags $w] 0]!="Zoom"} { + bindtags $w [linsert [bindtags $w] 0 Zoom]] + } + fgisPlanchet_setstatus $w\ + "Pick second corner. ESC or right button cancels" + set x [lindex $args 0] + set y [lindex $args 1] + $data(cmd) create rectangle $x $y $x $y -tag zoomer + bind Zoom "fgisPlanchet_zoom %W $x $y %x %y;break" + bind Zoom "%W coord zoomer $x $y %x %y; break" + } + 4 { foreach {x1 y1 x2 y2} $args break + if {[lindex [bindtags $w] 0]=="Zoom"} { + bindtags $w [lrange [bindtags $w] 1 end] + } + fgisPlanchet_limits $w [$w mapx $x1] [$w mapy $y1] [$w mapx $x2]\ + [$w mapy $y2] + $data(cmd) delete zoomer + } + default { + return -code error "Wrong # args. Should be $w zoom ?x y ?x y?? or\ + $w zoom cancel" + } +} +} + +# +# clear - deletes all layers and resets coordinate system. +# leaves projection untouched +# + +;proc fgisPlanchet_clear w { + upvar \#0 $w data + set data(lookable) {} + foreach layer [concat $data(overlays) $data(base)] { + $layer hide $w + } + $data(cmd) delete all + set data(limits) {} + set data(zoom) {} + set data(overlays) {} + set data(base) {} + if {[string length $data(legbox)]} {$data(legbox) delete all} + foreach b [concat $data(unzoombuttons) [list $data(zoombutton)] \ + $data(shiftbuttons)] { + if {[string length $b]&&[winfo exists $b]} { + $b configure -state disabled + } + } +} + +# +# layers - returns list of all layers +# +# + +;proc fgisPlanchet_layers {w args} { + upvar \#0 $w data + if [llength $args]>1 { + return -code error "Wrong # of args. Should be $w layers ?pattern?" + } + if ![llength $args] { set args "*"} + set result {} + upvar #0 $w data + foreach l [concat $data(base) $data(overlays)] { + if {[string match $args $l]&&[lsearch -exact $result $l]==-1} { + lappend result $l + } + } + return $result +} + +# +# hide $layer - clears given layer +# +# +;proc fgisPlanchet_hide {w args} { + upvar \#0 $w data + foreach l $args { + set list [fgisPlanchet_layers $w $l] + if ![llength $list] { + return -code error "No such layer \"$l\" in $w" + } + foreach ll $list { + $ll hide $w + $data(cmd) delete $ll + if {"$ll"=="$data(base)"} { + if {[string length $data(legbox)]} { + $data(legbox) delete all + } + set data(base) {} + } + if {[set index [lsearch -exact $data(overlays) $ll]]!=-1} { + set data(overlays) [lreplace $data(overlays) $index $index] + } + } + } + +} + +# +# show $layer ?-base|-overlay? +# displays layer +# +;proc fgisPlanchet_show {w args} { + upvar \#0 $w data + if ![llength $args]&&[llength $args]>2 { + return -code error "Wrong # args. Should be $w show layer ?mode?" + } + set layer [lindex $args 0] + if [llength $args]==1 { + if {![llength $data(limits)]&&[$layer info opaque]} { + set mode -base + } else { + set mode -overlay + } + } else { + set mode [lindex $args 1] + if [string match $mode* -base] { + set mode -base + if ![$layer info opaque] { + return -code error "Opaque mode is not supporded by $layer" + } + } elseif [string match $mode* -overlay] { + set mode -overlay + if [lsearch -exact $data(overlays) $layer]!=-1 { + return -code error "Layer \"$layer\" already visible in $w" + } + } else { + return -code error \ + "Invalid option \"$mode\". Should be -base or -overlay" + } + } + if ![llength $data(limits)] { + if [$layer info limits] { + # am I wrong? + eval fgisPlanchet_limits $w [$layer limits] + } else { + return -code error\ + "Cannot show $layer without defined coordinate system" + } + } else { + foreach {x1 y1 x2 y2} [$layer limits] break + foreach {X1 Y1 X2 Y2} $data(limits) break + if {($x2-$x1)*($X2-$X1)<0||($Y2-$Y1)*($y2-$y1)<0} { + return -code error "Layer $layer is not compatible with $w" + } + } + $layer show $w $mode + if {$mode=="-base"} { + if [llength $data(base)] { + $data(base) hide $w + $data(cmd) delete $data(base) + } + set data(base) $layer + $data(cmd) lower $layer + if {[string length $data(legbox)]&&[winfo exists $data(legbox)]} { + drawlegend 0 0 $data(legbox) $layer -base -columns 1 \ + -width [$data legbox cget -width] + } + } else { + lappend data(overlays) $layer + } + fgisPlanchet_setstatus $w "REDRAW: Wait please..." + update + $layer redraw $w + fgisPlanchet_setstatus $w {} +} + +# +# +# fgisPlanchet:Redraw - redraws all layers. Very expensive thing. +# Should be called only if view coords are changed +# +;proc fgisPlanchet:Redraw {w} { + upvar \#0 $w data + fgisPlanchet_setstatus $w "REDRAW: Wait please..." + update + foreach layer [concat $data(base) $data(overlays)] { + $layer redraw $w + } + fgisPlanchet_setstatus $w {} + if {[fgisPlanchet_ruler $w]=="on"} { + fgisPlanchet_ruler $w off + fgisPlanchet_ruler $w on + } + update +} +;proc fgisPlanchet_print {w args} { +upvar \#0 $w data +global fgis +array set opt [list\ +file "|"\ +printer $fgis(printer)\ +colormode $fgis(print_colormode)\ +fontmap fgis_fontmap] + +getopt opt $args +if [uplevel array exist $opt(fontmap)] { + upvar $opt(fontmap) fontmap +} elseif [uplevel #0 array exist $opt(fontmap)] { + upvar $opt(fontmap) fontmap +} else { + return -code error "Array \"$opt(fontmap)\" doesn't exist" +} +if {$data(orient)=="landscape"} {set rotate y} else {set rotate n} +if [catch {if {$opt(file)=="|"} { + exec $fgis(printcmd) -P$opt(printer) << [ $data(cmd) postscript\ + -rotate $rotate -colormode $opt(colormode) -fontmap fontmap +} else { + $data(cmd) postscript -rotate $rotate -colormode $opt(colormode)\ + -fontmap fontmap -file $opt(file) +} } err ] { + return -code error $err +} +} diff --git a/tcl/progressbar.tcl b/tcl/progressbar.tcl new file mode 100644 index 0000000..91046e0 --- /dev/null +++ b/tcl/progressbar.tcl @@ -0,0 +1,619 @@ +## +## Copyright 1996-7 Jeffrey Hobbs +## + +##------------------------------------------------------------------------ +## PROCEDURE +## progressbar +## +## DESCRIPTION +## Implements a Progressbar mega-widget +## +## ARGUMENTS +## progressbar +## +## OPTIONS +## (Any canvas widget option may be used in addition to these) +## +## -indicatorcolor DEFAULT: #5ae6fe +## The color of the progressbar. Must be in #rgb format. +## This is also the default item start foreground color. +## +## -itembackground DEFAULT: {} +## Default item background color. {} means transparent. +## +## -itemfgfinished DEFAULT: #00ff00 (green) +## Default item finished foreground color. Must be in #rgb format. +## +## -itemtype DEFAULT: document +## Default item type (currently 'document' and 'image' are supported). +## +## -labelanchor anchor DEFAULT: c +## Anchor for the label. Reasonable values are c, w and e. +## +## -labeltext string DEFAULT: {} +## Text for the label +## +## -labelwidth # DEFAULT: 0 (self-sizing) +## Width for the label +## +## -maxvalue # DEFAULT: 0 (percentage-based) +## This represents what the representative max value of the progress +## bar is. If it is 0, the progress bar interprets the -value option +## like a percentage (with an implicit 100 value for -maxvalue), +## otherwise it is representative of what -value would have to reach +## for the progress to be at 100%. +## +## -orientation horizontal|vertical DEFAULT: horizontal +## Orientation of the progressbar +## +## -showvalue TCL_BOOLEAN DEFAULT: 1 +## Whether or not to show the exact value beside the bar (it is +## displayed as a percentage of the possible max value). +## +## -showerror TCL_BOOLEAN DEFAULT: 1 +## Whether to raise an error in the trace on the -variable if the +## appropriate range is exceeded. +## +## -value # DEFAULT: 0 +## The value of the progress bar. This will be used to calculate the +## overall progress percentage in conjunction with the -maxvalue option. +## +## -variable varname DEFAULT: {} +## A variable from which to get the value for the bar. This variable +## will have a trace set upon it that forces a postive value. It cannot +## be unset until the widget is destroyed or you change this option. +## +## RETURNS: the window pathname +## +## BINDINGS (in addition to default widget bindings) +## +## METHODS +## These are the methods that this megawidget recognizes. Aside from +## those listed here, it accepts what is valid for canvas widgets. +## +## configure ?option? ?value option value ...? +## cget option +## Standard tk widget routines. +## +## create ?item? ?-option value ...? +## Start displaying the progress of an item. "item" is the +## name to associate with the item. If no name is supplied, a unique +## name is generated. If an item of the same name already exists, then +## a new unique name is generated. Returns the name of the created item. +## +## delete item +## Remove the given item from the list of items being displayed. +## Total progress is updated appropriately. +## +## itemconfigure item ?-option value? +## Sets option(s) for an item. +## +## VALID ITEM OPTIONS +## +## -background color Background color of icon associated with item. +## -fgstart #rgb Initial foreground color of item's icon. +## -fgfinished #rgb Final foreground color of item's icon. +## The progressbar changes the shade of the icon +## from the initial to the final color in +## conjunction with the %age of maxvalue. +## -maxvalue # max value that represents 100% of possible value +## -type type item type (document and image currently supported) +## This can only be set at creation. +## -value # current progress toward full value of maxvalue +## +## itemcget item -option +## Returns the current value of the option for the given item +## +## names ?pattern? +## Returns the names of the progressbar's constituent items. +## An optional pattern can limit the return result. +## +## recalculate +## Recalculates the value and maxvalue of the progressbar based +## on the values of the consituent items, if any. This is only +## necessary when changing from using the progressbar without items +## to using it with items. +## +## subwidget widget +## Returns the true widget path of the specified widget. Valid +## widgets are label, canvas. +## +## NAMESPACE & STATE +## The megawidget creates a global array with the classname, and a +## global array which is the name of each megawidget created. The latter +## array is deleted when the megawidget is destroyed. +## Public procs of $CLASSNAME and [string tolower $CLASSNAME] are used. +## Other procs that begin with $CLASSNAME are private. For each widget, +## commands named .$widgetname and $CLASSNAME$widgetname are created. +## +## EXAMPLE USAGE: +## +## pack [progressbar .p -labeltext "Usage:" -variable usage] -fill x -exp 1 +## for {set i 0} {$i <= 10} {incr i} { set usage ${i}0; after 1000 } +## +## +##------------------------------------------------------------------------ + +#package require Widget 1.0 +package provide Progressbar 1.1 + +array set Progressbar { + type frame + base {canvas canvas canvas {-highlightthickness 0 \ + -bd 1 -relief ridge -width 100 -height 25}} + components {label} + + -bd -borderwidth + -borderwidth {borderWidth BorderWidth 0} + -font {ALIAS label -font} + -fg -foreground + -foreground {ALIAS label -foreground} + -indicatorcolor {indicatorColor Color #5ae6fe} + -indicatorcolour -indicatorcolor + -itembackground {itemBackground Background {}} + -itemfgfinished {itemForegroundFinished Foreground #00ff00} + -itemtype {itemType ItemType document} + -labelanchor {labelAnchor Anchor c} + -labeltext {labelText Text {}} + -labelwidth {labelWidth Width 0} + -maxvalue {maxValue Value 0} + -orientation {orientation Orientation horizontal} + -relief {relief Relief flat} + -showvalue {showValue ShowValue 1} + -showerror {showError ShowError 1} + -value {value Value 0} + -variable {variable Variable {}} +} +# Create this to make sure there are registered in auto_mkindex +# these must come before the [widget create ...] +proc Progressbar args {} +proc progressbar args {} +widget create Progressbar + +;proc Progressbar:construct {w} { + upvar \#0 $w data + + ## Private variables + array set data { + counter 0 + } + set data(items) $data(class)${w}ITEMS + + grid $data(label) $data(canvas) -in $w -sticky ns + grid configure $data(canvas) -sticky news + grid columnconfig $w 1 -weight 1 + grid rowconfig $w 0 -weight 1 + grid remove $data(label) + + bind $data(canvas) [list Progressbar:resize $w %w %h] +} + +;proc Progressbar:init {w} { + upvar \#0 $w data + $data(basecmd) create rect -1 0 0 25 -fill $data(-indicatorcolor) \ + -tags bar -outline {} + $data(basecmd) create text 25 12 -fill $data(-foreground) \ + -tags text -anchor c + $data(basecmd) xview moveto 0 + $data(basecmd) yview moveto 0 +} + +;proc Progressbar:configure { w args } { + upvar \#0 $w data + + set truth {^(1|yes|true|on)$} + set resize 0 + set force 0 + foreach {key val} $args { + switch -- $key { + -borderwidth - -relief { .$w configure $key $val } + -font { + $data(label) configure -font $val + $data(basecmd) itemconfigure text -font $val + } + -foreground { + $data(label) configure -foreground $val + $data(basecmd) itemconfigure text -fill $val + } + -indicatorcolor { + $data(basecmd) itemconfigure bar -fill $val + } + -labelanchor { $data(label) configure -anchor $val } + -labeltext { + $data(label) configure -text $val + if {[string compare {} $val]} { + grid $data(label) + } else { + grid remove $data(label) + } + } + -labelwidth { $data(label) configure -width $val } + -maxvalue { + if {![regexp {^[0-9]+$} $val] || $val<0} { + return -code error "$key must be a positive integer" + } + set force 1 + } + -orientation { + if {[string match h* $val]} { + set val horizontal + } elseif {[string match v* $val]} { + set val vertical + } else { + return -code error \ + "orientation must be horizontal or vertical" + } + if {[string compare $data($key) $val]} { + set W [$data(basecmd) cget -width] + set H [$data(basecmd) cget -height] + $data(basecmd) configure -height $W -width $H + set resize 1 + } + } + -showvalue { + set val [regexp -nocase $truth $val] + set resize 1 + } + -showerror { set val [regexp -nocase $truth $val] } + -value { + if {[catch {Progressbar:set $w $val} err] && \ + $data(-showerror)} { + return -code error $err + } + if {$resize} { set resize 0 } + if {$force} { set force 0 } + continue + } + -variable { + if {![string compare $val $data(-variable)]} return + if {[string compare {} $data(-variable)]} { + uplevel \#0 [list trace vdelete $data(-variable) wu \ + "Progressbar:trace $w"] + set data(-variable) {} + } + if {[string compare {} $val]} { + set data(-variable) $val + upvar \#0 $val var + if {![info exists var] || \ + [catch {Progressbar:set $w $var} err]} { + set var $data(-value) + } + uplevel \#0 [list trace var $val wu "Progressbar:trace $w"] + } + ## avoid the set data($key) + continue + } + } + set data($key) $val + } + if {$force || ($resize && [winfo ismapped $data(canvas)])} { + Progressbar:resize $w [winfo width $data(canvas)] \ + [winfo height $data(canvas)] + } +} + +;proc Progressbar:destroy w { + upvar \#0 $w data + catch { Progressbar:configure $w -variable {} } +} + +;proc Progressbar:trace {w name el op} { + upvar \#0 $w data + upvar \#0 $data(-variable) var + if {[string match u $op]} { + set var $data(-value) + uplevel \#0 [list trace var $data(-variable) wu "Progressbar:trace $w"] + } elseif {[catch {Progressbar:set $w $var} err]} { + set var $data(-value) + if $data(-showerror) { return -code error $err } + } +} + +;proc Progressbar:resize {w W H} { + upvar \#0 $w data + + ## Assume a maxvalue of 100 if maxvalue is 0 (works like %age) + if {$data(-maxvalue)} { + set pcnt [expr {$data(-value)/double($data(-maxvalue))}] + } else { + set pcnt [expr {$data(-value)/100.0}] + } + if {[string match h* $data(-orientation)]} { + $data(basecmd) coords bar -1 0 [expr {$pcnt*$W}] $H + } else { + ## Vertical orientation needs testing + $data(basecmd) coords bar -1 $H $W [expr {$pcnt*$H}] + } + if $data(-showvalue) { + $data(basecmd) coords text [expr {$W/2}] [expr {$H/2-2}] + $data(basecmd) itemconfigure text -text [expr $pcnt*100.0]% + } else { + $data(basecmd) coords text $W $H + } +} + +;proc Progressbar:set {w val} { + upvar \#0 $w data + if {![regexp {^[0-9]+$} $val] || $val<0} { + return -code error "value must be an integer greater than 0" + } + if {[string comp {} $data(-variable)]} { + upvar \#0 $data(-variable) var + if {[catch {set var $val} err]} { + return -code error $err + } + } + set data(-value) $val + Progressbar:resize $w [winfo width $data(canvas)] \ + [winfo height $data(canvas)] +} + +# Manage progress items. These may be documents or images. +# (There needs to be an extensible system to allow other types, eg. Tclets) +# Each item may have a max value and a current value. +# The total download progress is calculated from the sums of item sizes. + +;proc Progressbar_create {w args} { + upvar \#0 $w data + + set cnt [incr data(counter)] + if {[string match -* [lindex $args 0]]} { + # Invent a name + set item progress$cnt + } else { + set item [lindex $args 0] + set args [lrange $args 1 end] + if {[info exists data(I:$item)]} { + # Ensure name doesn't already exist + return -code error "item \"$item\" already exists" + } + } + + array set config [list \ + -background $data(-itembackground) \ + -fgstart $data(-indicatorcolor) \ + -fgfinished $data(-itemfgfinished) \ + -maxvalue 100 \ + -type $data(-itemtype) \ + -value 0 \ + ] + array set configargs $args + if {[info exists configargs(-type)]} { + if {[string match {} \ + [info commands Progressbar:icon:$configargs(-type)]]} { + return -code error "invalid item type $configargs(-type)" + } + set config(-type) $configargs(-type) + unset configargs(-type) + } + incr data(-maxvalue) $config(-maxvalue) + incr data(-value) $config(-value) + # Add to display + set config(image) [image create bitmap $w:$item \ + -data [Progressbar:icon:$config(-type) cget -data] \ + -foreground $config(-fgstart) \ + -background $config(-background)] + set config(w) [label $w.item$cnt -image $config(image)] + foreach {ncols nrows} [grid size $w] break + if {[string match h* $data(-orientation)]} { + grid $config(w) -row 0 -column $ncols + } else { + grid $config(w) -row $nrows -column 0 + } + + set data(I:$item) [array get config] + + if {[string compare {} $args]} { + eval Progressbar_itemconfigure [list $w] [list $item] \ + [array get configargs] + } else { + Progressbar:set $w $data(-value) + } + + return $item +} + +# Turns #rgb into 3 elem list of decimal vals. +;proc Progressbar:parse_color c { + set c [string tolower $c] + if {[regexp {^\#([0-9a-f])([0-9a-f])([0-9a-f])$} $c x r g b]} { + # appending "0" right-shifts 4 bits + scan "${r}0 ${g}0 ${b}0" "%x %x %x" r g b + } else { + if {![regexp {^\#([0-9a-f]+)$} $c junk hex] || \ + [set len [string length $hex]]>12 || $len%3 != 0} { + return -code error "bad color value \"$c\"" + } + set len [expr {$len/3}] + scan $hex "%${len}x%${len}x%${len}x" r g b + } + return [list $r $g $b] +} + +## Returns a shade between two colors based on the frac (0.0-1.0) +;proc Progressbar:shade {orig dest frac} { + if {$frac >= 1.0} { return $dest } elseif {$frac <= 0.0} { return $orig } + foreach {origR origG origB} [Progressbar:parse_color $orig] \ + {destR destG destB} [Progressbar:parse_color $dest] { + set shade [format "\#%02x%02x%02x" \ + [expr {int($origR+double($destR-$origR)*$frac)}] \ + [expr {int($origG+double($destG-$origG)*$frac)}] \ + [expr {int($origB+double($destB-$origB)*$frac)}]] + return $shade + } +} + +;proc Progressbar_delete {w args} { + upvar \#0 $w data + + foreach item $args { + ## Don't complain about unknown items when deleting + if {![info exists data(I:$item)]} continue + + array set config $data(I:$item) + + incr data(-value) -$config(-value) + incr data(-maxvalue) -$config(-maxvalue) + if {$data(-value) < 0} { set data(-value) 0 } + if {$data(-maxvalue) < 0} { set data(-maxvalue) 0 } + + destroy $config(w) + image delete $config(image) + unset data(I:$item) + } + Progressbar:set $w $data(-value) +} + +## Progressbar_itemconfigure +## configure a progressar constituent item +## +;proc Progressbar_itemconfigure {w item args} { + upvar \#0 $w data + + if {![info exists data(I:$item)]} { + return -code error "unknown item \"$item\"" + } + + array set config $data(I:$item) + if {[string match {} $args]} { return [array get config -*] } + + set valChanged 0 + foreach {key val} $args { + if {[string match {} [set arg [array names config $key]]]} { + set arg [array names config ${key}*] + } + set num [llength $arg] + if {$num==0} { + return -code error "unknown option \"$key\", must be:\ + [join [array names config -*] {, }]" + } elseif {$num>1} { + return -code error "ambiguous option \"$args\",\ + must be one of: [join $arg {, }]" + } else { + set key $arg + } + switch -- $key { + -maxvalue { + if {![regexp {^[0-9]+$} $val] || $val<=0} { + return -code error "$key must be an integer greater than 0" + } + incr data(-maxvalue) [expr {$val-$config(-maxvalue)}] + if {$data(-maxvalue) < 0} { set data(-maxvalue) 0 } + set valChanged 1 + } + -value { + if {![regexp {^[0-9]+$} $val] || $val<0} { + return -code error "$key must be a postive integer" + } + incr data(-value) [expr {$val-$config(-value)}] + if {$data(-value) < 0} { set data(-value) 0 } + set valChanged 1 + } + -type { + ## Should we allow this to be changed? + return -code error "-type cannot be changed after creation" + } + -fgstart { + if {![regexp {^\#([0-9a-f]+)$} $val]} { + return -code error "color value must be in \#rgb format" + } + } + -fgfinished { + if {![regexp {^\#([0-9a-f]+)$} $val]} { + return -code error "color value must be in \#rgb format" + } + } + } + set config($key) $val + } + set data(I:$item) [array get config] + + if {$config(-maxvalue)} { + $config(image) configure -background $config(-background) \ + -foreground [Progressbar:shade \ + $config(-fgstart) $config(-fgfinished) \ + [expr {double($config(-value))/$config(-maxvalue)}]] + } + if {$valChanged} { Progressbar:set $w $data(-value) } +} + +## Progressbar_itemcget +## Returns a single item option +## +;proc Progressbar_itemcget {w item opt} { + upvar \#0 $w data + + if {![info exists data(I:$item)]} { + return -code error "unknown item \"$item\"" + } + array set config $data(I:$item) + ## Ensure that we are getting a -'ed value + if {![info exists config(-[string range $opt 1 end])]} { + return -code error "unknown option \"$opt\"" + } + return $config($opt) +} + +## Progressbar_names +## Return a list of item names +## +;proc Progressbar_names {w {pattern *}} { + upvar \#0 $w data + + set items {} + foreach name [array names data I:$pattern] { + lappend items [string range $name 2 end] + } + return $items +} + +## Progressbar_recalculate +## recalculates the percentage based purely on the constituent items +## If there are no items, it just ensures that -(max)value is >= 0 +## +;proc Progressbar_recalculate {w} { + upvar \#0 $w data + + set items [array names data I:*] + if {[string compare {} $items]} { + set data(-maxvalue) 0 + set data(-value) 0 + foreach item $items { + array set config $data($item) + if {$config(-value) < 0} {set config(-value) 0} + if {$config(-maxvalue) < 0} {set config(-maxvalue) 0} + incr data(-value) $config(-value) + incr data(-maxvalue) $config(-maxvalue) + set data($item) [array get config] + } + } else { + if {$data(-value) < 0} {set data(-value) 0} + if {$data(-maxvalue) < 0} {set data(-maxvalue) 0} + } + Progressbar:set $w $data(-value) + return +} + +image create bitmap Progressbar:icon:document -data {#define document_width 20 +#define document_height 23 +static char document_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x1f, 0x00, 0x04, 0x30, 0x00, 0x04, 0x50, 0x00, 0x04, 0x90, 0x00, + 0x04, 0x10, 0x01, 0x04, 0xf0, 0x03, 0x04, 0x00, 0x02, 0x04, 0x00, 0x02, + 0x04, 0x00, 0x02, 0x04, 0x00, 0x02, 0x04, 0x00, 0x02, 0x04, 0x00, 0x02, + 0x04, 0x00, 0x02, 0x04, 0x00, 0x02, 0x04, 0x00, 0x02, 0x04, 0x00, 0x02, + 0x04, 0x00, 0x02, 0x04, 0x00, 0x02, 0xfc, 0xff, 0x03}; +} + +image create bitmap Progressbar:icon:image -data {#define image_width 20 +#define image_height 23 +static char image_bits[] = { + 0xe0, 0xff, 0xff, 0x20, 0xe0, 0xff, 0xe0, 0xff, 0xff, 0x30, 0xff, 0xff, + 0xe8, 0xf8, 0xff, 0xdf, 0xf7, 0xff, 0xbb, 0xff, 0xff, 0x7b, 0xff, 0xff, + 0xfb, 0xfe, 0xff, 0xfb, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, + 0xcf, 0x1f, 0xfc, 0x03, 0x0e, 0xf8, 0x20, 0x70, 0xf0, 0x18, 0x80, 0xf1, + 0x07, 0x00, 0xf0, 0x00, 0x1e, 0xf0, 0xf8, 0x01, 0xf0, 0x00, 0x00, 0xf0, + 0xc0, 0x7f, 0xf3, 0x00, 0x80, 0xf0, 0x40, 0x00, 0xf0}; +} +return diff --git a/tcl/tabnotebook.tcl b/tcl/tabnotebook.tcl new file mode 100644 index 0000000..a4c5e3d --- /dev/null +++ b/tcl/tabnotebook.tcl @@ -0,0 +1,555 @@ +## +## Copyright 1997 Jeffrey Hobbs, CADIX International +## + +##------------------------------------------------------------------------ +## PROCEDURE +## tabnote +## +## DESCRIPTION +## Implements a Tabbed Notebook megawidget +## +## ARGUMENTS +## tabnote +## +## OPTIONS +## (Any entry widget option may be used in addition to these) +## +## -activebackground color DEFAULT: {} +## The background color given to the active tab. A value of {} +## means these items will pick up the widget's background color. +## +## -background color DEFAULT: DEFAULT +## The background color for the container subwidgets. +## +## -browsecmd script DEFAULT: {} +## A script that is executed each time a tab changes. It appends +## the old tab and the new tab to the script. An empty string ({}) +## represents the blank (empty) tab. +## +## -disabledbackground color DEFAULT: #c0c0c0 (dark gray) +## The background color given to disabled tabs. +## +## -justify justification DEFAULT: center +## The justification applied to the text in multi-line tabs. +## Must be one of: left, right, center. +## +## -linewidth pixels DEFAULT: 1 +## The width of the line surrounding the tabs. Must be at least 1. +## +## -linecolor color DEFAULT: black +## The color of the line surrounding the tabs. +## +## -normalbackground DEFAULT: {} +## The background color of items with normal state. A value of {} +## means these items will pick up the widget's background color. +## +## -padx pixels DEFAULT: 4 +## The X padding for folder tabs around the items. +## +## -pady pixels DEFAULT: 2 +## The Y padding for folder tabs around the items. +## +## RETURNS: the window pathname +## +## BINDINGS (in addition to default widget bindings) +## +## <1> in a tabs activates that tab. +## +## METHODS +## These are the methods that the Tabnote widget recognizes. Aside from +## these, it accepts methods that are valid for entry widgets. +## +## configure ?option? ?value option value ...? +## cget option +## Standard tk widget routines. +## +## activate id +## Activates the tab specified by id. id may either by the unique id +## returned by the add command or the string used in the add command. +## +## add string ?-window widget? ?-state state? +## Adds a tab to the tab notebook with the specified string, unless +## the string is the name of an image, in which case the image is used. +## Each string must be unique. The widget specifies a widget to show +## when that tab is pressed. It must be a child of the tab notebook +## (required for grid management) and exist prior to the 'add' command +## being called. The optional state can be normal (default), active or +## or disabled. If active is given, then this tab becomes the active +## tab. A unique tab id is returned. +## +## delete id +## Deletes the tab specified by id. id may either by the unique id +## returned by the add command or the string used in the add command. +## +## itemconfigure ?option? ?value option value ...? +## itemcget option +## Configure or retrieve the option of a tab notebook item. +## +## name tabId +## Returns the text name for a given tabId. +## +## subwidget widget +## Returns the true widget path of the specified widget. Valid +## widgets are hold (a frame), tabs (a canvas), blank (a frame). +## +## NAMESPACE & STATE +## The megawidget creates a global array with the classname, and a +## global array which is the name of each megawidget created. The latter +## array is deleted when the megawidget is destroyed. +## Public procs of $CLASSNAME and [string tolower $CLASSNAME] are used. +## Other procs that begin with $CLASSNAME are private. For each widget, +## commands named .$widgetname and $CLASSNAME$widgetname are created. +## +## EXAMPLE USAGE: +## +## +##------------------------------------------------------------------------ + +#package require Widget 1.0 +package provide Tabnotebook 1.3 + +array set Tabnotebook { + type frame + base frame + components { + {frame hold hold {-relief raised -bd 1}} + {frame blank} + {frame hide hide \ + {-background $data(-background) -height 1 -width 40}} + {canvas tabs tabs {-bg $data(-background) \ + -highlightthickness 0 -takefocus 0}} + } + + -activebackground {activeBackground ActiveBackground {}} + -bg -background + -background {ALIAS frame -background} + -bd -borderwidth + -borderwidth {ALIAS frame -borderwidth} + -browsecmd {browseCmd BrowseCommand {}} + -disabledbackground {disabledBackground DisabledBackground #a3a3a3} + -normalbackground {normalBackground normalBackground #c3c3c3} + -justify {justify Justify center} + -minwidth {minWidth Width -1} + -minheight {minHeight Height -1} + -padx {padX PadX 4} + -pady {padY PadY 2} + -relief {ALIAS frame -relief} + -linewidth {lineWidth LineWidth 1} + -linecolor {lineColor LineColor black} +} +# Create this to make sure there are registered in auto_mkindex +# these must come before the [widget create ...] +proc Tabnotebook args {} +proc tabnotebook args {} +widget create Tabnotebook + +;proc Tabnotebook:construct {w args} { + upvar \#0 $w data + + ## Private variables + array set data { + curtab {} + numtabs 0 + width 0 + height 0 + ids {} + } + + $data(tabs) yview moveto 0 + $data(tabs) xview moveto 0 + + grid $data(tabs) -sticky ew + grid $data(hold) -sticky news + grid $data(blank) -in $data(hold) -row 0 -column 0 -sticky nsew + grid columnconfig $w 0 -weight 1 + grid rowconfig $w 1 -weight 1 + grid columnconfig $data(hold) 0 -weight 1 + grid rowconfig $data(hold) 0 -weight 1 + + bind $data(tabs) " + if {\[string compare $data(tabs) %W\]} return + Tabnotebook:resize [list $w] %w + " + bind $data(tabs) <2> { %W scan mark %x 0 } + bind $data(tabs) { + %W scan dragto %x 0 + Tabnotebook:resize [winfo parent %W] [winfo width %W] + } +} + +;proc Tabnotebook:configure { w args } { + upvar \#0 $w data + + set truth {^(1|yes|true|on)$} + set post {} + foreach {key val} $args { + switch -- $key { + -activebackground { + if {[string compare $data(curtab) {}]} { + $data(tabs) itemconfig POLY:$data(curtab) -fill $val + } + if {[string compare $val {}]} { + $data(hide) config -bg $val + } else { + lappend post {$data(hide) config -bg $data(-background)} + } + } + -background { + $data(tabs) config -bg $val + $data(hold) config -bg $val + $data(blank) config -bg $val + } + -borderwidth { + $data(hold) config -bd $val + $data(hide) config -height $val + } + -disabledbackground { + foreach i $data(ids) { + if {[string match disabled $data(:$i:-state)]} { + $data(tabs) itemconfig POLY:$i -fill $val + } + } + } + -justify { $data(tabs) itemconfig TEXT -justify $val } + -linewidth { + $data(tabs) itemconfigure LINE -width $val + } + -linecolor { + $data(tabs) itemconfigure LINE -fill $val + } + -minwidth { + if {$val >= 0} { grid columnconfig $w 0 -minsize $val } + } + -minheight { + if {$val >= 0} { grid rowconfig $w 1 -minsize $val } + } + -normalbackground { + foreach i $data(ids) { + if {[string match normal $data(:$i:-state)]} { + $data(tabs) itemconfig POLY:$i -fill $val + } + } + } + -padx - -pady { + if {$val <= 0} { set val 1 } + } + -relief { + $data(hold) config -relief $val + } + } + set data($key) $val + } + if {[string compare $post {}]} { + eval [join $post \n] + } +} + +;proc Tabnotebook_add { w text args } { + upvar \#0 $w data + + set c $data(tabs) + if {[string match {} $text]} { + return -code error "non-empty text required for noteboook label" + } elseif {[string compare {} [$c find withtag ID:$text]]} { + return -code error "tab \"$text\" already exists" + } + array set s { + -window {} + -state normal + } + foreach {key val} $args { + switch -glob -- $key { + -w* { + if {[string compare $val {}]} { + if {![winfo exist $val]} { + return -code error "window \"$val\" does not exist" + } elseif {[string comp $w [winfo parent $val]] && \ + [string comp $data(hold) [winfo parent $val]]} { + return -code error "window \"$val\" must be a\ + child of the tab notebook ($w)" + } + } + set s(-window) $val + } + -s* { + if {![regexp {^(normal|disabled|active)$} $val]} { + return -code error "unknown state \"$val\", must be:\ + normal, disabled or active" + } + set s(-state) $val + } + default { + return -code error "unknown option '$key', must be:\ + [join [array names s] {, }]" + } + } + } + set tabnum [incr data(numtabs)] + set px $data(-padx) + set py $data(-pady) + if {[lsearch -exact [image names] $text] != -1} { + set i [$c create image $px $py -image $text -anchor nw \ + -tags [list IMG ID:$text TAB:$tabnum]] + } else { + set i [$c create text [expr {$px+1}] $py -text $text -anchor nw \ + -tags [list TEXT ID:$text TAB:$tabnum] \ + -justify $data(-justify)] + } + foreach {x1 y1 x2 y2} [$c bbox $i] { + set W [expr {$x2-$x1+$px}] + set FW [expr {$W+$px}] + set FH [expr {$y2-$y1+3*$py}] + } + set diff [expr {$FH-$data(height)}] + if {$diff > 0} { + $c move all 0 $diff + $c move $i 0 -$diff + set data(height) $FH + } + $c create poly 0 $FH $px $py $W $py $FW $FH -fill {} \ + -tags [list POLY POLY:$tabnum TAB:$tabnum] + $c create line 0 $FH $px $py $W $py $FW $FH \ + -tags [list LINE LINE:$tabnum TAB:$tabnum] \ + -width $data(-linewidth) -fill $data(-linecolor) + $c move TAB:$tabnum $data(width) [expr {($diff<0)?-$diff:0}] + $c raise $i + $c raise LINE:$tabnum + incr data(width) $FW + $c config -width $data(width) -height $data(height) \ + -scrollregion "0 0 $data(width) $data(height)" + $c bind TAB:$tabnum <1> [list Tabnotebook_activate $w $tabnum] + array set data [list :$tabnum:-window $s(-window) \ + :$tabnum:-state $s(-state)] + if {[string compare $s(-window) {}]} { + grid $s(-window) -in $data(hold) -row 0 -column 0 -sticky nsew + lower $s(-window) + } + switch $s(-state) { + active { Tabnotebook_activate $w $tabnum } + disabled {$c itemconfig POLY:$tabnum -fill $data(-disabledbackground)} + normal {$c itemconfig POLY:$tabnum -fill $data(-normalbackground)} + } + lappend data(ids) $tabnum + return $tabnum +} + +;proc Tabnotebook_activate { w id } { + upvar \#0 $w data + + if {[string compare $id {}]} { + set tab [Tabnotebook:verify $w $id] + if {[string match disabled $data(:$tab:-state)]} return + } else { + set tab {} + } + if {[string match $data(curtab) $tab]} return + set c $data(tabs) + set oldtab $data(curtab) + if {[string compare $oldtab {}]} { + $c itemconfig POLY:$oldtab -fill $data(-normalbackground) + set data(:$oldtab:-state) normal + } + set data(curtab) $tab + if {[string compare $tab {}]} { + set data(:$tab:-state) active + $c itemconfig POLY:$tab -fill $data(-activebackground) + } + if {[info exists data(:$tab:-window)] && \ + [winfo exists $data(:$tab:-window)]} { + raise $data(:$tab:-window) + } else { + raise $data(blank) + } + Tabnotebook:resize $w [winfo width $w] + if {[string comp $data(-browsecmd) {}]} { + uplevel \#0 $data(-browsecmd) \ + [list [Tabnotebook_name $w $oldtab] [Tabnotebook_name $w $tab]] + } +} + +;proc Tabnotebook_delete { w id } { + upvar \#0 $w data + + set tab [Tabnotebook:verify $w $id] + set c $data(tabs) + foreach {x1 y1 x2 y2} [$c bbox TAB:$tab] { set W [expr {$x2-$x1-3}] } + $c delete TAB:$tab + for { set i [expr {$tab+1}] } { $i <= $data(numtabs) } { incr i } { + $c move TAB:$i -$W 0 + } + foreach {x1 y1 x2 y2} [$c bbox all] { set H [expr {$y2-$y1-3}] } + if {$H<$data(height)} { + $c move all 0 [expr {$H-$data(height)}] + set data(height) $H + } + incr data(width) -$W + $c config -width $data(width) -height $data(height) \ + -scrollregion "0 0 $data(width) $data(height)" + set i [lsearch $data(ids) $tab] + set data(ids) [lreplace $data(ids) $i $i] + catch {grid forget $data(:$tab:-window)} + unset data(:$tab:-state) data(:$tab:-window) + if {[string match $tab $data(curtab)]} { + set data(curtab) {} + raise $data(blank) + } +} + +;proc Tabnotebook_itemcget { w id key } { + upvar \#0 $w data + + set tab [Tabnotebook:verify $w $id] + set opt [array names data :$tab:$key*] + set len [llength $opt] + if {$len == 1} { + return $data($opt) + } elseif {$len == 0} { + set all [array names data :$tab:-*] + foreach o $all { lappend opts [lindex [split $o :] end] } + return -code error "unknown option \"$key\", must be one of:\ + [join $opts {, }]" + } else { + foreach o $opt { lappend opts [lindex [split $o :] end] } + return -code error "ambiguous option \"$key\", must be one of:\ + [join $opts {, }]" + } +} + +;proc Tabnotebook_itemconfigure { w id args } { + upvar \#0 $w data + + set tab [Tabnotebook:verify $w $id] + set len [llength $args] + if {$len == 1} { + return [uplevel Tabnotebook_itemcget $w $tab $args] + } elseif {$len&1} { + return -code error "uneven set of key/value pairs in \"$args\"" + } + if {[string match {} $args]} { + set all [array names data :$tab:-*] + foreach o $all { lappend res [lindex [split $o :] end] $data($o) } + return $res + } + foreach {key val} $args { + switch -glob -- $key { + -w* { + if {[string comp $val {}]} { + if {![winfo exist $val]} { + return -code error "window \"$val\" does not exist" + } elseif {[string comp $w [winfo parent $val]] && \ + [string comp $data(hold) [winfo parent $val]]} { + return -code error "window \"$val\" must be a\ + child of the tab notebook ($w)" + } + } + set old $data(:$tab:-window) + if {[winfo exists $old]} { grid forget $old } + set data(:$tab:-window) $val + if {[string comp $val {}]} { + grid $val -in $data(hold) -row 0 -column 0 \ + -sticky nsew + lower $val + } + if {[string match active $data(:$tab:-state)]} { + if {[string comp $val {}]} { + raise $val + } else { + raise $data(blank) + } + } + } + -s* { + if {![regexp {^(normal|disabled|active)$} $val]} { + return -code error "unknown state \"$val\", must be:\ + normal, disabled or active" + } + if {[string match $val $data(:$tab:-state)]} return + set old $data(:$tab:-state) + switch $val { + active { + set data(:$tab:-state) $val + Tabnotebook_activate $w $tab + } + disabled { + if {[string match active $old]} { + Tabnotebook_activate $w {} + } + $data(tabs) itemconfig POLY:$tab \ + -fill $data(-disabledbackground) + set data(:$tab:-state) $val + } + normal { + if {[string match active $old]} { + Tabnotebook_activate $w {} + } + $data(tabs) itemconfig POLY:$tab -fill {} + set data(:$tab:-state) $val + } + } + } + default { + return -code error "unknown option '$key', must be:\ + [join [array names s] {, }]" + } + } + } +} + +## given a tab number, return the text +;proc Tabnotebook_name { w id } { + upvar \#0 $w data + + if {[string match {} $id]} return + set text {} + foreach item [$data(tabs) find withtag TAB:$id] { + set tags [$data(tabs) gettags $item] + if {[set i [lsearch -glob $tags {ID:*}]] != -1} { + set text [string range [lindex $tags $i] 3 end] + break + } + } + return $text +} + +;proc Tabnotebook:resize { w x } { + upvar \#0 $w data + + if {[string compare $data(curtab) {}]} { + set x [expr {round(-[$data(tabs) canvasx 0])}] + foreach {x1 y1 x2 y2} [$data(tabs) bbox TAB:$data(curtab)] { + place $data(hide) -y [winfo y $data(hold)] -x [expr {$x1+$x+3}] + $data(hide) config -width [expr {$x2-$x1-5}] + } + } else { + place forget $data(hide) + } +} + +;proc Tabnotebook:see { w id } { + upvar \#0 $w data + + set c $data(tabs) + set box [$c bbox $id] + if {[string match {} $box]} return + foreach {x y x1 y1} $box {left right} [$c xview] \ + {p q xmax ymax} [$c cget -scrollregion] { + set xpos [expr (($x1+$x)/2.0)/$xmax - ($right-$left)/2.0] + } + $c xview moveto $xpos +} + +;proc Tabnotebook:verify { w id } { + upvar \#0 $w data + + set c $data(tabs) + if {[string comp {} [set i [$c find withtag ID:$id]]]} { + if {[regexp {TAB:([0-9]+)} [$c gettags [lindex $i 0]] junk id]} { + return $id + } + } elseif {[string comp {} [$c find withtag TAB:$id]]} { + return $id + } + return -code error "unrecognized tab \"$id\"" +} + diff --git a/tcl/tclIndex b/tcl/tclIndex new file mode 100644 index 0000000..711522e --- /dev/null +++ b/tcl/tclIndex @@ -0,0 +1,79 @@ +# Tcl autoload index file, version 2.0 +# This file is generated by the "auto_mkindex" command +# and sourced to set up indexing information for one or +# more commands. Typically each line is a command that +# sets an element in the auto_index array, where the +# element name is the name of a command and the value is +# a script that loads the command. + +set auto_index(widget) [list source [file join $dir widget.tcl]] +set auto_index(ScrolledText) [list source [file join $dir widget.tcl]] +set auto_index(scrolledtext) [list source [file join $dir widget.tcl]] +set auto_index(planchet) [list source [file join $dir planchet.tcl]] +set auto_index(balloonhelp) [list source [file join $dir balloonhelp.tcl]] +set auto_index(Tabnotebook) [list source [file join $dir tabnotebook.tcl]] +set auto_index(tabnotebook) [list source [file join $dir tabnotebook.tcl]] +set auto_index(Console) [list source [file join $dir console.tcl]] +set auto_index(console) [list source [file join $dir console.tcl]] +set auto_index(ConsoleDialog) [list source [file join $dir console.tcl]] +set auto_index(consoledialog) [list source [file join $dir console.tcl]] +set auto_index(console_dialog) [list source [file join $dir console.tcl]] +set auto_index(echo) [list source [file join $dir console.tcl]] +set auto_index(alias) [list source [file join $dir console.tcl]] +set auto_index(dump) [list source [file join $dir console.tcl]] +set auto_index(which) [list source [file join $dir console.tcl]] +set auto_index(dir) [list source [file join $dir console.tcl]] +set auto_index(lremove) [list source [file join $dir console.tcl]] +set auto_index(unknown) [list source [file join $dir console.tcl]] +set auto_index(tcl_unknown) [list source [file join $dir console.tcl]] +set auto_index(Calculator) [list source [file join $dir calculator.tcl]] +set auto_index(calculator) [list source [file join $dir calculator.tcl]] +set auto_index(Combobox) [list source [file join $dir combobox.tcl]] +set auto_index(combobox) [list source [file join $dir combobox.tcl]] +set auto_index(Help) [list source [file join $dir help.tcl]] +set auto_index(help) [list source [file join $dir help.tcl]] +set auto_index(HelpDialog) [list source [file join $dir help.tcl]] +set auto_index(helpdialog) [list source [file join $dir help.tcl]] +set auto_index(help_dialog) [list source [file join $dir help.tcl]] +set auto_index(Progressbar) [list source [file join $dir progressbar.tcl]] +set auto_index(progressbar) [list source [file join $dir progressbar.tcl]] +set auto_index(Ventry) [list source [file join $dir ventry.tcl]] +set auto_index(ventry) [list source [file join $dir ventry.tcl]] +set auto_index(Hierarchy) [list source [file join $dir hierarchy.tcl]] +set auto_index(hierarchy) [list source [file join $dir hierarchy.tcl]] +set auto_index(hierarchy_dir) [list source [file join $dir hierarchy.tcl]] +set auto_index(hierarchy_widget) [list source [file join $dir hierarchy.tcl]] +set auto_index(layer) [list source [file join $dir layer.tcl]] +set auto_index(legend) [list source [file join $dir legend.tcl]] +set {auto_index($legname)} [list source [file join $dir legend.tcl]] +set auto_index(fgisLegend_title) [list source [file join $dir legend.tcl]] +set auto_index(fgisLegend_subtitle) [list source [file join $dir legend.tcl]] +set auto_index(fgisLegend_print) [list source [file join $dir legend.tcl]] +set auto_index(fgisLegend_set) [list source [file join $dir legend.tcl]] +set auto_index(fgisLegend_drawable) [list source [file join $dir legend.tcl]] +set auto_index(fgisLegend_delete) [list source [file join $dir legend.tcl]] +set auto_index(show_legend) [list source [file join $dir legend.tcl]] +set auto_index(color_box) [list source [file join $dir legend.tcl]] +set auto_index(fgisMakeObjectName) [list source [file join $dir objects.tcl]] +set auto_index(fgisCheckName) [list source [file join $dir objects.tcl]] +set auto_index(fgisSetObj) [list source [file join $dir objects.tcl]] +set auto_index(fgisSetList) [list source [file join $dir objects.tcl]] +set auto_index(getopt) [list source [file join $dir getopt.tcl]] +set auto_index(handleopt) [list source [file join $dir getopt.tcl]] +set auto_index(checkbooleanopt) [list source [file join $dir getopt.tcl]] +set auto_index(checklistopt) [list source [file join $dir getopt.tcl]] +set auto_index(checkintopt) [list source [file join $dir getopt.tcl]] +set auto_index(toolbar) [list source [file join $dir toolbar.tcl]] +set auto_index(__ruler_y) [list source [file join $dir toolbar.tcl]] +set auto_index(__show_scale) [list source [file join $dir toolbar.tcl]] +set auto_index(fgisPrintDialog) [list source [file join $dir toolbar.tcl]] +set auto_index(open_layer) [list source [file join $dir viewer.tcl]] +set auto_index(show_layer) [list source [file join $dir viewer.tcl]] +set auto_index(add_layer) [list source [file join $dir viewer.tcl]] +set auto_index(select_layers) [list source [file join $dir viewer.tcl]] +set auto_index(setup_look) [list source [file join $dir viewer.tcl]] +set auto_index(select_layer) [list source [file join $dir viewer.tcl]] +set auto_index(close_layer) [list source [file join $dir viewer.tcl]] +set auto_index(save_layer) [list source [file join $dir viewer.tcl]] +set auto_index(confirmExit) [list source [file join $dir viewer.tcl]] +set auto_index(HMinit_win) [list source [file join $dir html_library.tcl]] diff --git a/tcl/toolbar.tcl b/tcl/toolbar.tcl new file mode 100644 index 0000000..9903b77 --- /dev/null +++ b/tcl/toolbar.tcl @@ -0,0 +1,145 @@ +# +# toolbar.tcl - some standard interface gadgets for fGIS +# +# + +# +# Creates standard fGIS toolbar for given planchet +# Planchet should exist, otherwise you'll have hard time passing +# all toolbar buttons to corresponding planchet options +# wpath is pathname for frame which would be created for toolbar +# +option add *Toolbar*Font -*-times-bold-r-normal--10-* widgetDefault + +proc toolbar {wpath planchet} { +global fgis +set $wpath\(ruler) off +frame $wpath -class Toolbar +button $wpath.print -image [image create bitmap -data { +#define printer_width 16 +#define printer_height 16 +static unsigned char printer_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, + 0x08, 0x08, 0x08, 0x08, 0xfe, 0x3f, 0x01, 0x40, 0x01, 0x5c, 0x01, 0x40, + 0x01, 0x40, 0xfe, 0x3f, 0x04, 0x10, 0xfc, 0x1f, }; +}] -padx 0 -pady 0 -command [list fgisPrintDialog $planchet] +button $wpath.zoom -image [image create bitmap -data { +#define zoom_width 16 +#define zoom_height 16 +static unsigned char zoom_bits[] = { + 0x00, 0x0e, 0x80, 0x31, 0x40, 0x4e, 0x40, 0x51, 0xa0, 0xa4, 0xa0, 0xae, + 0xa0, 0xa4, 0x40, 0x51, 0x40, 0x4e, 0xa0, 0x31, 0x50, 0x0e, 0x28, 0x00, + 0x14, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x03, 0x00, }; +}] -padx 0 -pady 0 -command "$planchet zoom" +button $wpath.unzoom -image [image create bitmap -data { +#define unzoom_width 16 +#define unzoom_height 16 +static unsigned char unzoom_bits[] = { + 0x00, 0x0e, 0x80, 0x31, 0x40, 0x4e, 0x40, 0x51, 0xa0, 0xa0, 0xa0, 0xae, + 0xa0, 0xa0, 0x40, 0x51, 0x40, 0x4e, 0xa0, 0x31, 0x50, 0x0e, 0x28, 0x00, + 0x14, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x03, 0x00, }; +}] -padx 0 -pady 0 -command "$planchet unzoom" +button $wpath.all -image [image create bitmap -data { +#define unzoomall_width 16 +#define unzoomall_height 16 +static unsigned char unzoomall_bits[] = { + 0x00, 0x8e, 0x8c, 0xf1, 0x5a, 0x7e, 0x70, 0x59, 0xa0, 0xae, 0xe0, 0xa7, + 0xe0, 0xa1, 0xc0, 0x51, 0x70, 0x4f, 0xb8, 0x33, 0x5e, 0x0e, 0x2f, 0x08, + 0x15, 0x18, 0x0a, 0x30, 0x05, 0x60, 0x03, 0xc0, }; +}] -padx 0 -pady 0 -command "$planchet limits default" +button $wpath.left -image [image create bitmap -data { +#define left_width 11 +#define left_height 10 +static unsigned char left_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xe0, 0x01, 0xf8, 0x01, 0xfe, 0x01, + 0xf8, 0x01, 0xe0, 0x01, 0x80, 0x01, 0x00, 0x00, }; +}] -pady 3 -padx 2 -command "$planchet shift left" +button $wpath.up -image [image create bitmap -data { +#define up_width 10 +#define up_height 10 +static unsigned char up_bits[] = { + 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x70, 0x00, 0x70, 0x00, 0xf8, 0x00, + 0xf8, 0x00, 0xfc, 0x01, 0xfc, 0x01, 0x00, 0x00, }; +}] -pady 3 -padx 2 -command "$planchet shift up" +button $wpath.down -image [image create bitmap -data { +#define down_width 10 +#define down_height 10 +static unsigned char down_bits[] = { + 0x00, 0x00, 0xfc, 0x01, 0xfc, 0x01, 0xf8, 0x00, 0xf8, 0x00, 0x70, 0x00, + 0x70, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, }; +}] -padx 2 -pady 3 -command "$planchet shift down" +button $wpath.right -image [image create bitmap -data { +#define right_width 11 +#define right_height 10 +static unsigned char right_bits[] = { + 0X00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x3c, 0x00, 0xfc, 0x00, 0xfc, 0x03, + 0xfc, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0x00, 0x00, }; +}] -padx 2 -pady 3 -command "$planchet shift right" +checkbutton $wpath.ruler -image [image create bitmap -data { +#define ruler_width 16 +#define ruler_height 16 +static char ruler_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x40, 0x22, 0x44, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +}] -bd 3 -indicatoron 0 -variable $wpath\(ruler) \ + -onvalue on -offvalue off \ + -command "$planchet ruler \[set $wpath\(ruler)]" +upvar #0 $wpath data +set data(ruler) off +label $wpath.scale -textvariable "$wpath\(scale)" +pack $wpath.print $wpath.zoom $wpath.unzoom $wpath.all $wpath.ruler -side left +pack $wpath.scale -side left -padx 20 +pack $wpath.right $wpath.up $wpath.down $wpath.left -side right +if [winfo exists $planchet] { + $planchet configure -zoombutton $wpath.zoom -unzoombuttons\ + [list $wpath.unzoom $wpath.all] -shiftbuttons \ + [list $wpath.left $wpath.down $wpath.up $wpath.right]\ + -scalevar $wpath\(scale) + $planchet ruler off +} +} + +proc __ruler_y {canvas} { +return [expr [winfo height $canvas] - [$canvas canvasy 1c]+[$canvas canvasy 0c]] +} + +proc __show_scale {widget var index op} { +global map_items +if [llength $map_items($index)]==4 { + set canvas [lindex [split $index ","] 0] + $widget configure -text "Scale 1:[mapscale $canvas]" +} else { + $widget configure -text "Scale unknown" +} +} + +proc fgisPrintDialog planchet { +global fgis +set dialog [toplevel $planchet.print] +wm title $dialog "Print setup" +wm transient $dialog [winfo toplevel $planchet] +radiobutton $dialog.l1 -text "Printer" -value {} -variable\ + fgisPrint(dest) -anchor w\ + -command "$dialog.file configure -state disabled; + $dialog.printer configure -state normal + $dialog.browse configure -state disabled" +entry $dialog.printer -width 10 -textvar fgis(printer) +uplevel set fgisPrint(dest) {} +$dialog.printer insert end $fgis(printer) +radiobutton $dialog.l2 -text "File" -value "-file \$fgisPrint(file)"\ + -var fgisPrint(dest) -anchor w\ + -command "$dialog.file configure -state normal; + $dialog.printer configure -state disabled + $dialog.browse configure -state normal" +entry $dialog.file -textvar fgisPrint(file) -width 20 -state disable +button $dialog.browse -text "Browse.." -command \ + {set fgisPrint(file) [tk_getSaveFile]} -state disable +button $dialog.ok -text Ok -command "eval $planchet print \$fgisPrint(dest) ;\ + destroy $dialog" +button $dialog.cancel -text Cancel -command "destroy $dialog" +grid $dialog.l1 - $dialog.printer - - -sticky news +grid $dialog.l2 - $dialog.file - - $dialog.browse -sticky news +grid x $dialog.ok - x $dialog.cancel x -sticky news +} + diff --git a/tcl/ventry.tcl b/tcl/ventry.tcl new file mode 100644 index 0000000..348f2aa --- /dev/null +++ b/tcl/ventry.tcl @@ -0,0 +1,241 @@ +## +## ventry.tcl +## +## self-validating entry widget +## +## Copyright 1997 Jeffrey Hobbs, CADIX International +## + +##------------------------------------------------------------------------ +## PROCEDURE +## ventry +## +## DESCRIPTION +## Implements a self-validating entry widget +## +## ARGUMENTS +## ventry ?options? +## +## OPTIONS +## +## +## +## RETURNS: the widget name +## +## BINDINGS: +## +##------------------------------------------------------------------------ +## +## Example use at end of file +## + + +######################################################################## +############################# Ventry ############################### +######################################################################## + +array set Ventry { + type frame + base entry + components {label} + + -bd -borderwidth + -borderwidth {borderWidth BorderWidth 0} + -invalidcmd {invalidCmd InvalidCmd bell} + -labeltext {labelText LabelText {}} + -labelwidth {labelWidth Width 0} + -labelanchor {ALIAS label -anchor labelAnchor Anchor} + -labelfont {ALIAS label -font labelFont Font} + -labelforeground {ALIAS label -foreground labelForeground Foreground} + -relief {relief Relief flat} + -validatecmd -vcmd + -vcmd {validateCmd ValidateCmd {}} + -validate {validate Validate none} + -textvariable {textVariable TextVariable {}} +} + +# Create this to make sure there are registered in auto_mkindex +# these must come before the [widget create ...] +proc Ventry args {} +proc ventry args {} +widget create Ventry + +;proc Ventry:construct {w args} { + upvar \#0 $w data + + set data(flags) {} + + grid $data(label) $data(entry) -in $w -sticky ns + grid configure $data(entry) -sticky news + grid columnconfig $w 1 -weight 1 + grid rowconfig $w 0 -weight 1 + grid remove $data(label) + + bind $data(entry) [list Ventry:focus $w in] + bind $data(entry) [list Ventry:focus $w out] +} + +;proc Ventry:configure {w args} { + upvar \#0 $w data + set truth {^(1|yes|true|on)$} + foreach {key val} $args { + switch -- $key { + -borderwidth - -relief { .$w configure $key $val } + -labelanchor { $data(label) configure -anchor $val } + -labelfont { $data(label) configure -font $val } + -labelforeground { $data(label) configure -foreground $val } + -labeltext { + $data(label) configure -text $val + if {[string compare {} $val]} { + grid $data(label) + } else { + grid remove $data(label) + } + } + -labelwidth { $data(label) configure -width $val } + -validate { + if {![regexp {^(focus|focusin|focusout|all|none|key)$} $val]} { + return -code error "Invalid validation type \"$val\"" + } + } + -textvariable { $data(basecmd) configure -textvariable $val } + } + set data($key) $val + } +} + +;proc Ventry_insert {w index string} { + upvar \#0 $w data + + if {[regexp {^(all|key)$} $data(-validate)]} { + set index [$data(basecmd) index $index] + set cur [$data(basecmd) get] + set new [string range $cur 0 [expr $index-1]]$string[string range $cur $index end] + if {[catch {Ventry:validate $w $string $new $index insert} err]} { + return + } + } + return [uplevel [list $data(basecmd) insert $index $string]] +} + +;proc Ventry_delete {w first {last {}}} { + upvar \#0 $w data + + if {[regexp {^(all|key)$} $data(-validate)]} { + set first [$data(basecmd) index $first] + if {[string match {} $last]} { + set last [expr $first+1] + } else { + set last [$data(basecmd) index $last] + } + set cur [$data(basecmd) get] + set new [string range $cur 0 [expr $first-1]][string range $cur $last end] + if {[catch {Ventry:validate $w [string range $cur $first \ + [expr $last-1]] $new $first delete} err]} { + return + } + } + return [uplevel [list $data(basecmd) delete $first] $last] +} + +;proc Ventry_validate {w} { + upvar \#0 $w data + + set old $data(-validate) + set data(-validate) all + set code [catch {Ventry:validate $w {} [$data(basecmd) get] \ + [$data(basecmd) index insert] validate} err] + set data(-validate) $old + return [expr {$code?0:1}] +} + +;proc Ventry:focus {w which} { + upvar \#0 $w data + + if {[regexp "^(all|focus($which)?)\$" $data(-validate)]} { + catch {Ventry:validate $w {} [$data(basecmd) get] \ + [$data(basecmd) index insert] focus$which} + } +} + +;proc Ventry:validate {w str new index type} { + upvar \#0 $w data + + if {[string match {} $data(-vcmd)] || \ + [string match none $data(-validate)]} { + return + } + set data(flags) VALIDATING + + set cmd [Ventry:substitute $w $data(-vcmd) $str $new $index $type] + + set code [catch {uplevel \#0 $cmd} result] + if {$code != 0 && $code != 2} { + global errorInfo + append errorInfo "\n\t(in $w validation command)" + bgerror $result + set code 1 + } else { + set val [regexp {^(1|yes|true|on)$} $result] + if $val { set code 0 } else { set code 3 } + set result {} + } + + # If e->validate has become VALIDATE_NONE during the validation, + # it means that a loop condition almost occured. Do not allow + # this validation result to finish. + if {[string match none $data(-validate)] || \ + [string match VALIDATE_VAR $data(flags)]} { + set code 1 + } + # If validate will return ERROR, then disallow further validations + # Otherwise, if it didn't accept the new string (returned TCL_BREAK) + # then eval the invalidCmd (if it's set) + if {$code} { + if {$code == 3} { + ## TCL_BREAK + if {[string compare {} $data(-invalidcmd)]} { + set cmd [Ventry:substitute $w $data(-invalidcmd) \ + $str $new $index $type] + if {[catch {uplevel \#0 $cmd} result]} { + global errorInfo + append errorInfo "\n\t(in $w validation command)" + bgerror $result + set code 1 + set data(-validate) none + } + } + } else { + set data(-validate) none + } + } + set data(flags) {} + return -code $code $result +} + +;proc Ventry:substitute {w cmd change newstr index type} { + upvar \#0 $w data + + set old $cmd + set i [string first % $cmd] + if {$i < 0} { return $old } + set new [string range $cmd 0 [incr i -1]] + while 1 { + set c [string index $cmd [incr i 2]] + switch $c { + d { append new $type } + i { append new $index } + P { append new [list $newstr] } + s { append new [list [$data(basecmd) get]] } + S { append new [list $change] } + v { append new $data(-validate) } + W { append new [list $w] } + {} { append new %; return $new } + default { append new [list $c] } + } + set cmd [string range $cmd [incr i] end] + set i [string first % $cmd] + if {$i < 0} { return $new$cmd } + append new [string range $cmd 0 [incr i -1]] + } +} diff --git a/tcl/viewer.tcl b/tcl/viewer.tcl new file mode 100644 index 0000000..d03987f --- /dev/null +++ b/tcl/viewer.tcl @@ -0,0 +1,200 @@ +# High-level operation with layers +# +# + +proc open_layer {filename} { +global layerFile +if ![file exists $filename] { + if [file exist $filename.epp] { + append filename .epp + } else { + tk_messageBox -message "File $filename doesn't exists" -type ok + } +} +if {[file extension $filename]==".epp"} { + +set basename [file rootname $filename] +set layer [layer create raster -file $filename -title $basename ] + +if [file exists $basename.leg] { + $layer configure -legfile $basename.leg + set legend [$layer cget -legend] + if [string length [$legend title]] { + $layer configure -title [$legend title] + } +} +if [file exists $basename.clr] { + $layer configure -palfile $basename.clr +} + +} else { + set layer [uplevel #0 source [list $filename]] + set layerFile($layer) $filename +} + return $layer +} + + +#if ![llength $argv] { +# set argv [tk_getOpenFile -filetypes {{"Epp files" *.epp} +# {"fGIS layers" *.lay}}] +#} + +proc show_layer {layer} { + global planchet + if ![string length $layer] return + wm title . "Mapview: [$layer title]" + $planchet show $layer -base +} + +proc add_layer {{file {}}} { + global planchet + if ![string length $file] { + set file [tk_getOpenFile -filetypes {{"Epp files" *.epp} + {"fGIS layers" *.lay}}] + } + if ![string length $file] return + set layer [open_layer $file] + if ![llength [$planchet layers]] { + show_layer $layer + } + $planchet look add $layer + catch {.menu.file.m entryconfig "Save..." -state normal} + catch {.menu.file.m entryconfig "Close..." -state normal} + foreach i {1 2 3} { + catch {.menu.layer.m entryconfig $i -state normal} + } + +} + +proc select_layers {} { + global planchet + foreach layer [$planchet look list] { + set on($layer) 1 + } + catch {destroy .chooser} + toplevel .chooser + wm title .chooser "Select layer" + frame .chooser.t + listbox .chooser.t.l -width 40 -height 10 -yscrollcommand ".chooser.t.y set" -selectmode extended + scrollbar .chooser.t.y -orient vert -command ".chooser.t.l yview" + pack .chooser.t.l .chooser.t.y -side left -fill both -expand y + pack .chooser.t -fill both -expand y + frame .chooser.b + button .chooser.b.ok -padx 10 -text "Apply" -command {setup_look .chooser.t.l} + button .chooser.b.cancel -padx 10 -text "Close" -command {destroy .chooser} + pack .chooser.b.ok -side left + pack .chooser.b.cancel -side left + pack .chooser.b + set box .chooser.t.l + foreach layer [layer names] { + set n [$box size] + $box insert end [$layer title] + if [info exist on($layer)] { + $box selection set $n + } + } + +} + +proc setup_look {box} { + global platnchet + set layers [layer names] + $planchet look remove all + foreach n [$box curselection] { + $planchet look add [lindex $layers $n] + } +} + +proc select_layer {} { + global planchet + catch {destroy .chooser} + toplevel .chooser + wm title .chooser "Select layer" + wm transient .chooser + frame .chooser.t + bind .chooser {set selectedLayer ""} + listbox .chooser.t.l -width 40 -height 10 -yscrollcommand ".chooser.t.y set" -exportselection false + scrollbar .chooser.t.y -orient vert -command ".chooser.t.l yview" + pack .chooser.t.l .chooser.t.y -side left -fill both -expand y + pack .chooser.t -fill both -expand y + frame .chooser.b + bind .chooser.t.l {set selectedLayer [.chooser.t.l index active]} + button .chooser.b.ok -padx 10 -text "Ok" -command {set selectedLayer [.chooser.t.l curselection]} + button .chooser.b.cancel -padx 10 -text "Cancel" -command {set selectedLayer ""} + pack .chooser.b.ok -side left + pack .chooser.b.cancel -side left + pack .chooser.b + set box .chooser.t.l + set current [lindex [$planchet layers] 0] + foreach layer [layer names] { + set n [$box size] + $box insert end [$layer title] + if {"$layer"=="$current"} { + $box selection set $n + } + } + global selectedLayer + vwait selectedLayer + if { $selectedLayer == ""} { + set result "" + } else { + set result [lindex [layer names] $selectedLayer] + } + catch {destroy .chooser} + return $result +} + +proc close_layer {layer} { + global modifiedLayers planchet + if ![string length $layer] return + if [info exist modifiedLayers($layer)] { + switch -exact -- [tk_messageBox -title "Warning" -message\ + "This layer was modified. Save it?" -type yesnocancel] { + yes {save_layer $layer} + no {} + cancel {return} + } + } + + if {[llength [layer names]]==1} { + if {[tk_messageBox -title "Warning" -message "This is a last layer.\ + Closing it would cause mapview to exit. Proceed?"\ + -type yesno]=="no"} return else exit + + } + catch {$planchet look remove $layer} + $layer delete + if ![llength [$planchet layers]] { + show_layer [lindex [layer names] 0] + } +} + +proc save_layer {layer} { +global layerFile layerModified +if ![info exist layerFile($layer)] { + regsub -all "\[\t ]+" [$layer title] "_" filename + set filename [tk_getSaveFile -defaultextension ".lay" -initialfile $filename.lay] + if ![string length $filename] return + set layerFile($layer) $filename +} +if [file exists $layerFile($layer)] { + set bakname "[file rootname $layerFile].bak" + if [file exists $bakname] { + file delete $bakname + } + file rename $layerFile($layer) $bakname +} +set f [open $layerFile($layer) w] +puts $f [$layer dump] +close $f +catch {unset layerModified($layer)} +} + +proc confirmExit {} { + global argv0 + if {[tk_messageBox -title confirm -type yesno -message "Exit $argv0. Are + you sure"]=="yes"} { + destroy . + } +} diff --git a/tcl/widget.tcl b/tcl/widget.tcl new file mode 100644 index 0000000..373e2e7 --- /dev/null +++ b/tcl/widget.tcl @@ -0,0 +1,812 @@ +## +## widget.tcl +## +## Barebones requirements for creating and querying megawidgets +## +## Copyright 1997 Jeffrey Hobbs, CADIX International +## +## Initiated: 5 June 1997 +## Last Update: + +##------------------------------------------------------------------------ +## PROCEDURE +## widget +## +## DESCRIPTION +## Implements and modifies megawidgets +## +## ARGUMENTS +## widget ?? +## +## specifies a global array which is the name of a class and +## contains options database information. +## +## create classname +## creates the widget class $classname based on the specifications +## in the global array of the same name +## +## classes ?pattern? +## returns the classes created with this command. +## +## OPTIONS +## none +## +## RETURNS: the widget class +## +## NAMESPACE & STATE +## The global variable WIDGET is used. The public procedure is +## 'widget', with other private procedures beginning with 'widget'. +## +##------------------------------------------------------------------------ +## +## For a well-commented example for creating a megawidget using this method, +## see the ScrolledText example at the end of the file. +## +## SHORT LIST OF IMPORTANT THINGS TO KNOW: +## +## Specify the "type", "base", & "components" keys of the $CLASS global array +## +## In the $w global array that is created for each instance of a megawidget, +## the following keys are set by the "widget create $CLASS" procedure: +## "base", "basecmd", "container", "class", any option specified in the +## $CLASS array, each component will have a named key +## +## The following public methods are created for you: +## "cget", "configure", "destroy", & "subwidget" +## You need to write the following: +## "$CLASS:construct", "$CLASS:configure" +## You may want the following that will be called when appropriate: +## "$CLASS:init" (after initial configuration) +## "$CLASS:destroy" (called first thing when widget is being destroyed) +## +## All ${CLASS}_* commands are considered public methods. The megawidget +## routine will match your options and methods on a unique substring basis. +## +## END OF SHORT LIST + +package require Tk +package provide Widget 1.12 + +global WIDGET +lappend WIDGET(containers) frame toplevel +proc widget { cmd args } { + switch -glob $cmd { + cr* { return [uplevel widget_create $args] } + cl* { return [uplevel widget_classes $args] } + default { + return -code error "unknown [lindex [info level 0] 0] subcommand\ + \"$cmd\", must be one of: create, classes" + } + } +} + +;proc widget_classes {{pattern "*"}} { + global WIDGET + set classes {} + foreach name [array names WIDGET C:$pattern] { + lappend classes [string range $name 2 end] + } + return $classes +} + +;proc widget:eval {CLASS w subcmd args} { + upvar \#0 $w data + if {[string match {} [set arg [info commands ${CLASS}_$subcmd]]]} { + set arg [info commands ${CLASS}_$subcmd*] + } + set num [llength $arg] + if {$num==1} { + return [uplevel $arg [list $w] $args] + } elseif {$num} { + regsub -all "${CLASS}_" $arg {} arg + return -code error "ambiguous subcommand \"$subcmd\",\ + could be one of: [join $arg {, }]" + } elseif {[catch {uplevel [list $data(basecmd) $subcmd] $args} err]} { + return -code error $err + } else { + return $err + } +} + +;proc widget_create:constructor {CLASS} { + upvar \#0 $CLASS class + global WIDGET + + lappend datacons [list class $CLASS] + set basecons {} + if {[string compare $class(type) [lindex $class(base) 0]]} { + lappend datacons "base \$w.[list [lindex $class(base) 2]]" \ + "basecmd $CLASS\$w.[list [lindex $class(base) 2]]" + set comps "[list $class(base)] $class(components)" + } else { + lappend datacons "base \$w" "basecmd $CLASS\$w" \ + "[lindex $class(base) 1] \$w" + set comps $class(components) + } + foreach comp $comps { + switch [llength $comp] { + 0 continue + 1 { set name [set type [set wid $comp]]; set opts {} } + 2 { + set type [lindex $comp 0] + set name [set wid [lindex $comp 1]] + set opts {} + } + default { + foreach {type name wid opts} $comp break + set opts [string trim $opts] + } + } + lappend datacons "[list $name] \$w.[list $wid]" + lappend basecons "$type \$data($name) $opts" + if {[string match toplevel $type]} { + lappend basecons "wm withdraw \$data($name)" + } + } + set datacons [join $datacons] + set basecons [join $basecons "\n "] + + ## More of this proc could be configured ahead of time for increased + ## construction speed. It's delicate, so handle with extreme care. + ;proc $CLASS {w args} " + upvar \#0 \$w data $CLASS class + $class(type) \$w -class $CLASS + [expr [string match toplevel $class(type)]?{wm withdraw \$w\n}:{}] + ## Populate data array with user definable options + foreach o \[array names class -*\] { + if {\[string match -* \$class(\$o)\]} continue + set data(\$o) \[option get \$w \[lindex \$class(\$o) 0\] $CLASS\] + } + + ## Populate the data array + array set data \[list $datacons\] + ## Create all the base and component widgets + $basecons + + ## Allow for an initialization proc to be eval'ed + ## The user must create one + if {\[catch {$CLASS:construct \$w} err\]} { + catch {${CLASS}_destroy \$w} + return -code error \"megawidget construction error: \$err\" + } + + set base \$data(base) + if {\[string compare \$base \$w\]} { + ## If the base widget is not the container, then we want to rename + ## its widget commands and add the CLASS and container bind tables + ## to its bindtags in case certain bindings are made + rename \$w .\$w + rename \$base \$data(basecmd) + ## Interp alias is the optimal solution, but exposes + ## a bug in Tcl7/8 when renaming aliases + #interp alias {} \$base {} widget:eval $CLASS \$w + ;proc \$base args \"uplevel widget:eval $CLASS \[list \$w\] \\\$args\" + bindtags \$base \[linsert \[bindtags \$base\] 1\ + [expr {[string match toplevel $class(type)]?{}:{$w}}] $CLASS\] + } else { + rename \$w \$data(basecmd) + } + ;proc \$w args \"uplevel widget:eval $CLASS \[list \$w\] \\\$args\" + #interp alias {} \$w {} widget:eval $CLASS \$w + + ## Do the configuring here and eval the post initialization procedure + if {(\[string compare {} \$args\] && \ + \[catch {uplevel 1 ${CLASS}_configure \$w \$args} err\]) || \ + \[catch {$CLASS:init \$w} err\]} { + catch { ${CLASS}_destroy \$w } + return -code error \"megawidget initialization error: \$err\" + } + + return \$w\n" + interp alias {} [string tolower $CLASS] {} $CLASS + + ## These are provided so that errors due to lack of the command + ## existing don't arise. Since they are stubbed out here, the + ## user can't depend on 'unknown' or 'auto_load' to get this proc. + if {[string match {} [info commands $CLASS:construct]]} { + ;proc $CLASS:construct {w} { + # the user should rewrite this + # without the following error, a simple megawidget that was just + # a frame would be created by default + return -code error "user must write their own\ + [lindex [info level 0] 0] function" + } + } + if {[string match {} [info commands $CLASS:init]]} { + ;proc $CLASS:init {w} { + # the user should rewrite this + } + } +} + +;proc widget_create {CLASS} { + if {![string match {[A-Z]*} $CLASS] || [string match { } $CLASS]} { + return -code error "invalid class name \"$CLASS\": it must begin\ + with a capital letter and contain no spaces" + } + + global WIDGET + upvar \#0 $CLASS class + + ## First check to see that their container type is valid + if {[info exists class(type)]} { + ## I'd like to include canvas and text, but they don't accept the + ## -class option yet, which would thus require some voodoo on the + ## part of the constructor to make it think it was the proper class + if {![regexp ^([join $WIDGET(containers) |])\$ $class(type)]} { + return -code error "invalid class container type \"$class(type)\",\ + must be one of: [join $types {, }]" + } + } else { + ## Frame is the default container type + set class(type) frame + } + ## Then check to see that their base widget type is valid + ## We will create a default widget of the appropriate type just in + ## case they use the DEFAULT keyword as a default value in their + ## megawidget class definition + if {[info exists class(base)]} { + ## We check to see that we can create the base, that it returns + ## the same widget value we put in, and that it accepts cget. + if {[string match toplevel [lindex $class(base) 0]] && \ + [string compare toplevel $class(type)]} { + return -code error "\"toplevel\" is not allowed as the base\ + widget of a megawidget (perhaps you intended it to\ + be the class type)" + } + } else { + ## The container is the default base widget + set class(base) $class(type) + } + set types($class(type)) 0 + switch [llength $class(base)] { + 1 { set name [set type [set wid $class(base)]]; set opts {} } + 2 { + set type [lindex $class(base) 0] + set name [set wid [lindex $class(base) 1]] + set opts {} + } + default { foreach {type name wid opts} $class(base) break } + } + set class(base) [list $type $name $wid $opts] + if {[regexp {(^[\.A-Z]|[ \.])} $wid]} { + return -code error "invalid $CLASS class base widget name \"$wid\":\ + it cannot begin with a capital letter,\ + or contain spaces or \".\"" + } + set components(base) [set components($name) $type] + set widgets($wid) 0 + set types($type) 0 + + if {![info exists class(components)]} { set class(components) {} } + set comps $class(components) + set class(components) {} + ## Verify component widget list + foreach comp $comps { + ## We don't care if an opts item exists now + switch [llength $comp] { + 0 continue + 1 { set name [set type [set wid $comp]] } + 2 { + set type [lindex $comp 0] + set name [set wid [lindex $comp 1]] + } + default { foreach {type name wid} $comp break } + } + if {[info exists components($name)]} { + return -code error "component name \"$name\" occurs twice\ + in $CLASS class" + } + if {[info exists widgets($wid)]} { + return -code error "widget name \"$wid\" occurs twice\ + in $CLASS class" + } + if {[regexp {(^[\.A-Z]| |\.$)} $wid]} { + return -code error "invalid $CLASS class component widget\ + name \"$wid\": it cannot begin with a capital letter,\ + contain spaces or start or end with a \".\"" + } + if {[string match *.* $wid] && \ + ![info exists widgets([file root $wid])]} { + ## If the widget name contains a '.', then make sure we will + ## have created all the parents first. [file root $wid] is + ## a cheap trick to remove the last .child string from $wid + return -code error "no specified parent for $CLASS class\ + component widget name \"$wid\"" + } + lappend class(components) $comp + set components($name) $type + set widgets($wid) 0 + set types($type) 0 + } + + ## Go through the megawidget class definition, substituting for ALIAS + ## where necessary and setting up the options database for this $CLASS + foreach o [array names class -*] { + set name [lindex $class($o) 0] + switch -glob -- $name { + -* continue + ALIAS { + set len [llength $class($o)] + if {$len != 3 && $len != 5} { + return -code error "wrong \# args for ALIAS, must be:\ + {ALIAS componenttype option\ + ?databasename databaseclass?}" + } + foreach {name type opt dbname dbcname} $class($o) break + if {![info exists types($type)]} { + return -code error "cannot create alias \"$o\" to $CLASS\ + component type \"$type\" option \"$opt\":\ + component type does not exist" + } elseif {![info exists config($type)]} { + if {[string compare toplevel $type]} { + set w .__widget__$type + catch {destroy $w} + ## Make sure the component widget type exists, + ## returns the widget name, + ## and accepts configure as a subcommand + if {[catch {$type $w} result] || \ + [string compare $result $w] || \ + [catch {$w configure} config($type)]} { + ## Make sure we destroy it if it was a bad widget + catch {destroy $w} + ## Or rename it if it was a non-widget command + catch {rename $w {}} + return -code error "invalid widget type \"$type\"" + } + catch {destroy $w} + } else { + set config($type) [. configure] + } + } + set i [lsearch -glob $config($type) "$opt\[ \t\]*"] + if {$i == -1} { + return -code error "cannot create alias \"$o\" to $CLASS\ + component type \"$type\" option \"$opt\":\ + option does not exist" + } + if {$len==3} { + foreach {opt dbname dbcname def} \ + [lindex $config($type) $i] break + } elseif {$len==5} { + set def [lindex [lindex $config($type) $i] 3] + } + } + default { + if {[string compare {} $class($o)]} { + foreach {dbname dbcname def} $class($o) break + } else { + set dbcname [set dbname [string range $o 1 end]] + set def {} + } + } + } + set class($o) [list $dbname $dbcname $def] + option add *$CLASS.$dbname $def widgetDefault + } + ## Ensure that the class is set correctly + set class(class) $CLASS + + ## This creates the basic constructor procedure for the class + ## Both $CLASS and [string tolower $CLASS] commands will be created + widget_create:constructor $CLASS + + ## The user is not supposed to change this proc + set comps [lsort [array names components]] + ;proc ${CLASS}_subwidget {w widget} " + upvar \#0 \$w data + switch -- \$widget { + [join $comps { - }] { return \$data(\$widget) } + default { + return -code error \"No \$data(class) subwidget \\\"\$widget\\\",\ + must be one of: [join $comps {, }]\" + } + } + " + + ## The [winfo class %W] will work in this Destroy, which is necessary + ## to determine if we are destroying the actual megawidget container. + ## The ${CLASS}_destroy must occur to remove excess state elements. + ## This will break in Tk4.1p1, but work with any other 4.1+ version. + bind $CLASS " + if {\[string compare {} \[widget classes \[winfo class %W\]\]\]} { + catch {\[winfo class %W\]_destroy %W} + } + " + + ## The user is not supposed to change this proc + ## Instead they create a $CLASS:destroy proc + ## Some of this may be redundant, but at least it does the job + ;proc ${CLASS}_destroy {w} " + upvar \#0 \$w data + catch { $CLASS:destroy \$w } + catch { destroy \$data(base) } + catch { destroy \$w } + catch { rename \$data(basecmd) {} } + catch { rename \$data(base) {} } + catch { rename \$w {} } + catch { unset data } + return\n" + + if {[string match {} [info commands $CLASS:destroy]]} { + ## The user can optionally provide a special destroy handler + ;proc $CLASS:destroy {w args} { + # empty + } + } + + ## The user is not supposed to change this proc + ;proc ${CLASS}_cget {w args} { + if {[llength $args] != 1} { + return -code error "wrong \# args: should be \"$w cget option\"" + } + upvar \#0 $w data [winfo class $w] class + if {[info exists class($args)] && [string match -* $class($args)]} { + set args $class($args) + } + if {[string match {} [set arg [array names data $args]]]} { + set arg [array names data ${args}*] + } + set num [llength $arg] + if {$num==1} { + return $data($arg) + } elseif {$num} { + return -code error "ambiguous option \"$args\",\ + must be one of: [join $arg {, }]" + } elseif {[catch {$data(basecmd) cget $args} err]} { + return -code error $err + } else { + return $err + } + } + + ## The user is not supposed to change this proc + ## Instead they create a $CLASS:configure proc + ;proc ${CLASS}_configure {w args} { + upvar \#0 $w data [winfo class $w] class + + set num [llength $args] + if {$num==1} { + if {[info exists class($args)] && \ + [string match -* $class($args)]} { + set args $class($args) + } + if {[string match {} [set arg [array names data $args]]]} { + set arg [array names data ${args}*] + } + set num [llength $arg] + if {$num==1} { + ## FIX one-elem config + return "[list $arg] $class($arg) [list $data($arg)]" + } elseif {$num} { + return -code error "ambiguous option \"$args\",\ + must be one of: [join $arg {, }]" + } elseif {[catch {$data(basecmd) configure $args} err]} { + return -code error $err + } else { + return $err + } + } elseif {$num} { + ## Group the {key val} pairs to be distributed + if {$num&1} { + set last [lindex $args end] + set args [lrange $args 0 [incr num -2]] + } + set widargs {} + set cmdargs {} + foreach {key val} $args { + if {[info exists class($key)] && \ + [string match -* $class($key)]} { + set key $class($key) + } + if {[string match {} [set arg [array names data $key]]]} { + set arg [array names data $key*] + } + set len [llength $arg] + if {$len==1} { + lappend widargs $arg $val + } elseif {$len} { + set ambarg [list $key $arg] + break + } else { + lappend cmdargs $key $val + } + } + if {[string compare {} $widargs]} { + uplevel $class(class):configure [list $w] $widargs + } + if {[string compare {} $cmdargs] && [catch \ + {uplevel [list $data(basecmd)] configure $cmdargs} err]} { + return -code error $err + } + if {[info exists ambarg]} { + return -code error "ambiguous option \"[lindex $ambarg 0]\",\ + must be one of: [join [lindex $ambarg 1] {, }]" + } + if {[info exists last]} { + return -code error "value for \"$last\" missing" + } + } else { + foreach opt [$data(basecmd) configure] { + set options([lindex $opt 0]) [lrange $opt 1 end] + } + foreach opt [array names class -*] { + if {[string match -* $class($opt)]} { + set options($opt) [string range $class($opt) 1 end] + } else { + set options($opt) "$class($opt) [list $data($opt)]" + } + } + foreach opt [lsort [array names options]] { + lappend config "$opt $options($opt)" + } + return $config + } + } + + if {[string match {} [info commands $CLASS:configure]]} { + ## The user is intended to rewrite this one + ;proc $CLASS:configure {w args} { + foreach {key val} $args { + puts "$w: configure $key to [list $value]" + } + } + } + + set WIDGET(C:$CLASS) {} + return $CLASS +} + + +######################################################################## +########################## EXAMPLES #################################### +######################################################################## + +######################################################################## +########################## ScrolledText ################################ +######################################################################## + +##------------------------------------------------------------------------ +## PROCEDURE +## scrolledtext +## +## DESCRIPTION +## Implements a ScrolledText mega-widget +## +## ARGUMENTS +## scrolledtext +## +## OPTIONS +## (Any text widget option may be used in addition to these) +## +## -autoscrollbar TCL_BOOLEAN DEFAULT: 1 +## Whether to have dynamic or static scrollbars. +## +## RETURNS: the window pathname +## +## BINDINGS (in addition to default widget bindings) +## +## SUBCOMMANDS +## These are the subcmds that an instance of this megawidget recognizes. +## Aside from those listed here, it accepts subcmds that are valid for +## text widgets. +## +## configure ?option? ?value option value ...? +## cget option +## Standard tk widget routines. +## +## subwidget widget +## Returns the true widget path of the specified widget. Valid +## widgets are text, xscrollbar, yscrollbar. +## +## NAMESPACE & STATE +## The megawidget creates a global array with the classname, and a +## global array which is the name of each megawidget created. The latter +## array is deleted when the megawidget is destroyed. +## Public procs of $CLASSNAME and [string tolower $CLASSNAME] are used. +## Other procs that begin with $CLASSNAME are private. For each widget, +## commands named .$widgetname and $CLASSNAME$widgetname are created. +## +## EXAMPLE USAGE: +## +## pack [scrolledtext .st -width 40 -height 10] -fill both -exp 1 +## +##------------------------------------------------------------------------ + +## Create a global array with that is the name of the class: ScrolledText +## Each widget created will also have a global array created by the +## instantiation procedure that is the name of the widget (represented +## as $w below). There three special key names in the $CLASS array: +## +## type +## the type of base container we want to use (frame or toplevel). +## This would default to frame. This widget will be created for us +## by the constructor function. The $w array will have a "container" +## key that will point to the exact widget name. +## +## base +## the base widget type for this class. This key is optional and +## represents what kind of widget will be the base for the class. This +## way we know what default methods/options you'll have. If not +## specified, it defaults to the container type. +## To the global $w array, the key "basecmd" will be added by the widget +## instantiation function to point to a new proc that will be the direct +## accessor command for the base widget ("text" in the case of the +## ScrolledText megawidget). The $w "base" key will be the valid widget +## name (for passing to [winfo] and such), but "basecmd" will be the +## valid direct accessor function +## +## components +## the component widgets of the megawidget. This is a list of tuples +## (ie: {{listbox listbox} {scrollbar yscrollbar} {scrollbar xscrollbar}}) +## where each item is in the form {widgettype name}. These components +## will be created before the $CLASS:construct proc is called and the $w +## array will have keys with each name pointing to the appropriate +## widget in it. Use these keys to access your subwidgets. It is from +## this component list and the base and type about that the subwidget +## method is created. +## +## Aside from that, any $CLASS key that matches -* will be considered an +## option that this megawidget handles. The value can either be a +## 3-tuple list of the form {databaseName databaseClass defaultValue}, or +## it can be one element matching -*, which means this key (say -bd) is +## an alias for the option specified in the value (say -borderwidth) +## which must be specified fully somewhere else in the class array. +## +## If the value is a list beginning with "ALIAS", then the option is derived +## from a component of the megawidget. The form of the value must be a list +## with the elements: +## {ALIAS componenttype option ?databasename databaseclass?} +## An example of this would be inheriting a label components anchor: +## {ALIAS label -anchor labelAnchor Anchor} +## If the databasename is not specified, it determines the final options +## database info from the component and uses the components default value. +## Otherwise, just the components default value is used. +## +## The $w array will be populated by the instantiation procedure with the +## default values for all the specified $CLASS options. +## +array set ScrolledText { + type frame + base {text text text \ + {-xscrollcommand [list $data(xscrollbar) set] \ + -yscrollcommand [list $data(yscrollbar) set]}} + components { + {scrollbar xscrollbar sx {-orient h -bd 1 -highlightthickness 1 \ + -command [list $w xview]}} + {scrollbar yscrollbar sy {-orient v -bd 1 -highlightthickness 1 \ + -command [list $w yview]}} + } + + -autoscrollbar {autoScrollbar AutoScrollbar 1} +} + +# Create this to make sure there are registered in auto_mkindex +# these must come before the [widget create ...] +proc ScrolledText args {} +proc scrolledtext args {} +widget create ScrolledText + +## Then we "create" the widget. This makes all the necessary default widget +## routines. It creates the public accessor functions ($CLASSNAME and +## [string tolower $CLASSNAME]) as well as the public cget, configure, destroy +## and subwidget methods. The cget and configure commands work like the +## regular Tk ones. The destroy method is superfluous, as megawidgets will +## respond properly to [destroy $widget] (the Tk destroy command). +## The subwidget method has the following form: +## +## $widget subwidget name +## name - the component widget name +## Returns the widget patch to the component widget name. +## Allows the user direct access to your subwidgets. +## +## THE USER SHOULD PROVIDE AT LEAST THE FOLLOWING: +## +## $CLASSNAME:construct {w} => return value ignored +## w - the widget name, also the name of the global data array +## This procedure is called by the public accessor (instantiation) proc +## right after creating all component widgets and populating the global $w +## array with all the default option values, the "base" key and the key +## names for any other components. The user should then grid/pack all +## subwidgets into $w. At this point, the initial configure has not +## occured, so the widget options are all the default. If this proc +## errors, so does the main creation routine, returning your error. +## +## $CLASSNAME:configure {w args} => return ignored (should be empty) +## w - the widget name, also the name of the global data array +## args - a list of key/vals (already verified to exist) +## The user should process the key/vals however they require If this +## proc errors, so does the main creation routine, returning your error. +## +## THE FOLLOWING IS OPTIONAL: +## +## $CLASSNAME:init {w} => return value ignored +## w - the widget name, also the name of the global data array +## This procedure is called after the public configure routine and after +## the "basecmd" key has been added to the $w array. Ideally, this proc +## would be used to do any widget specific one-time initialization. +## +## $CLASSNAME:destroy {w} => return ignored (should be empty) +## w - the widget name, also the name of the global data array +## A default destroy handler is provided that cleans up after the megawidget +## (all state info), but if special cleanup stuff is needed, you would provide +## it in this procedure. This is the first proc called in the default destroy +## handler. +## + +;proc ScrolledText:construct {w} { + upvar \#0 $w data + + grid $data(text) $data(yscrollbar) -sticky news + grid $data(xscrollbar) -sticky ew + grid columnconfig $w 0 -weight 1 + grid rowconfig $w 0 -weight 1 + grid remove $data(yscrollbar) $data(xscrollbar) + bind $data(text) [list ScrolledText:resize $w 1] +} + +;proc ScrolledText:configure {w args} { + upvar \#0 $w data + set truth {^(1|yes|true|on)$} + foreach {key val} $args { + switch -- $key { + -autoscrollbar { + set data($key) [regexp -nocase $truth $val] + if {$data($key)} { + ScrolledText:resize $w 0 + } else { + grid $data(xscrollbar) + grid $data(yscrollbar) + } + } + } + } +} + +;proc ScrolledText_xview {w args} { + upvar \#0 $w data + if {[catch {uplevel $data(basecmd) xview $args} err]} { + return -code error $err + } +} + +;proc ScrolledText_yview {w args} { + upvar \#0 $w data + if {[catch {uplevel $data(basecmd) yview $args} err]} { + return -code error $err + } elseif {![winfo ismapped $data(xscrollbar)] && \ + [string compare {0 1} [$data(basecmd) xview]]} { + ## If the xscrollbar was unmapped, but is now needed, show it + grid $data(xscrollbar) + } +} + +;proc ScrolledText_insert {w args} { + upvar \#0 $w data + set code [catch {uplevel $data(basecmd) insert $args} err] + if {[winfo ismapped $w]} { ScrolledText:resize $w 0 } + return -code $code $err +} + +;proc ScrolledText_delete {w args} { + upvar \#0 $w data + set code [catch {uplevel $data(basecmd) delete $args} err] + if {[winfo ismapped $w]} { ScrolledText:resize $w 1 } + return -code $code $err +} + +;proc ScrolledText:resize {w d} { + upvar \#0 $w data + ## Only when deleting should we consider removing the scrollbars + if {!$data(-autoscrollbar)} return + if {[string compare {0 1} [$data(basecmd) xview]]} { + grid $data(xscrollbar) + } elseif {$d} { + grid remove $data(xscrollbar) + } + if {[string compare {0 1} [$data(basecmd) yview]]} { + grid $data(yscrollbar) + } elseif {$d} { + grid remove $data(yscrollbar) + } +} diff --git a/testdata/admin.epp b/testdata/admin.epp new file mode 100644 index 0000000000000000000000000000000000000000..f5ae887368d8a843211f6c8b97047e469bd609b7 GIT binary patch literal 45568 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 Z+Og^`escu=a@;W9+G-eI6YCS1{{yDF3_Ab- literal 0 HcmV?d00001 diff --git a/testdata/admin.lay b/testdata/admin.lay new file mode 100644 index 0000000..3d307e9 --- /dev/null +++ b/testdata/admin.lay @@ -0,0 +1,96 @@ +#fGIS Layer file. Layer type: raster +# Layer: áÄÍÉÎÉÓÔÒÁÔÉ×ÎÙÅ ÏÂÌÁÓÔÉ òæ +set _raster_ [raster /home/vitus/fgis/testdata/admin.epp] +set _legend_ [legend parse {-2 áÄÍÉÎÉÓÔÒÁÔÉ×ÎÙÅ ÏÂÌÁÓÔÉ òæ +1 ›òÅÓÐÕÂÌÉËÁ âÁÛËÏÒÔÏÓÔÁÎ +2 ›òÅÓÐÕÂÌÉËÁ âÕÒÑÔÉÑ +3 ›òÅÓÐÕÂÌÉËÁ äÁÇÅÓÔÁÎ +4 ›ëÁÂÁÒÄÉÎÏ-âÁÌËÁÒÓËÁÑ òÅÓÐÕÂÌÉËÁ +5 ›òÅÓÐÕÂÌÉËÁ ëÁÌÍÙËÉÑ-èÁÌØÍÇ ôÁÎÇÞ +6 ›òÅÓÐÕÂÌÉËÁ ëÁÒÅÌÉÑ +7 ›òÅÓÐÕÂÌÉËÁ ëÏÍÉ +8 ›òÅÓÐÕÂÌÉËÁ íÁÒÉÊ üÌ +9 ›íÏÒÄÏ×ÓËÁÑ óóò +10 ›óÅ×ÅÒÏ-ïÓÅÔÉÎÓËÁÑ óóò +11 ›òÅÓÐÕÂÌÉËÁ ôÁÔÁÒÓÔÁÎ +12 ›òÅÓÐÕÂÌÉËÁ ôÕ×Á +13 ›õÄÍÕÒÔÓËÁÑ òÅÓÐÕÂÌÉËÁ +14 ›þÅÞÅÎÓËÁÑ É éÎÇÕÛÓËÁÑ ÒÅÓÐÕÂÌÉËÉ +15 ›þÕ×ÁÛÓËÁÑ òÅÓÐÕÂÌÉËÁ +16 ›òÅÓÐÕÂÌÉËÁ óÁÈÁ (ñËÕÔÉÑ) +17 ›áÌÔÁÊÓËÉÊ ËÒÁÊ +18 ›òÅÓÐÕÂÌÉËÁ áÌÔÁÊ +19 ›ëÒÁÓÎÏÄÁÒÓËÉÊ ËÒÁÊ +20 ›òÅÓÐÕÂÌÉËÁ áÄÙÇÅÑ +21 ›ëÒÁÓÎÏÑÒÓËÉÊ ËÒÁÊ +22 ›òÅÓÐÕÂÌÉËÁ èÁËÁÓÓÉÑ +23 ›ôÁÊÍÙÒÓËÉÊ Á×Ô.ÏËÒÕÇ +24 ›ü×ÅÎËÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ +25 ›ðÒÉÍÏÒÓËÉÊ ËÒÁÊ +26 ›óÔÁ×ÒÏÐÏÌØÓËÉÊ ËÒÁÊ +27 ›ëÁÒÁÞÁÅ×Ï-þÅÒËÅÓÓËÁÑ òÅÓÐÕÂÌÉËÁ +28 ›èÁÂÁÒÏ×ÓËÉÊ ËÒÁÊ +29 ›å×ÒÅÊÓËÁÑ Á×Ô.ÏÂÌÁÓÔØ +30 ›áÍÕÒÓËÁÑ +31 ›áÒÈÁÎÇÅÌØÓËÁÑ +32 ›îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ +33 ›áÓÔÒÁÈÁÎÓËÁÑ +34 ›âÅÌÇÏÒÏÄÓËÁÑ +35 ›âÒÑÎÓËÁÑ +36 ›÷ÌÁÄÉÍÉÒÓËÁÑ +37 ›÷ÏÌÇÏÇÒÁÄÓËÁÑ +38 ›÷ÏÌÏÇÏÄÓËÁÑ +39 ›÷ÏÒÏÎÅÖÓËÁÑ +40 ›îÉÖÅÇÏÒÏÄÓËÁÑ +41 ›é×ÁÎÏ×ÓËÁÑ +42 ›éÒËÕÔÓËÁÑ +43 ›õÓÔØ-ïÒÄÙÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒ +44 ›ëÁÌÉÎÉÎÇÒÁÄÓËÁÑ +45 ›ô×ÅÒÓËÁÑ +46 ›ëÁÌÕÖÓËÁÑ +47 ›ëÁÍÞÁÔÓËÁÑ +48 ›ëÏÒÑËÓËÉÊ Á×Ô.ÏËÒÕÇ +49 ›ëÅÍÅÒÏ×ÓËÁÑ +50 ›ëÉÒÏ×ÓËÁÑ +51 ›ëÏÓÔÒÏÍÓËÁÑ +52 ›óÁÍÁÒÓËÁÑ +53 ›ëÕÒÇÁÎÓËÁÑ +54 ›ëÕÒÓËÁÑ +55 ›ìÅÎÉÎÇÒÁÄÓËÁÑ +56 ›ìÉÐÅÃËÁÑ +57 ›íÁÇÁÄÁÎÓËÁÑ +58 ›þÕËÏÔÓËÉÊ Á×Ô.ÏËÒÕÇ +59 ›íÏÓËÏ×ÓËÁÑ +60 ›íÕÒÍÁÎÓËÁÑ +61 ›îÏ×ÇÏÒÏÄÓËÁÑ +62 ›îÏ×ÏÓÉÂÉÒÓËÁÑ +63 ›ïÍÓËÁÑ +64 ›ïÒÅÎÂÕÒÇÓËÁÑ +65 ›ïÒÌÏ×ÓËÁÑ +66 ›ðÅÎÚÅÎÓËÁÑ +67 ›ðÅÒÍÓËÁÑ +68 ›ëÏÍÉ-ðÅÒÍÑÃËÉÊ Á×Ô.ÏËÒÕÇ +69 ›ðÓËÏ×ÓËÁÑ +70 ›òÏÓÔÏ×ÓËÁÑ +71 ›òÑÚÁÎÓËÁÑ +72 ›óÁÒÁÔÏ×ÓËÁÑ +73 ›óÁÈÁÌÉÎÓËÁÑ +74 ›åËÁÔÅÒÉÎÂÕÒÇÓËÁÑ +75 ›óÍÏÌÅÎÓËÁÑ +76 ›ôÁÍÂÏ×ÓËÁÑ +77 ›ôÏÍÓËÁÑ +78 ›ôÕÌØÓËÁÑ +79 ›ôÀÍÅÎÓËÁÑ +80 ›èÁÎÔÙ-íÁÎÓÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ +81 ›ñÍÁÌÏ-îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ +82 ›õÌØÑÎÏ×ÓËÁÑ +83 ›þÅÌÑÂÉÎÓËÁÑ +84 ›þÉÔÉÎÓËÁÑ +85 ›áÇÉÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒÕÇ +86 ›ñÒÏÓÌÁ×ÓËÁÑ +}] +layer create raster -raster $_raster_\ + -border none -ovrborder yes -ovrcolor black\ + -title { áÄÍÉÎÉÓÔÒÁÔÉ×ÎÙÅ ÏÂÌÁÓÔÉ òæ}\ + -legend $_legend_ + diff --git a/testdata/admin.leg b/testdata/admin.leg new file mode 100644 index 0000000..c7afc12 --- /dev/null +++ b/testdata/admin.leg @@ -0,0 +1,87 @@ +-2 áÄÍÉÎÉÓÔÒÁÔÉ×ÎÙÅ ÏÂÌÁÓÔÉ òæ +85 áÇÉÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒÕÇ +17 áÌÔÁÊÓËÉÊ ËÒÁÊ +30 áÍÕÒÓËÁÑ +31 áÒÈÁÎÇÅÌØÓËÁÑ +33 áÓÔÒÁÈÁÎÓËÁÑ +34 âÅÌÇÏÒÏÄÓËÁÑ +35 âÒÑÎÓËÁÑ +36 ÷ÌÁÄÉÍÉÒÓËÁÑ +37 ÷ÏÌÇÏÇÒÁÄÓËÁÑ +38 ÷ÏÌÏÇÏÄÓËÁÑ +39 ÷ÏÒÏÎÅÖÓËÁÑ +29 å×ÒÅÊÓËÁÑ Á×Ô.ÏÂÌÁÓÔØ +74 åËÁÔÅÒÉÎÂÕÒÇÓËÁÑ +41 é×ÁÎÏ×ÓËÁÑ +42 éÒËÕÔÓËÁÑ + 4 ëÁÂÁÒÄÉÎÏ-âÁÌËÁÒÓËÁÑ òÅÓÐÕÂÌÉËÁ +44 ëÁÌÉÎÉÎÇÒÁÄÓËÁÑ +46 ëÁÌÕÖÓËÁÑ +47 ëÁÍÞÁÔÓËÁÑ +27 ëÁÒÁÞÁÅ×Ï-þÅÒËÅÓÓËÁÑ òÅÓÐÕÂÌÉËÁ +49 ëÅÍÅÒÏ×ÓËÁÑ +50 ëÉÒÏ×ÓËÁÑ +68 ëÏÍÉ-ðÅÒÍÑÃËÉÊ Á×Ô.ÏËÒÕÇ +48 ëÏÒÑËÓËÉÊ Á×Ô.ÏËÒÕÇ +51 ëÏÓÔÒÏÍÓËÁÑ +19 ëÒÁÓÎÏÄÁÒÓËÉÊ ËÒÁÊ +21 ëÒÁÓÎÏÑÒÓËÉÊ ËÒÁÊ +53 ëÕÒÇÁÎÓËÁÑ +54 ëÕÒÓËÁÑ +55 ìÅÎÉÎÇÒÁÄÓËÁÑ +56 ìÉÐÅÃËÁÑ +57 íÁÇÁÄÁÎÓËÁÑ + 9 íÏÒÄÏ×ÓËÁÑ óóò +59 íÏÓËÏ×ÓËÁÑ +60 íÕÒÍÁÎÓËÁÑ +32 îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ +40 îÉÖÅÇÏÒÏÄÓËÁÑ +61 îÏ×ÇÏÒÏÄÓËÁÑ +62 îÏ×ÏÓÉÂÉÒÓËÁÑ +63 ïÍÓËÁÑ +64 ïÒÅÎÂÕÒÇÓËÁÑ +65 ïÒÌÏ×ÓËÁÑ +66 ðÅÎÚÅÎÓËÁÑ +67 ðÅÒÍÓËÁÑ +25 ðÒÉÍÏÒÓËÉÊ ËÒÁÊ +69 ðÓËÏ×ÓËÁÑ +20 òÅÓÐÕÂÌÉËÁ áÄÙÇÅÑ +18 òÅÓÐÕÂÌÉËÁ áÌÔÁÊ + 1 òÅÓÐÕÂÌÉËÁ âÁÛËÏÒÔÏÓÔÁÎ + 2 òÅÓÐÕÂÌÉËÁ âÕÒÑÔÉÑ + 3 òÅÓÐÕÂÌÉËÁ äÁÇÅÓÔÁÎ + 5 òÅÓÐÕÂÌÉËÁ ëÁÌÍÙËÉÑ-èÁÌØÍÇ ôÁÎÇÞ + 6 òÅÓÐÕÂÌÉËÁ ëÁÒÅÌÉÑ + 7 òÅÓÐÕÂÌÉËÁ ëÏÍÉ + 8 òÅÓÐÕÂÌÉËÁ íÁÒÉÊ üÌ +16 òÅÓÐÕÂÌÉËÁ óÁÈÁ (ñËÕÔÉÑ) +11 òÅÓÐÕÂÌÉËÁ ôÁÔÁÒÓÔÁÎ +12 òÅÓÐÕÂÌÉËÁ ôÕ×Á +22 òÅÓÐÕÂÌÉËÁ èÁËÁÓÓÉÑ +70 òÏÓÔÏ×ÓËÁÑ +71 òÑÚÁÎÓËÁÑ +52 óÁÍÁÒÓËÁÑ +72 óÁÒÁÔÏ×ÓËÁÑ +73 óÁÈÁÌÉÎÓËÁÑ +10 óÅ×ÅÒÏ-ïÓÅÔÉÎÓËÁÑ óóò +75 óÍÏÌÅÎÓËÁÑ +26 óÔÁ×ÒÏÐÏÌØÓËÉÊ ËÒÁÊ +23 ôÁÊÍÙÒÓËÉÊ Á×Ô.ÏËÒÕÇ +76 ôÁÍÂÏ×ÓËÁÑ +45 ô×ÅÒÓËÁÑ +77 ôÏÍÓËÁÑ +78 ôÕÌØÓËÁÑ +79 ôÀÍÅÎÓËÁÑ +13 õÄÍÕÒÔÓËÁÑ òÅÓÐÕÂÌÉËÁ +82 õÌØÑÎÏ×ÓËÁÑ +43 õÓÔØ-ïÒÄÙÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒ +28 èÁÂÁÒÏ×ÓËÉÊ ËÒÁÊ +80 èÁÎÔÙ-íÁÎÓÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ +83 þÅÌÑÂÉÎÓËÁÑ +14 þÅÞÅÎÓËÁÑ É éÎÇÕÛÓËÁÑ ÒÅÓÐÕÂÌÉËÉ +84 þÉÔÉÎÓËÁÑ +15 þÕ×ÁÛÓËÁÑ òÅÓÐÕÂÌÉËÁ +58 þÕËÏÔÓËÉÊ Á×Ô.ÏËÒÕÇ +24 ü×ÅÎËÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ +81 ñÍÁÌÏ-îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ +86 ñÒÏÓÌÁ×ÓËÁÑ diff --git a/testdata/admin_html.leg b/testdata/admin_html.leg new file mode 100644 index 0000000..828c43f --- /dev/null +++ b/testdata/admin_html.leg @@ -0,0 +1,86 @@ +85 html/85.html +17 html/17.html +30 html/30.html +31 html/31.html +33 html/33.html +34 html/34.html +35 html/35.html +36 html/36.html +37 html/37.html +38 html/38.html +39 html/39.html +29 html/29.html +74 html/74.html +41 html/41.html +42 html/42.html +4 html/4.html +44 html/44.html +46 html/46.html +47 html/47.html +27 html/27.html +49 html/49.html +50 html/50.html +68 html/68.html +48 html/48.html +51 html/51.html +19 html/19.html +21 html/21.html +53 html/53.html +54 html/54.html +55 html/55.html +56 html/56.html +57 html/57.html +9 html/9.html +59 html/59.html +60 html/60.html +32 html/32.html +40 html/40.html +61 html/61.html +62 html/62.html +63 html/63.html +64 html/64.html +65 html/65.html +66 html/66.html +67 html/67.html +25 html/25.html +69 html/69.html +20 html/20.html +18 html/18.html +1 html/1.html +2 html/2.html +3 html/3.html +5 html/5.html +6 html/6.html +7 html/7.html +8 html/8.html +16 html/16.html +11 html/11.html +12 html/12.html +22 html/22.html +70 html/70.html +71 html/71.html +52 html/52.html +72 html/72.html +73 html/73.html +10 html/10.html +75 html/75.html +26 html/26.html +23 html/23.html +76 html/76.html +45 html/45.html +77 html/77.html +78 html/78.html +79 html/79.html +13 html/13.html +82 html/82.html +43 html/43.html +28 html/28.html +80 html/80.html +83 html/83.html +14 html/14.html +84 html/84.html +15 html/15.html +58 html/58.html +24 html/24.html +81 html/81.html +86 html/86.html diff --git a/testdata/html/1.html b/testdata/html/1.html new file mode 100644 index 0000000..8b850b5 --- /dev/null +++ b/testdata/html/1.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ âÁÛËÏÒÔÏÓÔÁÎ + + +

    òÅÓÐÕÂÌÉËÁ âÁÛËÏÒÔÏÓÔÁÎ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ âÁÛËÏÒÔÏÓÔÁÎ" + + diff --git a/testdata/html/10.html b/testdata/html/10.html new file mode 100644 index 0000000..cbd0a53 --- /dev/null +++ b/testdata/html/10.html @@ -0,0 +1,10 @@ + + +óÅ×ÅÒÏ-ïÓÅÔÉÎÓËÁÑ óóò + + +

    óÅ×ÅÒÏ-ïÓÅÔÉÎÓËÁÑ óóò

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "óÅ×ÅÒÏ-ïÓÅÔÉÎÓËÁÑ óóò" + + diff --git a/testdata/html/11.html b/testdata/html/11.html new file mode 100644 index 0000000..220f2df --- /dev/null +++ b/testdata/html/11.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ ôÁÔÁÒÓÔÁÎ + + +

    òÅÓÐÕÂÌÉËÁ ôÁÔÁÒÓÔÁÎ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ ôÁÔÁÒÓÔÁÎ" + + diff --git a/testdata/html/12.html b/testdata/html/12.html new file mode 100644 index 0000000..62f0f86 --- /dev/null +++ b/testdata/html/12.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ ôÕ×Á + + +

    òÅÓÐÕÂÌÉËÁ ôÕ×Á

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ ôÕ×Á" + + diff --git a/testdata/html/13.html b/testdata/html/13.html new file mode 100644 index 0000000..9822ac2 --- /dev/null +++ b/testdata/html/13.html @@ -0,0 +1,10 @@ + + +õÄÍÕÒÔÓËÁÑ òÅÓÐÕÂÌÉËÁ + + +

    õÄÍÕÒÔÓËÁÑ òÅÓÐÕÂÌÉËÁ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "õÄÍÕÒÔÓËÁÑ òÅÓÐÕÂÌÉËÁ" + + diff --git a/testdata/html/14.html b/testdata/html/14.html new file mode 100644 index 0000000..f82108d --- /dev/null +++ b/testdata/html/14.html @@ -0,0 +1,10 @@ + + +þÅÞÅÎÓËÁÑ É éÎÇÕÛÓËÁÑ ÒÅÓÐÕÂÌÉËÉ + + +

    þÅÞÅÎÓËÁÑ É éÎÇÕÛÓËÁÑ ÒÅÓÐÕÂÌÉËÉ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "þÅÞÅÎÓËÁÑ É éÎÇÕÛÓËÁÑ ÒÅÓÐÕÂÌÉËÉ" + + diff --git a/testdata/html/15.html b/testdata/html/15.html new file mode 100644 index 0000000..e9efbb2 --- /dev/null +++ b/testdata/html/15.html @@ -0,0 +1,10 @@ + + +þÕ×ÁÛÓËÁÑ òÅÓÐÕÂÌÉËÁ + + +

    þÕ×ÁÛÓËÁÑ òÅÓÐÕÂÌÉËÁ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "þÕ×ÁÛÓËÁÑ òÅÓÐÕÂÌÉËÁ" + + diff --git a/testdata/html/16.html b/testdata/html/16.html new file mode 100644 index 0000000..666062e --- /dev/null +++ b/testdata/html/16.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ óÁÈÁ (ñËÕÔÉÑ) + + +

    òÅÓÐÕÂÌÉËÁ óÁÈÁ (ñËÕÔÉÑ)

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ óÁÈÁ (ñËÕÔÉÑ)" + + diff --git a/testdata/html/17.html b/testdata/html/17.html new file mode 100644 index 0000000..e939224 --- /dev/null +++ b/testdata/html/17.html @@ -0,0 +1,10 @@ + + +áÌÔÁÊÓËÉÊ ËÒÁÊ + + +

    áÌÔÁÊÓËÉÊ ËÒÁÊ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "áÌÔÁÊÓËÉÊ ËÒÁÊ" + + diff --git a/testdata/html/18.html b/testdata/html/18.html new file mode 100644 index 0000000..81b98f9 --- /dev/null +++ b/testdata/html/18.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ áÌÔÁÊ + + +

    òÅÓÐÕÂÌÉËÁ áÌÔÁÊ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ áÌÔÁÊ" + + diff --git a/testdata/html/19.html b/testdata/html/19.html new file mode 100644 index 0000000..4797b9e --- /dev/null +++ b/testdata/html/19.html @@ -0,0 +1,10 @@ + + +ëÒÁÓÎÏÄÁÒÓËÉÊ ËÒÁÊ + + +

    ëÒÁÓÎÏÄÁÒÓËÉÊ ËÒÁÊ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÒÁÓÎÏÄÁÒÓËÉÊ ËÒÁÊ" + + diff --git a/testdata/html/2.html b/testdata/html/2.html new file mode 100644 index 0000000..23f2cba --- /dev/null +++ b/testdata/html/2.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ âÕÒÑÔÉÑ + + +

    òÅÓÐÕÂÌÉËÁ âÕÒÑÔÉÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ âÕÒÑÔÉÑ" + + diff --git a/testdata/html/20.html b/testdata/html/20.html new file mode 100644 index 0000000..2d6dcc4 --- /dev/null +++ b/testdata/html/20.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ áÄÙÇÅÑ + + +

    òÅÓÐÕÂÌÉËÁ áÄÙÇÅÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ áÄÙÇÅÑ" + + diff --git a/testdata/html/21.html b/testdata/html/21.html new file mode 100644 index 0000000..b154a5b --- /dev/null +++ b/testdata/html/21.html @@ -0,0 +1,10 @@ + + +ëÒÁÓÎÏÑÒÓËÉÊ ËÒÁÊ + + +

    ëÒÁÓÎÏÑÒÓËÉÊ ËÒÁÊ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÒÁÓÎÏÑÒÓËÉÊ ËÒÁÊ" + + diff --git a/testdata/html/22.html b/testdata/html/22.html new file mode 100644 index 0000000..d4157de --- /dev/null +++ b/testdata/html/22.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ èÁËÁÓÓÉÑ + + +

    òÅÓÐÕÂÌÉËÁ èÁËÁÓÓÉÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ èÁËÁÓÓÉÑ" + + diff --git a/testdata/html/23.html b/testdata/html/23.html new file mode 100644 index 0000000..5237030 --- /dev/null +++ b/testdata/html/23.html @@ -0,0 +1,10 @@ + + +ôÁÊÍÙÒÓËÉÊ Á×Ô.ÏËÒÕÇ + + +

    ôÁÊÍÙÒÓËÉÊ Á×Ô.ÏËÒÕÇ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ôÁÊÍÙÒÓËÉÊ Á×Ô.ÏËÒÕÇ" + + diff --git a/testdata/html/24.html b/testdata/html/24.html new file mode 100644 index 0000000..e3f2f24 --- /dev/null +++ b/testdata/html/24.html @@ -0,0 +1,10 @@ + + +ü×ÅÎËÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ + + +

    ü×ÅÎËÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ü×ÅÎËÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ" + + diff --git a/testdata/html/25.html b/testdata/html/25.html new file mode 100644 index 0000000..049d392 --- /dev/null +++ b/testdata/html/25.html @@ -0,0 +1,10 @@ + + +ðÒÉÍÏÒÓËÉÊ ËÒÁÊ + + +

    ðÒÉÍÏÒÓËÉÊ ËÒÁÊ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ðÒÉÍÏÒÓËÉÊ ËÒÁÊ" + + diff --git a/testdata/html/26.html b/testdata/html/26.html new file mode 100644 index 0000000..e84bfb2 --- /dev/null +++ b/testdata/html/26.html @@ -0,0 +1,10 @@ + + +óÔÁ×ÒÏÐÏÌØÓËÉÊ ËÒÁÊ + + +

    óÔÁ×ÒÏÐÏÌØÓËÉÊ ËÒÁÊ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "óÔÁ×ÒÏÐÏÌØÓËÉÊ ËÒÁÊ" + + diff --git a/testdata/html/27.html b/testdata/html/27.html new file mode 100644 index 0000000..d70047a --- /dev/null +++ b/testdata/html/27.html @@ -0,0 +1,10 @@ + + +ëÁÒÁÞÁÅ×Ï-þÅÒËÅÓÓËÁÑ òÅÓÐÕÂÌÉËÁ + + +

    ëÁÒÁÞÁÅ×Ï-þÅÒËÅÓÓËÁÑ òÅÓÐÕÂÌÉËÁ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÁÒÁÞÁÅ×Ï-þÅÒËÅÓÓËÁÑ òÅÓÐÕÂÌÉËÁ" + + diff --git a/testdata/html/28.html b/testdata/html/28.html new file mode 100644 index 0000000..724ebdc --- /dev/null +++ b/testdata/html/28.html @@ -0,0 +1,10 @@ + + +èÁÂÁÒÏ×ÓËÉÊ ËÒÁÊ + + +

    èÁÂÁÒÏ×ÓËÉÊ ËÒÁÊ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "èÁÂÁÒÏ×ÓËÉÊ ËÒÁÊ" + + diff --git a/testdata/html/29.html b/testdata/html/29.html new file mode 100644 index 0000000..63fe5e8 --- /dev/null +++ b/testdata/html/29.html @@ -0,0 +1,10 @@ + + +å×ÒÅÊÓËÁÑ Á×Ô.ÏÂÌÁÓÔØ + + +

    å×ÒÅÊÓËÁÑ Á×Ô.ÏÂÌÁÓÔØ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "å×ÒÅÊÓËÁÑ Á×Ô.ÏÂÌÁÓÔØ" + + diff --git a/testdata/html/3.html b/testdata/html/3.html new file mode 100644 index 0000000..8663731 --- /dev/null +++ b/testdata/html/3.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ äÁÇÅÓÔÁÎ + + +

    òÅÓÐÕÂÌÉËÁ äÁÇÅÓÔÁÎ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ äÁÇÅÓÔÁÎ" + + diff --git a/testdata/html/30.html b/testdata/html/30.html new file mode 100644 index 0000000..056e6ad --- /dev/null +++ b/testdata/html/30.html @@ -0,0 +1,10 @@ + + +áÍÕÒÓËÁÑ + + +

    áÍÕÒÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "áÍÕÒÓËÁÑ" + + diff --git a/testdata/html/31.html b/testdata/html/31.html new file mode 100644 index 0000000..2c74696 --- /dev/null +++ b/testdata/html/31.html @@ -0,0 +1,10 @@ + + +áÒÈÁÎÇÅÌØÓËÁÑ + + +

    áÒÈÁÎÇÅÌØÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "áÒÈÁÎÇÅÌØÓËÁÑ" + + diff --git a/testdata/html/32.html b/testdata/html/32.html new file mode 100644 index 0000000..7d9547e --- /dev/null +++ b/testdata/html/32.html @@ -0,0 +1,10 @@ + + +îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ + + +

    îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ" + + diff --git a/testdata/html/33.html b/testdata/html/33.html new file mode 100644 index 0000000..0b0c3e6 --- /dev/null +++ b/testdata/html/33.html @@ -0,0 +1,10 @@ + + +áÓÔÒÁÈÁÎÓËÁÑ + + +

    áÓÔÒÁÈÁÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "áÓÔÒÁÈÁÎÓËÁÑ" + + diff --git a/testdata/html/34.html b/testdata/html/34.html new file mode 100644 index 0000000..1303828 --- /dev/null +++ b/testdata/html/34.html @@ -0,0 +1,10 @@ + + +âÅÌÇÏÒÏÄÓËÁÑ + + +

    âÅÌÇÏÒÏÄÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "âÅÌÇÏÒÏÄÓËÁÑ" + + diff --git a/testdata/html/35.html b/testdata/html/35.html new file mode 100644 index 0000000..3e823f9 --- /dev/null +++ b/testdata/html/35.html @@ -0,0 +1,10 @@ + + +âÒÑÎÓËÁÑ + + +

    âÒÑÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "âÒÑÎÓËÁÑ" + + diff --git a/testdata/html/36.html b/testdata/html/36.html new file mode 100644 index 0000000..48f74cb --- /dev/null +++ b/testdata/html/36.html @@ -0,0 +1,10 @@ + + +÷ÌÁÄÉÍÉÒÓËÁÑ + + +

    ÷ÌÁÄÉÍÉÒÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "÷ÌÁÄÉÍÉÒÓËÁÑ" + + diff --git a/testdata/html/37.html b/testdata/html/37.html new file mode 100644 index 0000000..c4d42ae --- /dev/null +++ b/testdata/html/37.html @@ -0,0 +1,10 @@ + + +÷ÏÌÇÏÇÒÁÄÓËÁÑ + + +

    ÷ÏÌÇÏÇÒÁÄÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "÷ÏÌÇÏÇÒÁÄÓËÁÑ" + + diff --git a/testdata/html/38.html b/testdata/html/38.html new file mode 100644 index 0000000..6f6bd39 --- /dev/null +++ b/testdata/html/38.html @@ -0,0 +1,10 @@ + + +÷ÏÌÏÇÏÄÓËÁÑ + + +

    ÷ÏÌÏÇÏÄÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "÷ÏÌÏÇÏÄÓËÁÑ" + + diff --git a/testdata/html/39.html b/testdata/html/39.html new file mode 100644 index 0000000..3b2909a --- /dev/null +++ b/testdata/html/39.html @@ -0,0 +1,10 @@ + + +÷ÏÒÏÎÅÖÓËÁÑ + + +

    ÷ÏÒÏÎÅÖÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "÷ÏÒÏÎÅÖÓËÁÑ" + + diff --git a/testdata/html/4.html b/testdata/html/4.html new file mode 100644 index 0000000..1bf78f5 --- /dev/null +++ b/testdata/html/4.html @@ -0,0 +1,10 @@ + + +ëÁÂÁÒÄÉÎÏ-âÁÌËÁÒÓËÁÑ òÅÓÐÕÂÌÉËÁ + + +

    ëÁÂÁÒÄÉÎÏ-âÁÌËÁÒÓËÁÑ òÅÓÐÕÂÌÉËÁ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÁÂÁÒÄÉÎÏ-âÁÌËÁÒÓËÁÑ òÅÓÐÕÂÌÉËÁ" + + diff --git a/testdata/html/40.html b/testdata/html/40.html new file mode 100644 index 0000000..50f8574 --- /dev/null +++ b/testdata/html/40.html @@ -0,0 +1,10 @@ + + +îÉÖÅÇÏÒÏÄÓËÁÑ + + +

    îÉÖÅÇÏÒÏÄÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "îÉÖÅÇÏÒÏÄÓËÁÑ" + + diff --git a/testdata/html/41.html b/testdata/html/41.html new file mode 100644 index 0000000..fd9dae2 --- /dev/null +++ b/testdata/html/41.html @@ -0,0 +1,10 @@ + + +é×ÁÎÏ×ÓËÁÑ + + +

    é×ÁÎÏ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "é×ÁÎÏ×ÓËÁÑ" + + diff --git a/testdata/html/42.html b/testdata/html/42.html new file mode 100644 index 0000000..12a4903 --- /dev/null +++ b/testdata/html/42.html @@ -0,0 +1,10 @@ + + +éÒËÕÔÓËÁÑ + + +

    éÒËÕÔÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "éÒËÕÔÓËÁÑ" + + diff --git a/testdata/html/43.html b/testdata/html/43.html new file mode 100644 index 0000000..a9568c6 --- /dev/null +++ b/testdata/html/43.html @@ -0,0 +1,10 @@ + + +õÓÔØ-ïÒÄÙÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒ + + +

    õÓÔØ-ïÒÄÙÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "õÓÔØ-ïÒÄÙÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒ" + + diff --git a/testdata/html/44.html b/testdata/html/44.html new file mode 100644 index 0000000..042cb89 --- /dev/null +++ b/testdata/html/44.html @@ -0,0 +1,10 @@ + + +ëÁÌÉÎÉÎÇÒÁÄÓËÁÑ + + +

    ëÁÌÉÎÉÎÇÒÁÄÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÁÌÉÎÉÎÇÒÁÄÓËÁÑ" + + diff --git a/testdata/html/45.html b/testdata/html/45.html new file mode 100644 index 0000000..9737d69 --- /dev/null +++ b/testdata/html/45.html @@ -0,0 +1,10 @@ + + +ô×ÅÒÓËÁÑ + + +

    ô×ÅÒÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ô×ÅÒÓËÁÑ" + + diff --git a/testdata/html/46.html b/testdata/html/46.html new file mode 100644 index 0000000..9f86d26 --- /dev/null +++ b/testdata/html/46.html @@ -0,0 +1,10 @@ + + +ëÁÌÕÖÓËÁÑ + + +

    ëÁÌÕÖÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÁÌÕÖÓËÁÑ" + + diff --git a/testdata/html/47.html b/testdata/html/47.html new file mode 100644 index 0000000..8abddce --- /dev/null +++ b/testdata/html/47.html @@ -0,0 +1,10 @@ + + +ëÁÍÞÁÔÓËÁÑ + + +

    ëÁÍÞÁÔÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÁÍÞÁÔÓËÁÑ" + + diff --git a/testdata/html/48.html b/testdata/html/48.html new file mode 100644 index 0000000..6f6b515 --- /dev/null +++ b/testdata/html/48.html @@ -0,0 +1,10 @@ + + +ëÏÒÑËÓËÉÊ Á×Ô.ÏËÒÕÇ + + +

    ëÏÒÑËÓËÉÊ Á×Ô.ÏËÒÕÇ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÏÒÑËÓËÉÊ Á×Ô.ÏËÒÕÇ" + + diff --git a/testdata/html/49.html b/testdata/html/49.html new file mode 100644 index 0000000..0792c69 --- /dev/null +++ b/testdata/html/49.html @@ -0,0 +1,10 @@ + + +ëÅÍÅÒÏ×ÓËÁÑ + + +

    ëÅÍÅÒÏ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÅÍÅÒÏ×ÓËÁÑ" + + diff --git a/testdata/html/5.html b/testdata/html/5.html new file mode 100644 index 0000000..53e2dab --- /dev/null +++ b/testdata/html/5.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ ëÁÌÍÙËÉÑ-èÁÌØÍÇ ôÁÎÇÞ + + +

    òÅÓÐÕÂÌÉËÁ ëÁÌÍÙËÉÑ-èÁÌØÍÇ ôÁÎÇÞ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ ëÁÌÍÙËÉÑ-èÁÌØÍÇ ôÁÎÇÞ" + + diff --git a/testdata/html/50.html b/testdata/html/50.html new file mode 100644 index 0000000..8254bd4 --- /dev/null +++ b/testdata/html/50.html @@ -0,0 +1,10 @@ + + +ëÉÒÏ×ÓËÁÑ + + +

    ëÉÒÏ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÉÒÏ×ÓËÁÑ" + + diff --git a/testdata/html/51.html b/testdata/html/51.html new file mode 100644 index 0000000..1cddf65 --- /dev/null +++ b/testdata/html/51.html @@ -0,0 +1,10 @@ + + +ëÏÓÔÒÏÍÓËÁÑ + + +

    ëÏÓÔÒÏÍÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÏÓÔÒÏÍÓËÁÑ" + + diff --git a/testdata/html/52.html b/testdata/html/52.html new file mode 100644 index 0000000..8ccddfe --- /dev/null +++ b/testdata/html/52.html @@ -0,0 +1,10 @@ + + +óÁÍÁÒÓËÁÑ + + +

    óÁÍÁÒÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "óÁÍÁÒÓËÁÑ" + + diff --git a/testdata/html/53.html b/testdata/html/53.html new file mode 100644 index 0000000..3a929ad --- /dev/null +++ b/testdata/html/53.html @@ -0,0 +1,10 @@ + + +ëÕÒÇÁÎÓËÁÑ + + +

    ëÕÒÇÁÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÕÒÇÁÎÓËÁÑ" + + diff --git a/testdata/html/54.html b/testdata/html/54.html new file mode 100644 index 0000000..a5286ea --- /dev/null +++ b/testdata/html/54.html @@ -0,0 +1,10 @@ + + +ëÕÒÓËÁÑ + + +

    ëÕÒÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÕÒÓËÁÑ" + + diff --git a/testdata/html/55.html b/testdata/html/55.html new file mode 100644 index 0000000..825b3d0 --- /dev/null +++ b/testdata/html/55.html @@ -0,0 +1,10 @@ + + +ìÅÎÉÎÇÒÁÄÓËÁÑ + + +

    ìÅÎÉÎÇÒÁÄÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ìÅÎÉÎÇÒÁÄÓËÁÑ" + + diff --git a/testdata/html/56.html b/testdata/html/56.html new file mode 100644 index 0000000..1fb9917 --- /dev/null +++ b/testdata/html/56.html @@ -0,0 +1,10 @@ + + +ìÉÐÅÃËÁÑ + + +

    ìÉÐÅÃËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ìÉÐÅÃËÁÑ" + + diff --git a/testdata/html/57.html b/testdata/html/57.html new file mode 100644 index 0000000..b57c740 --- /dev/null +++ b/testdata/html/57.html @@ -0,0 +1,10 @@ + + +íÁÇÁÄÁÎÓËÁÑ + + +

    íÁÇÁÄÁÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "íÁÇÁÄÁÎÓËÁÑ" + + diff --git a/testdata/html/58.html b/testdata/html/58.html new file mode 100644 index 0000000..e812156 --- /dev/null +++ b/testdata/html/58.html @@ -0,0 +1,10 @@ + + +þÕËÏÔÓËÉÊ Á×Ô.ÏËÒÕÇ + + +

    þÕËÏÔÓËÉÊ Á×Ô.ÏËÒÕÇ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "þÕËÏÔÓËÉÊ Á×Ô.ÏËÒÕÇ" + + diff --git a/testdata/html/59.html b/testdata/html/59.html new file mode 100644 index 0000000..6c40f0d --- /dev/null +++ b/testdata/html/59.html @@ -0,0 +1,10 @@ + + +íÏÓËÏ×ÓËÁÑ + + +

    íÏÓËÏ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "íÏÓËÏ×ÓËÁÑ" + + diff --git a/testdata/html/6.html b/testdata/html/6.html new file mode 100644 index 0000000..4e0624d --- /dev/null +++ b/testdata/html/6.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ ëÁÒÅÌÉÑ + + +

    òÅÓÐÕÂÌÉËÁ ëÁÒÅÌÉÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ ëÁÒÅÌÉÑ" + + diff --git a/testdata/html/60.html b/testdata/html/60.html new file mode 100644 index 0000000..4c44570 --- /dev/null +++ b/testdata/html/60.html @@ -0,0 +1,10 @@ + + +íÕÒÍÁÎÓËÁÑ + + +

    íÕÒÍÁÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "íÕÒÍÁÎÓËÁÑ" + + diff --git a/testdata/html/61.html b/testdata/html/61.html new file mode 100644 index 0000000..0ac7e6a --- /dev/null +++ b/testdata/html/61.html @@ -0,0 +1,10 @@ + + +îÏ×ÇÏÒÏÄÓËÁÑ + + +

    îÏ×ÇÏÒÏÄÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "îÏ×ÇÏÒÏÄÓËÁÑ" + + diff --git a/testdata/html/62.html b/testdata/html/62.html new file mode 100644 index 0000000..585303e --- /dev/null +++ b/testdata/html/62.html @@ -0,0 +1,10 @@ + + +îÏ×ÏÓÉÂÉÒÓËÁÑ + + +

    îÏ×ÏÓÉÂÉÒÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "îÏ×ÏÓÉÂÉÒÓËÁÑ" + + diff --git a/testdata/html/63.html b/testdata/html/63.html new file mode 100644 index 0000000..6deaf77 --- /dev/null +++ b/testdata/html/63.html @@ -0,0 +1,10 @@ + + +ïÍÓËÁÑ + + +

    ïÍÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ïÍÓËÁÑ" + + diff --git a/testdata/html/64.html b/testdata/html/64.html new file mode 100644 index 0000000..8c107df --- /dev/null +++ b/testdata/html/64.html @@ -0,0 +1,10 @@ + + +ïÒÅÎÂÕÒÇÓËÁÑ + + +

    ïÒÅÎÂÕÒÇÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ïÒÅÎÂÕÒÇÓËÁÑ" + + diff --git a/testdata/html/65.html b/testdata/html/65.html new file mode 100644 index 0000000..7c6a4c1 --- /dev/null +++ b/testdata/html/65.html @@ -0,0 +1,10 @@ + + +ïÒÌÏ×ÓËÁÑ + + +

    ïÒÌÏ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ïÒÌÏ×ÓËÁÑ" + + diff --git a/testdata/html/66.html b/testdata/html/66.html new file mode 100644 index 0000000..df0ea6f --- /dev/null +++ b/testdata/html/66.html @@ -0,0 +1,10 @@ + + +ðÅÎÚÅÎÓËÁÑ + + +

    ðÅÎÚÅÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ðÅÎÚÅÎÓËÁÑ" + + diff --git a/testdata/html/67.html b/testdata/html/67.html new file mode 100644 index 0000000..2c6f47c --- /dev/null +++ b/testdata/html/67.html @@ -0,0 +1,10 @@ + + +ðÅÒÍÓËÁÑ + + +

    ðÅÒÍÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ðÅÒÍÓËÁÑ" + + diff --git a/testdata/html/68.html b/testdata/html/68.html new file mode 100644 index 0000000..41176ca --- /dev/null +++ b/testdata/html/68.html @@ -0,0 +1,10 @@ + + +ëÏÍÉ-ðÅÒÍÑÃËÉÊ Á×Ô.ÏËÒÕÇ + + +

    ëÏÍÉ-ðÅÒÍÑÃËÉÊ Á×Ô.ÏËÒÕÇ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ëÏÍÉ-ðÅÒÍÑÃËÉÊ Á×Ô.ÏËÒÕÇ" + + diff --git a/testdata/html/69.html b/testdata/html/69.html new file mode 100644 index 0000000..820ba52 --- /dev/null +++ b/testdata/html/69.html @@ -0,0 +1,10 @@ + + +ðÓËÏ×ÓËÁÑ + + +

    ðÓËÏ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ðÓËÏ×ÓËÁÑ" + + diff --git a/testdata/html/7.html b/testdata/html/7.html new file mode 100644 index 0000000..d3092e8 --- /dev/null +++ b/testdata/html/7.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ ëÏÍÉ + + +

    òÅÓÐÕÂÌÉËÁ ëÏÍÉ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ ëÏÍÉ" + + diff --git a/testdata/html/70.html b/testdata/html/70.html new file mode 100644 index 0000000..fe1e05f --- /dev/null +++ b/testdata/html/70.html @@ -0,0 +1,10 @@ + + +òÏÓÔÏ×ÓËÁÑ + + +

    òÏÓÔÏ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÏÓÔÏ×ÓËÁÑ" + + diff --git a/testdata/html/71.html b/testdata/html/71.html new file mode 100644 index 0000000..0d40339 --- /dev/null +++ b/testdata/html/71.html @@ -0,0 +1,10 @@ + + +òÑÚÁÎÓËÁÑ + + +

    òÑÚÁÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÑÚÁÎÓËÁÑ" + + diff --git a/testdata/html/72.html b/testdata/html/72.html new file mode 100644 index 0000000..39d5afa --- /dev/null +++ b/testdata/html/72.html @@ -0,0 +1,10 @@ + + +óÁÒÁÔÏ×ÓËÁÑ + + +

    óÁÒÁÔÏ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "óÁÒÁÔÏ×ÓËÁÑ" + + diff --git a/testdata/html/73.html b/testdata/html/73.html new file mode 100644 index 0000000..96716be --- /dev/null +++ b/testdata/html/73.html @@ -0,0 +1,10 @@ + + +óÁÈÁÌÉÎÓËÁÑ + + +

    óÁÈÁÌÉÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "óÁÈÁÌÉÎÓËÁÑ" + + diff --git a/testdata/html/74.html b/testdata/html/74.html new file mode 100644 index 0000000..9aa2b37 --- /dev/null +++ b/testdata/html/74.html @@ -0,0 +1,10 @@ + + +åËÁÔÅÒÉÎÂÕÒÇÓËÁÑ + + +

    åËÁÔÅÒÉÎÂÕÒÇÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "åËÁÔÅÒÉÎÂÕÒÇÓËÁÑ" + + diff --git a/testdata/html/75.html b/testdata/html/75.html new file mode 100644 index 0000000..b70308c --- /dev/null +++ b/testdata/html/75.html @@ -0,0 +1,10 @@ + + +óÍÏÌÅÎÓËÁÑ + + +

    óÍÏÌÅÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "óÍÏÌÅÎÓËÁÑ" + + diff --git a/testdata/html/76.html b/testdata/html/76.html new file mode 100644 index 0000000..a850bd0 --- /dev/null +++ b/testdata/html/76.html @@ -0,0 +1,10 @@ + + +ôÁÍÂÏ×ÓËÁÑ + + +

    ôÁÍÂÏ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ôÁÍÂÏ×ÓËÁÑ" + + diff --git a/testdata/html/77.html b/testdata/html/77.html new file mode 100644 index 0000000..bb8c516 --- /dev/null +++ b/testdata/html/77.html @@ -0,0 +1,10 @@ + + +ôÏÍÓËÁÑ + + +

    ôÏÍÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ôÏÍÓËÁÑ" + + diff --git a/testdata/html/78.html b/testdata/html/78.html new file mode 100644 index 0000000..a369f71 --- /dev/null +++ b/testdata/html/78.html @@ -0,0 +1,10 @@ + + +ôÕÌØÓËÁÑ + + +

    ôÕÌØÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ôÕÌØÓËÁÑ" + + diff --git a/testdata/html/79.html b/testdata/html/79.html new file mode 100644 index 0000000..ff04059 --- /dev/null +++ b/testdata/html/79.html @@ -0,0 +1,10 @@ + + +ôÀÍÅÎÓËÁÑ + + +

    ôÀÍÅÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ôÀÍÅÎÓËÁÑ" + + diff --git a/testdata/html/8.html b/testdata/html/8.html new file mode 100644 index 0000000..61b26fe --- /dev/null +++ b/testdata/html/8.html @@ -0,0 +1,10 @@ + + +òÅÓÐÕÂÌÉËÁ íÁÒÉÊ üÌ + + +

    òÅÓÐÕÂÌÉËÁ íÁÒÉÊ üÌ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "òÅÓÐÕÂÌÉËÁ íÁÒÉÊ üÌ" + + diff --git a/testdata/html/80.html b/testdata/html/80.html new file mode 100644 index 0000000..02dc197 --- /dev/null +++ b/testdata/html/80.html @@ -0,0 +1,15 @@ + + +èÁÎÔÙ-íÁÎÓÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ + + +

    èÁÎÔÙ-íÁÎÓÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "èÁÎÔÙ-íÁÎÓÉÊÓËÉÊ Á×Ô.ÏËÒÕÇ" +

    +èÁÎÔÙ-íÁÎÓÉÊÓËÉÊ ÏËÒÕÇ Ñ×ÌÑÅÔÓÑ ÞÁÓÔØÀ +ôÀÍÅÎÓËÏÊ ÏÂÌÁÓÔÉ + + + + diff --git a/testdata/html/81.html b/testdata/html/81.html new file mode 100644 index 0000000..3a85550 --- /dev/null +++ b/testdata/html/81.html @@ -0,0 +1,10 @@ + + +ñÍÁÌÏ-îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ + + +

    ñÍÁÌÏ-îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ñÍÁÌÏ-îÅÎÅÃËÉÊ Á×Ô.ÏËÒÕÇ" + + diff --git a/testdata/html/82.html b/testdata/html/82.html new file mode 100644 index 0000000..02aee9b --- /dev/null +++ b/testdata/html/82.html @@ -0,0 +1,10 @@ + + +õÌØÑÎÏ×ÓËÁÑ + + +

    õÌØÑÎÏ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "õÌØÑÎÏ×ÓËÁÑ" + + diff --git a/testdata/html/83.html b/testdata/html/83.html new file mode 100644 index 0000000..c9b9219 --- /dev/null +++ b/testdata/html/83.html @@ -0,0 +1,10 @@ + + +þÅÌÑÂÉÎÓËÁÑ + + +

    þÅÌÑÂÉÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "þÅÌÑÂÉÎÓËÁÑ" + + diff --git a/testdata/html/84.html b/testdata/html/84.html new file mode 100644 index 0000000..13a4426 --- /dev/null +++ b/testdata/html/84.html @@ -0,0 +1,10 @@ + + +þÉÔÉÎÓËÁÑ + + +

    þÉÔÉÎÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "þÉÔÉÎÓËÁÑ" + + diff --git a/testdata/html/85.html b/testdata/html/85.html new file mode 100644 index 0000000..587d62b --- /dev/null +++ b/testdata/html/85.html @@ -0,0 +1,10 @@ + + +áÇÉÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒÕÇ + + +

    áÇÉÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒÕÇ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "áÇÉÎÓËÉÊ âÕÒÑÔÓËÉÊ Á×Ô.ÏËÒÕÇ" + + diff --git a/testdata/html/86.html b/testdata/html/86.html new file mode 100644 index 0000000..87af595 --- /dev/null +++ b/testdata/html/86.html @@ -0,0 +1,10 @@ + + +ñÒÏÓÌÁ×ÓËÁÑ + + +

    ñÒÏÓÌÁ×ÓËÁÑ

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "ñÒÏÓÌÁ×ÓËÁÑ" + + diff --git a/testdata/html/9.html b/testdata/html/9.html new file mode 100644 index 0000000..d80827b --- /dev/null +++ b/testdata/html/9.html @@ -0,0 +1,10 @@ + + +íÏÒÄÏ×ÓËÁÑ óóò + + +

    íÏÒÄÏ×ÓËÁÑ óóò

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "íÏÒÄÏ×ÓËÁÑ óóò" + + diff --git a/testdata/lesras.epp b/testdata/lesras.epp new file mode 100755 index 0000000000000000000000000000000000000000..5c1d115c9ffbc8b7741c7a9aba5246c76bab4228 GIT binary patch literal 84096 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 literal 0 HcmV?d00001 diff --git a/testdata/lesras.lay b/testdata/lesras.lay new file mode 100644 index 0000000..be7708b --- /dev/null +++ b/testdata/lesras.lay @@ -0,0 +1,30 @@ +#fGIS Layer file. Layer type: raster +# Layer: ìÅÓÏÒÁÓÔ. ÒÁÊÏÎÉÒÏ×ÁÎÉÅ +set _raster_ [raster ../testdata/lesras.epp] +set _legend_ [legend parse {-2 ìÅÓÏÒÁÓÔ. ÒÁÊÏÎÉÒÏ×ÁÎÉÅ +1 úÏÎÁ ÁÒËÔÉÞÅÓËÏÊ ÐÕÓÔÙÎÉ +2 úÏÎÁ ÔÕÎÄÒÙ -ÒÁ×ÎÉÎÎÁÑ +3 úÏÎÁ ÔÕÎÄÒÙ -ÇÏÒÎÁÑ +4 úÏÎÁ ÌÅÓÏÔÕÎÄÒÙ +5 úÏÎÁ ÌÕÇÏ× É ÌÕÇÏ×ÙÈ ÒÅÄËÏÌÅÓÉÊ +6 ðÏÄÚÏÎÁ ÒÅÄËÏÓÔÏÊÎÏÊ ÔÁÊÇÉ +7 ðÏÄÚÏÎÁ ÓÅ×ÅÒÎÏÊ ÔÁÊÇÉ +8 ðÏÄÚÏÎÁ ÓÒÅÄÎÅÊ ÔÁÊÇÉ +9 ðÏÄÚÏÎÁ ÀÖÎÏÊ ÔÁÊÇÉ +10 ÐÏÄÚÏÎÁ Ó ÐÒÅÏÂÌÁÄÁÎÉÅÍ È×ÏÊÎÙÈ +11 ÐÏÄÚÏÎÁ Ó ÏÄÉÎÁËÏ×ÙÍ ÕÞÁÓÔÉÅÍ È×ÏÊÎÙÈ É ÛÉÒÏËÏÌÉÓÔ×ÅÎÎÙÈ +12 ÐÏÄÚÏÎÁ ÍÏÎÏÄÏÍÉÎÁÎÔÎÙÈ ÌÅÓÏ× +13 ÐÏÄÚÏÎÁ ÐÏÌÉÄÏÍÉÎÁÎÔÎÙÈ-ÔÅÒÍÏÆÉÌØÎÙÈ ÌÅÓÏ× +14 ÚÏÎÁ +15 ÓÅ×ÅÒÎÙÈ ÓÔÅÐÅÊ +16 ÀÖÎÙÈ ÓÔÅÐÅÊ +17 ÓÅ×ÅÒÎÏÊ ÐÏÌÕÐÕÓÔÙÎÉ +18 ÀÖÎÏÊ ÐÏÌÕÐÕÓÔÙÎÉ +19 ÓÅ×ÅÒÎÏÊ ÐÕÓÔÙÎÉ +20 ÀÖÎÏÊ ÐÕÓÔÙÎÉ +}] +layer create raster -raster $_raster_\ + -border none -ovrborder yes -ovrcolor black\ + -title { ìÅÓÏÒÁÓÔ. ÒÁÊÏÎÉÒÏ×ÁÎÉÅ}\ + -legend $_legend_ + diff --git a/testdata/lesras.leg b/testdata/lesras.leg new file mode 100644 index 0000000..d3877e6 --- /dev/null +++ b/testdata/lesras.leg @@ -0,0 +1,22 @@ +-2 ìÅÓÏÒÁÓÔ. ÒÁÊÏÎÉÒÏ×ÁÎÉÅ + 1 úÏÎÁ ÁÒËÔÉÞÅÓËÏÊ ÐÕÓÔÙÎÉ + 2 úÏÎÁ ÔÕÎÄÒÙ -ÒÁ×ÎÉÎÎÁÑ + 3 úÏÎÁ ÔÕÎÄÒÙ -ÇÏÒÎÁÑ + 4 úÏÎÁ ÌÅÓÏÔÕÎÄÒÙ + 5 úÏÎÁ ÌÕÇÏ× É ÌÕÇÏ×ÙÈ ÒÅÄËÏÌÅÓÉÊ + 6 ðÏÄÚÏÎÁ ÒÅÄËÏÓÔÏÊÎÏÊ ÔÁÊÇÉ + 7 ðÏÄÚÏÎÁ ÓÅ×ÅÒÎÏÊ ÔÁÊÇÉ + 8 ðÏÄÚÏÎÁ ÓÒÅÄÎÅÊ ÔÁÊÇÉ + 9 ðÏÄÚÏÎÁ ÀÖÎÏÊ ÔÁÊÇÉ + 10 óÅ×ÅÒÎÁÑ ÐÏÄÚÏÎÁ Ó ÐÒÅÏÂÌÁÄÁÎÉÅÍ È×ÏÊÎÙÈ + 11 àÖÎÁÑ ÐÏÄÚÏÎÁ Ó ÏÄÉÎÁËÏ×ÙÍ ÕÞÁÓÔÉÅÍ È×ÏÊÎÙÈ É ÛÉÒÏËÏÌÉÓÔ×ÅÎÎÙÈ + 12 óÅ×ÅÒÎÁÑ ÐÏÄÚÏÎÁ ÍÏÎÏÄÏÍÉÎÁÎÔÎÙÈ ÌÅÓÏ× + 13 àÖÎÁÑ ÐÏÄÚÏÎÁ ÐÏÌÉÄÏÍÉÎÁÎÔÎÙÈ-ÔÅÒÍÏÆÉÌØÎÙÈ ÌÅÓÏ× + 14 ìÅÓÏÓÔÅÐÎÁÑ ÚÏÎÁ + 15 ðÏÄÚÏÎÁ ÓÅ×ÅÒÎÙÈ ÓÔÅÐÅÊ + 16 ðÏÄÚÏÎÁ ÀÖÎÙÈ ÓÔÅÐÅÊ + 17 ðÏÄÚÏÎÁ ÓÅ×ÅÒÎÏÊ ÐÏÌÕÐÕÓÔÙÎÉ + 18 ðÏÄÚÏÎÁ ÀÖÎÏÊ ÐÏÌÕÐÕÓÔÙÎÉ + 19 ðÏÄÚÏÎÁ ÓÅ×ÅÒÎÏÊ ÐÕÓÔÙÎÉ + 20 ðÏÄÚÏÎÁ ÀÖÎÏÊ ÐÕÓÔÙÎÉ + diff --git a/testdata/mkhtml.tcl b/testdata/mkhtml.tcl new file mode 100644 index 0000000..12a6aab --- /dev/null +++ b/testdata/mkhtml.tcl @@ -0,0 +1,24 @@ +set f [open admin.leg] +set out [open admin_html.leg w] +while {[gets $f line]>=0} { + if ![regexp {^ *([0-9]+) (.*)$} $line all code text] continue + if {$code<0} continue + set outname "html/$code.html" + puts $out "$code $outname" + set f2 [open $outname "w"] + puts $f2 " + +$text + + +

    $text

    + +üÔÏ ÏÐÉÓÁÎÉÅ ÒÅÇÉÏÎÁ "$text" + +" +close $f2 +} +close $out +close $f + + diff --git a/testdata/pgrm.epp b/testdata/pgrm.epp new file mode 100755 index 0000000000000000000000000000000000000000..969e19dc45a3fd010c8f9816dc28d788a829ea26 GIT binary patch literal 75008 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

    4Z)weZ;^Z_eDP_AEi@cxgv-&11o7af*R*5@ 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 literal 0 HcmV?d00001 diff --git a/testdata/poger.epp b/testdata/poger.epp new file mode 100755 index 0000000000000000000000000000000000000000..0c6b53d1374289b8f72f9adbee5ff7263c1adfb7 GIT binary patch literal 60160 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 ZN1Tx#a-ET{x+5baAODTfyJtp5{x``?cd!5e literal 0 HcmV?d00001 diff --git a/testdata/soil_mo.leg b/testdata/soil_mo.leg new file mode 100644 index 0000000..8397de6 --- /dev/null +++ b/testdata/soil_mo.leg @@ -0,0 +1,34 @@ +1 Item 1 +2 Item 2 +3 Item 3 +4 Item 4 +5 Item 5 +6 Item 6 +7 Item 7 +8 Item 8 +9 Item 9 +10 Item 10 +11 Item 11 +12 Item 12 +13 Item 13 +14 Item 14 +15 Item 15 +16 Item 16 +17 Item 17 +18 Item 18 +19 Item 19 +20 Item 20 +21 Item 21 +22 Item 22 +23 Item 23 +24 Item 24 +25 Item 25 +26 Item 26 +27 Item 27 +28 Item 28 +29 Item 29 +30 Item 30 +31 Item 31 +32 Item 32 +33 Item 33 +34 Item 34 diff --git a/testdata/test.prj b/testdata/test.prj new file mode 100644 index 0000000..ceeae1b --- /dev/null +++ b/testdata/test.prj @@ -0,0 +1,5 @@ +#! /home/vitus/fgis/tcl/hypermap +info proc hyper_* +hyper_layer admin admin_html +add_layer admin.lay +add_layer lesras.lay -- 2.39.2