liborigin-20080225.orig/0000750000175000017500000000000010762260627014524 5ustar fboudrafboudraliborigin-20080225.orig/Makefile.WINDOWS0000640000175000017500000000041210762260627017313 0ustar fboudrafboudraall : opj2dat liborigin.dll liborigin.dll : OPJFile.cpp OPJFile.h g++ -s -shared OPJFile.cpp -o liborigin.dll -lws2_32 -Wl,--out-implib,liborigin.a opj2dat: opj2dat.cpp OPJFile.cpp g++ -o opj2dat opj2dat.cpp OPJFile.cpp -lws2_32 clean : rm -f *~ *.o liborigin-20080225.orig/README0000640000175000017500000000730410762260627015411 0ustar fboudrafboudraliborigin and opj2dat --------------------- Author : Stefan Gerlach, Alex Kargovsky (fully support of 7.5 project files) Thanks to : Ion Vasilief for Windows patches and testing compiling : $ make -f Makefile.LINUX or for Darwin : $ make -f Makefile.DARWIN or for Windows : $ make -f Makefile.WINDOWS or with Solaris Compiler : $ make -f Makefile.Solaris Usage : $ ./opj2dat --------------------------------------------------------------------------- FEATURES : * reads any worksheets with all columns * supports 4.1, 5.0, 6.0, 6.1, 7.0, 7.5 projects * full support for 7.5 project files (worksheets,functions,matrix,graphs,notes) Thanks to Alex Kargovsky --------------------------------------------------------------------------- TODO : U Crash on 1kW_Diode.OPJ -> works on Linux U Crash on fano.OPJ -> works on Linux ------- X V Crash on Fred2_....OPJ O check tachyone.OPJ, test.OPJ, CaFChargenvergleich.OPJ V crash on backup.opj -> cname==0 but no matrix ! * read spreadsheet infos (LAYER section) with better method -> check out examples * support MATRIX tables * check older project versions (6.0,5.0,etc.) -> size always 0 * get column/row numbers -> resize matrix * check ws+matrix.opj 5x2 & 2x5 : 0x215 / 0x23D * check all matrix examples (also mixed) * fix reading of mixed columns in file -> SiGe example * support FUNCTION : drf_spin, tachyonen2.OPJ * read graphs * support extra graph (no link to data) : power_cdw * fix various problems (check ORIGIN/README) * support for Origin's standalone file formats It would be cool if liborigin could recognize some of Origins's standdalone file formats: *.ogg (graphic), and perhaps *.otw (template) and *.ogs (LabTalk Scripts) --------------------------------------------------------------------------- * hex dump opj files : hexdump -C file.opj > file.dump * check all projects within LabPlot 1.X (to check that it doesn't crash) LabPlot import.qs --------------------------------------------------------------------------- Changelog : 2008-02-25 * improvements from qtiplot 2007-08-21 * added build script and spec file * added tree.hh installation to Makefile.LINUX 2007-08-17 * clean up, Excel worksheets 2007-07-08 * fixed crash in 7.0 projects 2007-05-29 * full support of 7.5 projects (Alex Kargovsky) 2007-04-24 * almost full support of 7.5 projects (Thanks to Alex Kargovsky) * liborigin also supports Origins's standdalone file formats: *.ogw (worksheet) and *.ogm (matrix). 2006-12-01 * fixed crash when matrix size is incorrect 2006-11-26 * fixed crash of i943_iv.OPJ, companatonmy.opj (4.1) * fixed crash of companatomy_new.opj 06-07-06 * read size of matrix 06-02-06 * replaced arrays with vectors and char* with strings 06-01-06 * fixed convertion of 4.1 projects 05-30-06 * read matrix tables (testing) 05-29-06 * read column type if names are not matching (seems to be ok) 05-26-06 * compare only 11 chars of col label in header section 05-24-06 * fixed byteorder on big endian systems 05-16-06 * better method for storing label data (Entry) 11-15-05 * read empty entries * read label columns 11-12-05 * read valuesize from file * get names with multiple '_' correct 11-10-05 * 4.1 projects : data reading 11-09-05 * completely redesigned (using '\n') 10-25-05 * fixed problems reading column types * general column names and spreadsheet sections 09-23-05 * read also 4.1 projects 09-22-05 * new spreadsheet name finding and corrected column names 09-21-05 * new version resolving 6.0SR4 vs 6.1 problems * Spreadsheet SECTION for 6.1,6.04,6.0,5.0 09-20-05 * SPREADSHEET section for all spreadsheets (7.5,7.0) 09-09-05 * import also 5.0 projects 09-03-05 * STARTED project liborigin from LabPlot import filter liborigin-20080225.orig/ws4.opj0000750000175000017500000015567710762260627016003 0ustar fboudrafboudraCPYA 4,2769 817# ' X2U0*S@ !Qdd?? Data1_A  ???????????????????????????????????????????????????????????????????????????????????????????????????? !add?? Data1_B  ?@@@@@@ @"@$@&@(@*@,@.@0@1@2@3@4@5@6@7@8@9@:@;@<@=@>@?@@@@@A@A@B@B@C@C@D@D@E@E@F@F@G@G@H@H@I@I@J@J@K@K@L@L@M@M@N@N@O@O@P@@P@P@P@Q@@Q@Q@Q@R@@R@R@R@S@@S@S@S@T@@T@T@T@U@@U@U@U@V@@V@V@V@W@@W@W@W@X@@X@X@X@Y@ !Q?? Data2_A , ?????????????????????????????? !a?? Data2_B , r`Ac?A`?gu?n3%0?P?1%ϡ ?bp%?R7o?# ?P&#?a?Zx?Ds??2 ?!!eʖ?Z?0W?v?~l?mN?D$?w.#w|v?T?*Pq?Tr?lNG?xƇ?M07?a~$? !a?? Data2_C , @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !Q?? Data3_A , @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !a?? Data3_B , ?@@@@@@ @"@$@&@(@*@,@.@0@1@2@3@4@5@6@7@8@9@:@;@<@=@>@ !Q{{?? Data4_A  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !a{{?? Data4_B  7nч? h?+g? ®Y?,"L7?Ձ?qN? #?S[k?Oh?v@?437~?z!|t?`> ?fo)2#?F ? ?`p?ָ3JF?2Zn5.?Ed?r{eA? i/Q?m[?kU?}!?%!?Q,^w?a5h?u-+?Q?<]?lB?0 p?H?A@6t?.L?)H?ȡtY?E?i`p?x솠?S*F??ʂ?Y Ia?OSH?'T?n-?ySD?{?ډd@? UT?WhH?E@?cg?&i?hRE ?olU3`?⌓?tmj!? ?r`S?^7^Y?՗+?vNĬ?$/B T?tMQ?4?R? rY?w˓ԸC?+?p?uhR,D?-%?c{?ᗎa?Ʋd?"@?+H>?:J?E 芑?5}?NDo? !a{{?? Data4_C  E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@E@ Data1rP ORIGIN,FdXX3? BA"""? BAXX - ^@?@$@?d@l "$Ej:;M (? ף= ף= Pd, o 98?\\>>A  1 o #c5fffff?Կ(>>__WIOTN (  fffff?Կ(  o92 o # Dpffffff??(>>__LayerInfoStorage7 (  pffff??(  dA !Q$l  dB !al    P  @ P   "&@% P  @$ P    P   P P    P  @ P   "&@% P  @$ P    P   P P   P   P   P   P   P   P Data2(P ORIGIN,FdXX#? BAc/? BAXX - ^@?@$@?@l "$Ej:;M (? ף= ף= Pd, o II?55>>C  3 o II?>>A  1 o #c5fffff?Կ(>>__WIOTN (  fffff?Կ(  o92 o # Dpffffff??(>>__LayerInfoStorage7 (  pffff??(  A !Q$l  B !al  C !a    P  @ P   "&@% P  @$ P    P   P P    P  @ P   "&@% P  @$ P    P   P P   P   P   P   P   P   P Data3FcP ORIGIN,FdXXM1? BA5? BAXX - ^@?@$@?@l "$Ej:;M (? ף= ף= Pd, o ?55>>A  3 o #c5fffff?Կ(>>__WIOTN (  fffff?Կ(  o92 o # Dpffffff??(>>__LayerInfoStorage7 (  pffff??(  A !Q$l  B !al    P  @ P   "&@% P  @$ P    P   P P    P  @ P   "&@% P  @$ P    P   P P   P   P   P   P   P   P Data4^^=P ORIGIN,FdXX6? BA^B? BAXX - ^@?@$@?{@l "$Ej:;M (? ף= ף= Pd, o a ` ?55>>C  42 o ll?>>A  4 o #c5fffff?Կ(>>__WIOTN (  fffff?Կ(  o92 o # Dpffffff??(>>__LayerInfoStorage7 (  pffff??(  {A !Q$l   {B !al   {C !a    P  @ P   "&@% P  @$ P    P   P P    P  @ P   "&@% P  @$ P    P   P P   P   P   P   P   P   P @ ResultsLog    6 KrD BAgE? BA  ws4                %  (  liborigin-20080225.orig/CMakeLists.txt0000640000175000017500000000041410762260627017264 0ustar fboudrafboudraadd_library (origin SHARED OPJFile.cpp) set_target_properties(origin PROPERTIES VERSION 0.0.4 SOVERSION 0 ) install(TARGETS origin DESTINATION lib) add_executable(opj2dat opj2dat.cpp) target_link_libraries (opj2dat origin) install(TARGETS opj2dat DESTINATION bin) liborigin-20080225.orig/liborigin.pro0000640000175000017500000000033510762260627017226 0ustar fboudrafboudraTARGET = liborigin TEMPLATE = lib CONFIG += warn_on release thread CONFIG += dll MOC_DIR = ./tmp OBJECTS_DIR = ./tmp DESTDIR = ./ HEADERS = OPJFile.h SOURCES = OPJFile.cpp liborigin-20080225.orig/build-liborigin.sh0000750000175000017500000000074410762260627020143 0ustar fboudrafboudra#!/bin/bash # build liborigin RPM package LVERSION=20080225 SPEC=liborigin.spec ################################ SRC=liborigin-"$LVERSION".tar.gz if [ ! -f "$SRC" ] ; then echo "$SRC not found!" exit fi if [ ! -f "$SPEC" ] ; then echo "$SPEC not found!" exit fi echo "%_topdir /tmp/build" > ~/.rpmmacros rm -rf /tmp/build/ mkdir -p /tmp/build/{SOURCES,SPECS,RPMS,SRPMS,BUILD} cp $SRC /tmp/build/SOURCES cp $SPEC /tmp/build/SPECS cd /tmp/build/SPECS/ rpmbuild -ba $SPEC liborigin-20080225.orig/Makefile.SOLARIS0000640000175000017500000000023210762260627017275 0ustar fboudrafboudraall : opj2dat opj2dat: opj2dat.cpp OPJFile.cpp OPJFile.h c++ -o opj2dat opj2dat.cpp OPJFile.cpp clean : rm -f *~ *.o *.lo opj2dat rm -rf .deps .libs liborigin-20080225.orig/import.qs0000640000175000017500000000004310762260627016401 0ustar fboudrafboudraimportOPJ("../liborigin/ws4.opj"); liborigin-20080225.orig/Makefile.LINUX0000640000175000017500000000222010762260627017057 0ustar fboudrafboudraTARGET = liborigin TARGET0 = $(TARGET).so TARGET1 = $(TARGET0).0 TARGET2 = $(TARGET0).0.0 TARGET3 = $(TARGET0).0.0.4 OPJ = OPJFile OPJ2DAT = opj2dat CC = g++ CFLAGS = -pipe -Wall -W -O2 -fPIC LDFLAGS = -shared -Wl,-soname,$(TARGET1) LIBEXT = `./lib-arch.sh` all : $(TARGET0) $(OPJ2DAT) $(TARGET0) : $(OPJ).cpp $(OPJ).h $(CC) -c $(CFLAGS) $(OPJ).cpp -o $(OPJ).o $(CC) $(LDFLAGS) -o $(TARGET3) $(OPJ).o mkdir -p lib chmod 644 $(TARGET3) mv -f $(TARGET3) lib/ (cd lib/;\ ln -sf $(TARGET3) $(TARGET0);\ ln -sf $(TARGET3) $(TARGET1);\ ln -sf $(TARGET3) $(TARGET2)) $(OPJ2DAT): $(OPJ2DAT).cpp $(CC) $(CFLAGS) -L lib/ -o $(OPJ2DAT) -lorigin $(OPJ2DAT).cpp clean : rm -f *~ *.o $(OPJ2DAT) $(TARGET0)* rm -rf lib/ install: mkdir -pv $(DESTDIR)/usr/$(LIBEXT) cp -a lib/* $(DESTDIR)/usr/$(LIBEXT)/ mkdir -p $(DESTDIR)/usr/bin chmod 755 $(OPJ2DAT) cp $(OPJ2DAT) $(DESTDIR)/usr/bin mkdir -p $(DESTDIR)/usr/include/$(TARGET) chmod 644 $(OPJ).h tree.hh cp $(OPJ).h tree.hh $(DESTDIR)/usr/include/$(TARGET) ldconfig uninstall: rm -f $(DESTDIR)/usr/$(LIBEXT)/$(TARGET0)* $(DESTDIR)/usr/bin/$(OPJ2DAT) $(DESTDIR)/usr/include/$(TARGET)/$(OPJ).h ldconfig liborigin-20080225.orig/OPJFile.h0000640000175000017500000007446410762260627016145 0ustar fboudrafboudra/*************************************************************************** File : OPJFile.h -------------------------------------------------------------------- Copyright : (C) 2005-2008 Stefan Gerlach (C) 2008 by Alex Kargovsky, Ion Vasilief Email (use @ for *) : stefan.gerlach*uni-konstanz.de, kargovsky*yumr.phys.msu.su, ion_vasilief*yahoo.fr Description : Origin project import class ***************************************************************************/ /*************************************************************************** * * * 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 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ /* Origin 7.5 column value display : see FORMAT */ #ifndef OPJFILE_H #define OPJFILE_H /* version 0.0 2008-02-25 */ #define LIBORIGIN_VERSION 0x00080225 #define LIBORIGIN_VERSION_STRING "2008-02-25" #include #include #include "tree.hh" using namespace std; struct rect { short left; short top; short right; short bottom; int height() const { return bottom-top; }; int width() const { return right-left; }; rect() { } rect(short width, short height) : left(0) , top(0) , right(width) , bottom(height) { } }; struct originWindow { enum State {Normal, Minimized, Maximized}; enum Title {Name, Label, Both}; string name; string label; int objectID; bool bHidden; State state; Title title; rect clientRect; double creation_date; // Julian date/time double modification_date; // Julian date/time originWindow(string _name="", string _label="", bool _bHidden=false) : name(_name) , label(_label) , bHidden(_bHidden) , state(Normal) , title(Both) , creation_date(0.0) , modification_date(0.0) {}; }; struct originData { int type; // 0 - double, 1 - string double d; string s; originData(double _d) : d(_d) , type(0) , s("") {}; originData(char* _s) : s(_s) , type(1) , d(1.0e-307) {}; }; enum ColumnType {X, Y, Z, XErr, YErr, Label, NONE}; struct spreadColumn { string name; ColumnType type; int value_type;//Numeric = 0, Text = 1, Date = 2, Time = 3, Month = 4, Day = 5, Text&Numeric = 6 int value_type_specification; //see above int significant_digits; int decimal_places; int numeric_display_type;//Default Decimal Digits=0, Decimal Places=1, Significant Digits=2 string command; string comment; int width; int index; vector odata; spreadColumn(string _name="", int _index=0) : name(_name) , index(_index) , command("") , comment("") , value_type(0) , value_type_specification(0) , significant_digits(6) , decimal_places(6) , width(8) , numeric_display_type(0) {}; }; struct spreadSheet : public originWindow { int maxRows; bool bLoose; bool bMultisheet; vector column; spreadSheet(string _name="") : originWindow(_name) , bLoose(true) , bMultisheet(false) {}; }; struct excel : public originWindow { int maxRows; bool bLoose; vector sheet; excel(string _name="", string _label="", int _maxRows=0, bool _bHidden=false, bool _bLoose=true) : originWindow(_name, _label, _bHidden) , maxRows(_maxRows) , bLoose(_bLoose) { }; }; struct matrix : public originWindow { enum ViewType {DataView, ImageView}; enum HeaderViewType {ColumnRow, XY}; int nr_rows; int nr_cols; int value_type_specification; int significant_digits; int decimal_places; int numeric_display_type;//Default Decimal Digits=0, Decimal Places=1, Significant Digits=2 string command; int width; int index; ViewType view; HeaderViewType header; vector data; matrix(string _name="", int _index=0) : originWindow(_name) , index(_index) , command("") , value_type_specification(0) , significant_digits(6) , decimal_places(6) , width(8) , numeric_display_type(0) , view(DataView) , header(ColumnRow) {}; }; struct function { string name; int type;//Normal = 0, Polar = 1 string formula; double begin; double end; int points; int index; function(string _name="", int _index=0) : name(_name) , index(_index) , type(0) , formula("") , begin(0.0) , end(0.0) , points(0) {}; }; struct text { string txt; rect clientRect; int color; int fontsize; int rotation; int tab; int border_type; int attach; text(const string& _txt="") : txt(_txt) {}; text(const string& _txt, const rect& _clientRect, int _color, int _fontsize, int _rotation, int _tab, int _border_type, int _attach) : txt(_txt) , clientRect(_clientRect) , color(_color) , fontsize(_fontsize) , rotation(_rotation) , tab(_tab) , border_type(_border_type) , attach(_attach) {}; }; struct pieProperties { unsigned char view_angle; unsigned char thickness; bool clockwise_rotation; short rotation; unsigned short radius; unsigned short horizontal_offset; unsigned long displaced_sections; // maximum - 32 sections unsigned short displacement; //labels bool format_automatic; bool format_values; bool format_percentages; bool format_categories; bool position_associate; unsigned short distance; pieProperties() : clockwise_rotation(false) , format_automatic(false) , format_values(false) , format_percentages(false) , format_categories(false) , position_associate(false) {}; }; struct vectorProperties { int color; double width; unsigned short arrow_lenght; unsigned char arrow_angle; bool arrow_closed; string endXColName; string endYColName; int position; string angleColName; string magnitudeColName; float multiplier; int const_angle; int const_magnitude; vectorProperties() : arrow_closed(false) , position(0) , multiplier(1.0) , const_angle(0) , const_magnitude(0) {}; }; struct graphCurve { int type; string dataName; string xColName; string yColName; int line_color; int line_style; int line_connect; double line_width; bool fillarea; int fillarea_type; int fillarea_pattern; int fillarea_color; int fillarea_first_color; int fillarea_pattern_color; double fillarea_pattern_width; int fillarea_pattern_border_style; int fillarea_pattern_border_color; double fillarea_pattern_border_width; int symbol_type; int symbol_color; int symbol_fill_color; double symbol_size; int symbol_thickness; int point_offset; //pie pieProperties pie; //vector vectorProperties vector; }; enum AxisPosition {Left = 0, Bottom = 1, Right = 2, Top = 3}; struct graphAxisBreak { bool show; bool log10; double from; double to; int position; double scale_increment_before; double scale_increment_after; unsigned char minor_ticks_before; unsigned char minor_ticks_after; graphAxisBreak() : show(false) { } }; struct graphGrid { bool hidden; int color; int style; double width; }; struct graphAxisFormat { bool hidden; int color; double thickness; double majorTickLength; int majorTicksType; int minorTicksType; int axisPosition; double axisPositionValue; }; struct graphAxisTick { bool hidden; int color; int value_type;//Numeric = 0, Text = 1, Date = 2, Time = 3, Month = 4, Day = 5, Text&Numeric = 6 int value_type_specification; int decimal_places; int fontsize; bool fontbold; string dataName; string colName; int rotation; }; struct graphAxis { int pos; text label; double min; double max; double step; int majorTicks; int minorTicks; int scale; graphGrid majorGrid; graphGrid minorGrid; graphAxisFormat formatAxis[2]; graphAxisTick tickAxis[2]; //bottom-top, left-right }; struct rectangle { rect clientRect; int attach; }; struct circle { rect clientRect; int attach; }; struct lineVertex { int shape_type; double shape_width; double shape_length; double x; double y; lineVertex() : shape_type(0) , shape_width(0.0) , shape_length(0.0) , x(0.0) , y(0.0) {} }; struct line { rect clientRect; int color; int attach; double width; int line_style; lineVertex begin; lineVertex end; }; struct bitmap { rect clientRect; int attach; unsigned long size; unsigned char* data; double left; double top; double width; double height; }; struct metafile { rect clientRect; int attach; }; struct graphLayer { rect clientRect; text legend; graphAxis xAxis; graphAxis yAxis; graphAxisBreak xAxisBreak; graphAxisBreak yAxisBreak; double histogram_bin; double histogram_begin; double histogram_end; vector texts; vector lines; vector bitmaps; vector curve; }; struct graphLayerRange { double min; double max; double step; graphLayerRange(double _min=0.0, double _max=0.0, double _step=0.0) { min=_min; max=_max; step=_step; }; }; struct graph : public originWindow { vector layer; unsigned short width; unsigned short height; graph(string _name="") : originWindow(_name) {}; }; struct note : public originWindow { string text; note(string _name="") : originWindow(_name) {}; }; struct projectNode { int type; // 0 - object, 1 - folder string name; double creation_date; // Julian date/time double modification_date; // Julian date/time projectNode(string _name="", int _type=0, double _creation_date=0.0, double _modification_date=0.0) : name(_name) , type(_type) , creation_date(_creation_date) , modification_date(_modification_date) {}; }; class OPJFile { public: OPJFile(const char* filename); ~OPJFile() { for(unsigned int g=0; g 0) delete GRAPH[g].layer[l].bitmaps[b].data; } int Parse(); double Version() const { return version/100.0; } //!< get version of project file const tree* project() const { return &projectTree; } //spreadsheet properties int numSpreads() const { return SPREADSHEET.size(); } //!< get number of spreadsheets const char *spreadName(int s) const { return SPREADSHEET[s].name.c_str(); } //!< get name of spreadsheet s bool spreadHidden(int s) const { return SPREADSHEET[s].bHidden; } //!< is spreadsheet s hidden bool spreadLoose(int s) const { return SPREADSHEET[s].bLoose; } //!< is spreadsheet s loose rect spreadWindowRect(int s) const { return SPREADSHEET[s].clientRect; } //!< get window rectangle of spreadsheet s const char *spreadLabel(int s) const { return SPREADSHEET[s].label.c_str(); } //!< get label of spreadsheet s double spreadCreationDate(int s) const { return SPREADSHEET[s].creation_date; } //!< get creation date of spreadsheet s double spreadModificationDate(int s) const { return SPREADSHEET[s].modification_date; } //!< get modification date of spreadsheet s originWindow::State spreadState(int s) const { return SPREADSHEET[s].state; } //!< get window state of spreadsheet s originWindow::Title spreadTitle(int s) const { return SPREADSHEET[s].title; } //!< get window state of spreadsheet s int numCols(int s) const { return SPREADSHEET[s].column.size(); } //!< get number of columns of spreadsheet s int numRows(int s,int c) const { return SPREADSHEET[s].column[c].odata.size(); } //!< get number of rows of column c of spreadsheet s int maxRows(int s) const { return SPREADSHEET[s].maxRows; } //!< get maximum number of rows of spreadsheet s //spreadsheet's column properties const char *colName(int s, int c) const { return SPREADSHEET[s].column[c].name.c_str(); } //!< get name of column c of spreadsheet s ColumnType colType(int s, int c) const { return SPREADSHEET[s].column[c].type; } //!< get type of column c of spreadsheet s const char *colCommand(int s, int c) const { return SPREADSHEET[s].column[c].command.c_str(); } //!< get command of column c of spreadsheet s const char *colComment(int s, int c) const { return SPREADSHEET[s].column[c].comment.c_str(); } //!< get comment of column c of spreadsheet s int colValueType(int s, int c) const { return SPREADSHEET[s].column[c].value_type; } //!< get value type of column c of spreadsheet s int colValueTypeSpec(int s, int c) const { return SPREADSHEET[s].column[c].value_type_specification; } //!< get value type specification of column c of spreadsheet s int colSignificantDigits(int s, int c) const { return SPREADSHEET[s].column[c].significant_digits; } //!< get significant digits of column c of spreadsheet s int colDecPlaces(int s, int c) const { return SPREADSHEET[s].column[c].decimal_places; } //!< get decimal places of column c of spreadsheet s int colNumDisplayType(int s, int c) const { return SPREADSHEET[s].column[c].numeric_display_type; } //!< get numeric display type of column c of spreadsheet s int colWidth(int s, int c) const { return SPREADSHEET[s].column[c].width; } //!< get width of column c of spreadsheet s void* oData(int s, int c, int r, bool alwaysDouble=false) const { if(alwaysDouble) return (void*)&SPREADSHEET[s].column[c].odata[r].d; if(SPREADSHEET[s].column[c].odata[r].type==0) return (void*)&SPREADSHEET[s].column[c].odata[r].d; else return (void*)SPREADSHEET[s].column[c].odata[r].s.c_str(); } //!< get data of column c/row r of spreadsheet s //matrix properties int numMatrices() const { return MATRIX.size(); } //!< get number of matrices const char *matrixName(int m) const { return MATRIX[m].name.c_str(); } //!< get name of matrix m bool matrixHidden(int m) const { return MATRIX[m].bHidden; } //!< is matrix m hidden rect matrixWindowRect(int m) const { return MATRIX[m].clientRect; } //!< get window rectangle of matrix m const char *matrixLabel(int m) const { return MATRIX[m].label.c_str(); } //!< get label of matrix m double matrixCreationDate(int m) const { return MATRIX[m].creation_date; } //!< get creation date of matrix m double matrixModificationDate(int m) const { return MATRIX[m].modification_date; } //!< get modification date of matrix m originWindow::State matrixState(int m) const { return MATRIX[m].state; } //!< get window state of matrix m originWindow::Title matrixTitle(int m) const { return MATRIX[m].title; } //!< get window state of matrix m int numMatrixCols(int m) const { return MATRIX[m].nr_cols; } //!< get number of columns of matrix m int numMatrixRows(int m) const { return MATRIX[m].nr_rows; } //!< get number of rows of matrix m const char *matrixFormula(int m) const { return MATRIX[m].command.c_str(); } //!< get formula of matrix m int matrixValueTypeSpec(int m) const { return MATRIX[m].value_type_specification; } //!< get value type specification of matrix m int matrixSignificantDigits(int m) const { return MATRIX[m].significant_digits; } //!< get significant digits of matrix m int matrixDecPlaces(int m) const { return MATRIX[m].decimal_places; } //!< get decimal places of matrix m int matrixNumDisplayType(int m) const { return MATRIX[m].numeric_display_type; } //!< get numeric display type of matrix m int matrixWidth(int m) const { return MATRIX[m].width; } //!< get width of matrix m matrix::ViewType matrixViewType(int m) const { return MATRIX[m].view; } //!< get view type of matrix m matrix::HeaderViewType matrixHeaderViewType(int m) const { return MATRIX[m].header; } //!< get header view type of matrix m double matrixData(int m, int c, int r) const { return MATRIX[m].data[r*MATRIX[m].nr_cols+c]; } //!< get data of row r of column c of matrix m vector matrixData(int m) const { return MATRIX[m].data; } //!< get data of matrix m //function properties int numFunctions() const { return FUNCTION.size(); } //!< get number of functions int functionIndex(const char* s) const { return compareFunctionnames(s); } //!< get name of function s const char *functionName(int s) const { return FUNCTION[s].name.c_str(); } //!< get name of function s int functionType(int s) const { return FUNCTION[s].type; } //!< get type of function s double functionBegin(int s) const { return FUNCTION[s].begin; } //!< get begin of interval of function s double functionEnd(int s) const { return FUNCTION[s].end; } //!< get end of interval of function s int functionPoints(int s) const { return FUNCTION[s].points; } //!< get number of points in interval of function s const char *functionFormula(int s) const { return FUNCTION[s].formula.c_str(); } //!< get formula of function s //graph properties enum Color {Black=0, Red=1, Green=2, Blue=3, Cyan=4, Magenta=5, Yellow=6, DarkYellow=7, Navy=8, Purple=9, Wine=10, Olive=11, DarkCyan=12, Royal=13, Orange=14, Violet=15, Pink=16, White=17, LightGray=18, Gray=19, LTYellow=20, LTCyan=21, LTMagenta=22, DarkGray=23, Custom=255}; enum Plot {Line=200, Scatter=201, LineSymbol=202, Column=203, Area=204, HiLoClose=205, Box=206, ColumnFloat=207, Vector=208, PlotDot=209, Wall3D=210, Ribbon3D=211, Bar3D=212, ColumnStack=213, AreaStack=214, Bar=215, BarStack=216, FlowVector=218, Histogram=219, MatrixImage=220, Pie=225, Contour=226, Unknown=230, ErrorBar=231, TextPlot=232, XErrorBar=233, SurfaceColorMap=236, SurfaceColorFill=237, SurfaceWireframe=238, SurfaceBars=239, Line3D=240, Text3D=241, Mesh3D=242, XYZTriangular=245, LineSeries=246, YErrorBar=254, XYErrorBar=255, GraphScatter3D=0x8AF0, GraphTrajectory3D=0x8AF1, Polar=0x00020000, SmithChart=0x00040000, FillArea=0x00800000}; enum LineStyle {Solid=0, Dash=1, Dot=2, DashDot=3, DashDotDot=4, ShortDash=5, ShortDot=6, ShortDashDot=7}; enum LineConnect {NoLine=0, Straight=1, TwoPointSegment=2, ThreePointSegment=3, BSpline=8, Spline=9, StepHorizontal=11, StepVertical=12, StepHCenter=13, StepVCenter=14, Bezier=15}; enum Scale {Linear=0, Log10=1, Probability=2, Probit=3, Reciprocal=4, OffsetReciprocal=5, Logit=6, Ln=7, Log2=8}; enum ValueType {Numeric=0, Text=1, Time=2, Date=3, Month=4, Day=5, ColumnHeading=6, TickIndexedDataset=7, TextNumeric=9, Categorical=10}; enum BorderType {BlackLine=0, Shadow=1, DarkMarble=2, WhiteOut=3, BlackOut=4, None=-1}; enum Attach {Frame=0, Page=1, Scale=2}; enum VectorPosition {Tail, Midpoint, Head}; int numGraphs() const { return GRAPH.size(); } //!< get number of graphs const char *graphName(int s) const { return GRAPH[s].name.c_str(); } //!< get name of graph s const char *graphLabel(int s) const { return GRAPH[s].label.c_str(); } //!< get name of graph s double graphCreationDate(int s) const { return GRAPH[s].creation_date; } //!< get creation date of graph s double graphModificationDate(int s) const { return GRAPH[s].modification_date; } //!< get modification date of graph s originWindow::State graphState(int s) const { return GRAPH[s].state; } //!< get window state of graph s originWindow::Title graphTitle(int s) const { return GRAPH[s].title; } //!< get window state of graph s bool graphHidden(int s) const { return GRAPH[s].bHidden; } //!< is graph s hidden rect graphRect(int s) const { return rect(GRAPH[s].width, GRAPH[s].height); } //!< get rectangle of graph s rect graphWindowRect(int s) const { return GRAPH[s].clientRect; } //!< get window rectangle of graph s int numLayers(int s) const { return GRAPH[s].layer.size(); } //!< get number of layers of graph s rect layerRect(int s, int l) const { return GRAPH[s].layer[l].clientRect; } //!< get rectangle of layer l of graph s text layerXAxisTitle(int s, int l) const { return GRAPH[s].layer[l].xAxis.label; } //!< get label of X-axis of layer l of graph s text layerYAxisTitle(int s, int l) const { return GRAPH[s].layer[l].yAxis.label; } //!< get label of Y-axis of layer l of graph s text layerLegend(int s, int l) const { return GRAPH[s].layer[l].legend; } //!< get legend of layer l of graph s vector layerTexts(int s, int l) const { return GRAPH[s].layer[l].texts; } //!< get texts of layer l of graph s vector layerLines(int s, int l) const { return GRAPH[s].layer[l].lines; } //!< get lines of layer l of graph s vector layerBitmaps(int s, int l) const { return GRAPH[s].layer[l].bitmaps; } //!< get bitmaps of layer l of graph s graphAxisBreak layerXBreak(int s, int l) const { return GRAPH[s].layer[l].xAxisBreak; } //!< get break of horizontal axis of layer l of graph s graphAxisBreak layerYBreak(int s, int l) const { return GRAPH[s].layer[l].yAxisBreak; } //!< get break of vertical axis of layer l of graph s graphLayerRange layerXRange(int s, int l) const { return graphLayerRange(GRAPH[s].layer[l].xAxis.min, GRAPH[s].layer[l].xAxis.max, GRAPH[s].layer[l].xAxis.step); } //!< get X-range of layer l of graph s graphLayerRange layerYRange(int s, int l) const { return graphLayerRange(GRAPH[s].layer[l].yAxis.min, GRAPH[s].layer[l].yAxis.max, GRAPH[s].layer[l].yAxis.step); } //!< get Y-range of layer l of graph s vector layerXTicks(int s, int l) const { vector tick; tick.push_back(GRAPH[s].layer[l].xAxis.majorTicks); tick.push_back(GRAPH[s].layer[l].xAxis.minorTicks); return tick; } //!< get X-axis ticks of layer l of graph s vector layerYTicks(int s, int l) const { vector tick; tick.push_back(GRAPH[s].layer[l].yAxis.majorTicks); tick.push_back(GRAPH[s].layer[l].yAxis.minorTicks); return tick; } //!< get Y-axis ticks of layer l of graph s vector layerGrid(int s, int l) const { vector grid; grid.push_back(GRAPH[s].layer[l].xAxis.majorGrid); grid.push_back(GRAPH[s].layer[l].xAxis.minorGrid); grid.push_back(GRAPH[s].layer[l].yAxis.majorGrid); grid.push_back(GRAPH[s].layer[l].yAxis.minorGrid); return grid; } //!< get grid of layer l of graph s vector layerAxisFormat(int s, int l) const { vector format; format.push_back(GRAPH[s].layer[l].yAxis.formatAxis[0]); //bottom format.push_back(GRAPH[s].layer[l].yAxis.formatAxis[1]); //top format.push_back(GRAPH[s].layer[l].xAxis.formatAxis[0]); //left format.push_back(GRAPH[s].layer[l].xAxis.formatAxis[1]); //right return format; } //!< get title and format of axes of layer l of graph s vector layerAxisTickLabels(int s, int l) const { vector tick; tick.push_back(GRAPH[s].layer[l].yAxis.tickAxis[0]); //bottom tick.push_back(GRAPH[s].layer[l].yAxis.tickAxis[1]); //top tick.push_back(GRAPH[s].layer[l].xAxis.tickAxis[0]); //left tick.push_back(GRAPH[s].layer[l].xAxis.tickAxis[1]); //right return tick; } //!< get tick labels of axes of layer l of graph s vector layerHistogram(int s, int l) const { vector range; range.push_back(GRAPH[s].layer[l].histogram_bin); range.push_back(GRAPH[s].layer[l].histogram_begin); range.push_back(GRAPH[s].layer[l].histogram_end); return range; } //!< get histogram bin of layer l of graph s int layerXScale(int s, int l) const { return GRAPH[s].layer[l].xAxis.scale; } //!< get scale of X-axis of layer l of graph s int layerYScale(int s, int l) const { return GRAPH[s].layer[l].yAxis.scale; } //!< get scale of Y-axis of layer l of graph s int numCurves(int s, int l) const { return GRAPH[s].layer[l].curve.size(); } //!< get number of curves of layer l of graph s const char *curveDataName(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].dataName.c_str(); } //!< get data source name of curve c of layer l of graph s const char *curveXColName(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].xColName.c_str(); } //!< get X-column name of curve c of layer l of graph s const char *curveYColName(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].yColName.c_str(); } //!< get Y-column name of curve c of layer l of graph s int curveType(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].type; } //!< get type of curve c of layer l of graph s int curveLineStyle(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].line_style; } //!< get line style of curve c of layer l of graph s int curveLineColor(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].line_color; } //!< get line color of curve c of layer l of graph s int curveLineConnect(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].line_connect; } //!< get line connect of curve c of layer l of graph s double curveLineWidth(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].line_width; } //!< get line width of curve c of layer l of graph s bool curveIsFilledArea(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].fillarea; } //!< get is filled area of curve c of layer l of graph s int curveFillAreaColor(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].fillarea_color; } //!< get area fillcolor of curve c of layer l of graph s int curveFillAreaFirstColor(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].fillarea_first_color; } //!< get area first fillcolor of curve c of layer l of graph s int curveFillPattern(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].fillarea_pattern; } //!< get fill pattern of curve c of layer l of graph s int curveFillPatternColor(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].fillarea_pattern_color; } //!< get fill pattern color of curve c of layer l of graph s double curveFillPatternWidth(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].fillarea_pattern_width; } //!< get fill pattern line width of curve c of layer l of graph s int curveFillPatternBorderStyle(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].fillarea_pattern_border_style; } //!< get fill pattern border style of curve c of layer l of graph s int curveFillPatternBorderColor(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].fillarea_pattern_border_color; } //!< get fill pattern border color of curve c of layer l of graph s double curveFillPatternBorderWidth(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].fillarea_pattern_border_width; } //!< get fill pattern border line width of curve c of layer l of graph s int curveSymbolType(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].symbol_type; } //!< get symbol type of curve c of layer l of graph s int curveSymbolColor(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].symbol_color; } //!< get symbol color of curve c of layer l of graph s int curveSymbolFillColor(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].symbol_fill_color; } //!< get symbol fill color of curve c of layer l of graph s double curveSymbolSize(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].symbol_size; } //!< get symbol size of curve c of layer l of graph s int curveSymbolThickness(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].symbol_thickness; } //!< get symbol thickness of curve c of layer l of graph s pieProperties curvePieProperties(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].pie; } //!< get pie properties of curve c of layer l of graph s vectorProperties curveVectorProperties(int s, int l, int c) const { return GRAPH[s].layer[l].curve[c].vector; } //!< get vector properties of curve c of layer l of graph s int numNotes() const { return NOTE.size(); } //!< get number of notes const char *noteName(int n) const { return NOTE[n].name.c_str(); } //!< get name of note n const char *noteLabel(int n) const { return NOTE[n].label.c_str(); } //!< get label of note n const char *noteText(int n) const { return NOTE[n].text.c_str(); } //!< get text of note n double noteCreationDate(int n) const { return NOTE[n].creation_date; } //!< get creation date of note n double noteModificationDate(int n) const { return NOTE[n].modification_date; } //!< get modification date of note n originWindow::State noteState(int n) const { return NOTE[n].state; } //!< get window state of note n originWindow::Title noteTitle(int n) const { return NOTE[n].title; } //!< get window state of note n const char* resultsLogString() const { return resultsLog.c_str();} //!< get Results Log private: bool IsBigEndian(); void ByteSwap(unsigned char * b, int n); int ParseFormatOld(); int ParseFormatNew(); int compareSpreadnames(char *sname) const; //!< returns matching spread index int compareExcelnames(char *sname) const; //!< returns matching excel index int compareColumnnames(int spread, char *sname) const; //!< returns matching column index int compareExcelColumnnames(int excel, int sheet, char *sname) const; //!< returns matching column index int compareMatrixnames(char *sname) const; //!< returns matching matrix index int compareFunctionnames(const char *sname) const; //!< returns matching function index vector findDataByIndex(int index) const; string findObjectByIndex(int index); void readSpreadInfo(FILE *fopj, FILE *fdebug); void readExcelInfo(FILE *f, FILE *debug); void readMatrixInfo(FILE *fopj, FILE *fdebug); void readGraphInfo(FILE *fopj, FILE *fdebug); void readGraphGridInfo(graphGrid &grid, FILE *fopj, int pos); void readGraphAxisBreakInfo(graphAxisBreak &axis_break, FILE *fopj, int pos); void readGraphAxisFormatInfo(graphAxisFormat &format, FILE *fopj, int pos); void readGraphAxisTickLabelsInfo(graphAxisTick &tick, FILE *fopj, int pos); void readProjectTree(FILE *f, FILE *debug); void readProjectTreeFolder(FILE *f, FILE *debug, tree::iterator parent); void readWindowProperties(originWindow& window, FILE *f, FILE *debug, int POS, int headersize); void skipObjectInfo(FILE *fopj, FILE *fdebug); void setColName(int spread); //!< set default column name starting from spreadsheet spread void convertSpreadToExcel(int spread); const char* filename; //!< project file name int version; //!< project version int dataIndex; int objectIndex; string resultsLog; vector SPREADSHEET; vector MATRIX; vector EXCEL; vector FUNCTION; vector GRAPH; vector NOTE; tree projectTree; }; #endif // OPJFILE_H liborigin-20080225.orig/liborigin.spec0000750000175000017500000000304010762260627017356 0ustar fboudrafboudra# # spec file for liborigin # # Copyright (c) 2008 Stefan Gerlach. # This file and all modifications and additions to the pristine # package are under the same license as the package itself. # # Please submit bugfixes or comments to stefan.gerlach@uni-konstanz.de # %define version 20080225 %define release 1 ################################################################################ Name: liborigin URL: http://liborigin.sourceforge.net/ Version: %{version} Release: %{release} Distribution: %distro Summary: Library for reading ORIGIN files Source: %{name}-%{version}.tar.gz Group: Applications/Engineering License: GPL Packager: Stefan Gerlach Vendor: http://liborigin.sourceforge.net/ BuildRoot: %{_tmppath}/%{name}-%{version}-build %description liborigin is a library for reading Microcal ORIGIN files. It also contains a commandline tool opj2dat to convert them to data files. %endif Authors: -------- %{packager} %prep %setup %build %{__make} %clean rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_DIR/%{name}-%{version} rm -f ../file.list.%{name} %install %{__make} DESTDIR="$RPM_BUILD_ROOT" install cd $RPM_BUILD_ROOT find . -type d | sed '1,2d;s,^\.,\%attr(755\,root\,root) \%dir ,' > $RPM_BUILD_DIR/file.list.%{name} find . -type f -o -type l | sed 's,^\.,\%attr(-\,root\,root) ,' >> $RPM_BUILD_DIR/file.list.%{name} %post /sbin/ldconfig %postun /sbin/ldconfig %files -f ../file.list.%{name} %doc README COPYING FORMAT import.qs %changelog * Sat Aug 18 2007 - stefan.gerlach@uni-konstanz.de newly created liborigin-20080225.orig/tree.hh0000640000175000017500000024663210762260627016022 0ustar fboudrafboudra/* $Id: tree.hh,v 1.147 2007/10/19 11:24:24 peekas Exp $ STL-like templated tree class. Copyright (C) 2001-2006 Kasper Peeters . */ /** \mainpage tree.hh \author Kasper Peeters \version 2.4 \date 18-Oct-2007 \see http://www.aei.mpg.de/~peekas/tree/ \see http://www.aei.mpg.de/~peekas/tree/ChangeLog The tree.hh library for C++ provides an STL-like container class for n-ary trees, templated over the data stored at the nodes. Various types of iterators are provided (post-order, pre-order, and others). Where possible the access methods are compatible with the STL or alternative algorithms are available. */ /* The tree.hh code 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; version 2 or 3. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** \todo - New-style move members are not completely finished yet. - It would be good to have an iterator which can iterate over all nodes below a given node. - Fixed depth iterators do not iterate over the entire range if there are 'holes' in the tree. - If a range uses const iter_base& as end iterator, things will inevitably go wrong, because upcast from iter_base to a non-sibling_iter is incorrect. This upcast should be removed (and then all illegal uses as previously in 'equal' will be flagged by the compiler). This requires new copy constructors though. - There's a bug in replace(sibling_iterator, ...) when the ranges sit next to each other. Turned up in append_child(iter,iter) but has been avoided now. - "std::operator<" does not work correctly on our iterators, and for some reason a globally defined template operator< did not get picked up. Using a comparison class now, but this should be investigated. */ #ifndef tree_hh_ #define tree_hh_ #include #include #include #include #include #include #include // HP-style construct/destroy have gone from the standard, // so here is a copy. namespace kp { template void constructor(T1* p, T2& val) { new ((void *) p) T1(val); } template void constructor(T1* p) { new ((void *) p) T1; } template void destructor(T1* p) { p->~T1(); } }; /// A node in the tree, combining links to other nodes as well as the actual data. template class tree_node_ { // size: 5*4=20 bytes (on 32 bit arch), can be reduced by 8. public: tree_node_ *parent; tree_node_ *first_child, *last_child; tree_node_ *prev_sibling, *next_sibling; T data; }; // __attribute__((packed)); template > > class tree { protected: typedef tree_node_ tree_node; public: /// Value of the data stored at a node. typedef T value_type; class iterator_base; class pre_order_iterator; class post_order_iterator; class sibling_iterator; class leaf_iterator; tree(); tree(const T&); tree(const iterator_base&); tree(const tree&); ~tree(); void operator=(const tree&); /// Base class for iterators, only pointers stored, no traversal logic. #ifdef __SGI_STL_PORT class iterator_base : public stlport::bidirectional_iterator { #else class iterator_base { #endif public: typedef T value_type; typedef T* pointer; typedef T& reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; iterator_base(); iterator_base(tree_node *); T& operator*() const; T* operator->() const; /// When called, the next increment/decrement skips children of this node. void skip_children(); /// Number of children of the node pointed to by the iterator. unsigned int number_of_children() const; sibling_iterator begin() const; sibling_iterator end() const; tree_node *node; protected: bool skip_current_children_; }; /// Depth-first iterator, first accessing the node, then its children. class pre_order_iterator : public iterator_base { public: pre_order_iterator(); pre_order_iterator(tree_node *); pre_order_iterator(const iterator_base&); pre_order_iterator(const sibling_iterator&); bool operator==(const pre_order_iterator&) const; bool operator!=(const pre_order_iterator&) const; pre_order_iterator& operator++(); pre_order_iterator& operator--(); pre_order_iterator operator++(int); pre_order_iterator operator--(int); pre_order_iterator& operator+=(unsigned int); pre_order_iterator& operator-=(unsigned int); }; /// Depth-first iterator, first accessing the children, then the node itself. class post_order_iterator : public iterator_base { public: post_order_iterator(); post_order_iterator(tree_node *); post_order_iterator(const iterator_base&); post_order_iterator(const sibling_iterator&); bool operator==(const post_order_iterator&) const; bool operator!=(const post_order_iterator&) const; post_order_iterator& operator++(); post_order_iterator& operator--(); post_order_iterator operator++(int); post_order_iterator operator--(int); post_order_iterator& operator+=(unsigned int); post_order_iterator& operator-=(unsigned int); /// Set iterator to the first child as deep as possible down the tree. void descend_all(); }; /// Breadth-first iterator, using a queue class breadth_first_queued_iterator : public iterator_base { public: breadth_first_queued_iterator(); breadth_first_queued_iterator(tree_node *); breadth_first_queued_iterator(const iterator_base&); bool operator==(const breadth_first_queued_iterator&) const; bool operator!=(const breadth_first_queued_iterator&) const; breadth_first_queued_iterator& operator++(); breadth_first_queued_iterator operator++(int); breadth_first_queued_iterator& operator+=(unsigned int); private: std::queue traversal_queue; }; /// The default iterator types throughout the tree class. typedef pre_order_iterator iterator; typedef breadth_first_queued_iterator breadth_first_iterator; /// Iterator which traverses only the nodes at a given depth from the root. class fixed_depth_iterator : public iterator_base { public: fixed_depth_iterator(); fixed_depth_iterator(tree_node *); fixed_depth_iterator(const iterator_base&); fixed_depth_iterator(const sibling_iterator&); fixed_depth_iterator(const fixed_depth_iterator&); bool operator==(const fixed_depth_iterator&) const; bool operator!=(const fixed_depth_iterator&) const; fixed_depth_iterator& operator++(); fixed_depth_iterator& operator--(); fixed_depth_iterator operator++(int); fixed_depth_iterator operator--(int); fixed_depth_iterator& operator+=(unsigned int); fixed_depth_iterator& operator-=(unsigned int); tree_node *first_parent_; private: void set_first_parent_(); void find_leftmost_parent_(); }; /// Iterator which traverses only the nodes which are siblings of each other. class sibling_iterator : public iterator_base { public: sibling_iterator(); sibling_iterator(tree_node *); sibling_iterator(const sibling_iterator&); sibling_iterator(const iterator_base&); bool operator==(const sibling_iterator&) const; bool operator!=(const sibling_iterator&) const; sibling_iterator& operator++(); sibling_iterator& operator--(); sibling_iterator operator++(int); sibling_iterator operator--(int); sibling_iterator& operator+=(unsigned int); sibling_iterator& operator-=(unsigned int); tree_node *range_first() const; tree_node *range_last() const; tree_node *parent_; private: void set_parent_(); }; /// Iterator which traverses only the leaves. class leaf_iterator : public iterator_base { public: leaf_iterator(); leaf_iterator(tree_node *); leaf_iterator(const sibling_iterator&); leaf_iterator(const iterator_base&); bool operator==(const leaf_iterator&) const; bool operator!=(const leaf_iterator&) const; leaf_iterator& operator++(); leaf_iterator& operator--(); leaf_iterator operator++(int); leaf_iterator operator--(int); leaf_iterator& operator+=(unsigned int); leaf_iterator& operator-=(unsigned int); }; /// Return iterator to the beginning of the tree. inline pre_order_iterator begin() const; /// Return iterator to the end of the tree. inline pre_order_iterator end() const; /// Return post-order iterator to the beginning of the tree. post_order_iterator begin_post() const; /// Return post-order iterator to the end of the tree. post_order_iterator end_post() const; /// Return fixed-depth iterator to the first node at a given depth from the given iterator. fixed_depth_iterator begin_fixed(const iterator_base&, unsigned int) const; /// Return fixed-depth iterator to end of the nodes at given depth from the given iterator. fixed_depth_iterator end_fixed(const iterator_base&, unsigned int) const; /// Return breadth-first iterator to the first node at a given depth. breadth_first_queued_iterator begin_breadth_first() const; /// Return breadth-first iterator to end of the nodes at given depth. breadth_first_queued_iterator end_breadth_first() const; /// Return sibling iterator to the first child of given node. sibling_iterator begin(const iterator_base&) const; /// Return sibling iterator to the end of the children of a given node. sibling_iterator end(const iterator_base&) const; /// Return leaf iterator to the first leaf of the tree. leaf_iterator begin_leaf() const; /// Return leaf iterator to the last leaf of the tree. leaf_iterator end_leaf() const; /// Return iterator to the parent of a node. template static iter parent(iter); /// Return iterator to the previous sibling of a node. template iter previous_sibling(iter) const; /// Return iterator to the next sibling of a node. template iter next_sibling(iter) const; /// Return iterator to the next node at a given depth. template iter next_at_same_depth(iter) const; /// Erase all nodes of the tree. void clear(); /// Erase element at position pointed to by iterator, return incremented iterator. template iter erase(iter); /// Erase all children of the node pointed to by iterator. void erase_children(const iterator_base&); /// Insert empty node as last/first child of node pointed to by position. template iter append_child(iter position); template iter prepend_child(iter position); /// Insert node as last/first child of node pointed to by position. template iter append_child(iter position, const T& x); template iter prepend_child(iter position, const T& x); /// Append the node (plus its children) at other_position as last/first child of position. template iter append_child(iter position, iter other_position); template iter prepend_child(iter position, iter other_position); /// Append the nodes in the from-to range (plus their children) as last/first children of position. template iter append_children(iter position, sibling_iterator from, sibling_iterator to); template iter prepend_children(iter position, sibling_iterator from, sibling_iterator to); /// Short-hand to insert topmost node in otherwise empty tree. pre_order_iterator set_head(const T& x); /// Insert node as previous sibling of node pointed to by position. template iter insert(iter position, const T& x); /// Specialisation of previous member. sibling_iterator insert(sibling_iterator position, const T& x); /// Insert node (with children) pointed to by subtree as previous sibling of node pointed to by position. template iter insert_subtree(iter position, const iterator_base& subtree); /// Insert node as next sibling of node pointed to by position. template iter insert_after(iter position, const T& x); /// Insert node (with children) pointed to by subtree as next sibling of node pointed to by position. template iter insert_subtree_after(iter position, const iterator_base& subtree); /// Replace node at 'position' with other node (keeping same children); 'position' becomes invalid. template iter replace(iter position, const T& x); /// Replace node at 'position' with subtree starting at 'from' (do not erase subtree at 'from'); see above. template iter replace(iter position, const iterator_base& from); /// Replace string of siblings (plus their children) with copy of a new string (with children); see above sibling_iterator replace(sibling_iterator orig_begin, sibling_iterator orig_end, sibling_iterator new_begin, sibling_iterator new_end); /// Move all children of node at 'position' to be siblings, returns position. template iter flatten(iter position); /// Move nodes in range to be children of 'position'. template iter reparent(iter position, sibling_iterator begin, sibling_iterator end); /// Move all child nodes of 'from' to be children of 'position'. template iter reparent(iter position, iter from); /// Replace node with a new node, making the old node a child of the new node. template iter wrap(iter position, const T& x); /// Move 'source' node (plus its children) to become the next sibling of 'target'. template iter move_after(iter target, iter source); /// Move 'source' node (plus its children) to become the previous sibling of 'target'. template iter move_before(iter target, iter source); sibling_iterator move_before(sibling_iterator target, sibling_iterator source); /// Move 'source' node (plus its children) to become the node at 'target' (erasing the node at 'target'). template iter move_ontop(iter target, iter source); /// Merge with other tree, creating new branches and leaves only if they are not already present. void merge(sibling_iterator, sibling_iterator, sibling_iterator, sibling_iterator, bool duplicate_leaves=false); /// Sort (std::sort only moves values of nodes, this one moves children as well). void sort(sibling_iterator from, sibling_iterator to, bool deep=false); template void sort(sibling_iterator from, sibling_iterator to, StrictWeakOrdering comp, bool deep=false); /// Compare two ranges of nodes (compares nodes as well as tree structure). template bool equal(const iter& one, const iter& two, const iter& three) const; template bool equal(const iter& one, const iter& two, const iter& three, BinaryPredicate) const; template bool equal_subtree(const iter& one, const iter& two) const; template bool equal_subtree(const iter& one, const iter& two, BinaryPredicate) const; /// Extract a new tree formed by the range of siblings plus all their children. tree subtree(sibling_iterator from, sibling_iterator to) const; void subtree(tree&, sibling_iterator from, sibling_iterator to) const; /// Exchange the node (plus subtree) with its sibling node (do nothing if no sibling present). void swap(sibling_iterator it); /// Exchange two nodes (plus subtrees) void swap(iterator, iterator); /// Count the total number of nodes. int size() const; /// Count the total number of nodes below the indicated node (plus one). int size(const iterator_base&) const; /// Check if tree is empty. bool empty() const; /// Compute the depth to the root. int depth(const iterator_base&) const; /// Determine the maximal depth of the tree. int max_depth() const; /// Determine the maximal depth of the tree below a given one. int max_depth(const iterator_base&) const; /// Count the number of children of node at position. static unsigned int number_of_children(const iterator_base&); /// Count the number of 'next' siblings of node at iterator. unsigned int number_of_siblings(const iterator_base&) const; /// Determine whether node at position is in the subtrees with root in the range. bool is_in_subtree(const iterator_base& position, const iterator_base& begin, const iterator_base& end) const; /// Determine whether the iterator is an 'end' iterator and thus not actually pointing to a node. bool is_valid(const iterator_base&) const; /// Determine the index of a node in the range of siblings to which it belongs. unsigned int index(sibling_iterator it) const; /// Inverse of 'index': return the n-th child of the node at position. sibling_iterator child(const iterator_base& position, unsigned int) const; /// Comparator class for iterators (compares pointer values; why doesn't this work automatically?) class iterator_base_less { public: bool operator()(const typename tree::iterator_base& one, const typename tree::iterator_base& two) const { return one.node < two.node; } }; tree_node *head, *feet; // head/feet are always dummy; if an iterator points to them it is invalid private: tree_node_allocator alloc_; void head_initialise_(); void copy_(const tree& other); /// Comparator class for two nodes of a tree (used for sorting and searching). template class compare_nodes { public: compare_nodes(StrictWeakOrdering comp) : comp_(comp) {}; bool operator()(const tree_node *a, const tree_node *b) { static StrictWeakOrdering comp; return comp(a->data, b->data); } private: StrictWeakOrdering comp_; }; }; //template //class iterator_base_less { // public: // bool operator()(const typename tree::iterator_base& one, // const typename tree::iterator_base& two) const // { // txtout << "operatorclass<" << one.node < two.node << std::endl; // return one.node < two.node; // } //}; // template // bool operator<(const typename tree::iterator& one, // const typename tree::iterator& two) // { // txtout << "operator< " << one.node < two.node << std::endl; // if(one.node < two.node) return true; // return false; // } // // template // bool operator==(const typename tree::iterator& one, // const typename tree::iterator& two) // { // txtout << "operator== " << one.node == two.node << std::endl; // if(one.node == two.node) return true; // return false; // } // // template // bool operator>(const typename tree::iterator_base& one, // const typename tree::iterator_base& two) // { // txtout << "operator> " << one.node < two.node << std::endl; // if(one.node > two.node) return true; // return false; // } // Tree template tree::tree() { head_initialise_(); } template tree::tree(const T& x) { head_initialise_(); set_head(x); } template tree::tree(const iterator_base& other) { head_initialise_(); set_head((*other)); replace(begin(), other); } template tree::~tree() { clear(); alloc_.deallocate(head,1); alloc_.deallocate(feet,1); } template void tree::head_initialise_() { head = alloc_.allocate(1,0); // MSVC does not have default second argument feet = alloc_.allocate(1,0); head->parent=0; head->first_child=0; head->last_child=0; head->prev_sibling=0; //head; head->next_sibling=feet; //head; feet->parent=0; feet->first_child=0; feet->last_child=0; feet->prev_sibling=head; feet->next_sibling=0; } template void tree::operator=(const tree& other) { copy_(other); } template tree::tree(const tree& other) { head_initialise_(); copy_(other); } template void tree::copy_(const tree& other) { clear(); pre_order_iterator it=other.begin(), to=begin(); while(it!=other.end()) { to=insert(to, (*it)); it.skip_children(); ++it; } to=begin(); it=other.begin(); while(it!=other.end()) { to=replace(to, it); to.skip_children(); it.skip_children(); ++to; ++it; } } template void tree::clear() { if(head) while(head->next_sibling!=feet) erase(pre_order_iterator(head->next_sibling)); } template void tree::erase_children(const iterator_base& it) { // std::cout << "erase_children " << it.node << std::endl; if(it.node==0) return; tree_node *cur=it.node->first_child; tree_node *prev=0; while(cur!=0) { prev=cur; cur=cur->next_sibling; erase_children(pre_order_iterator(prev)); kp::destructor(&prev->data); alloc_.deallocate(prev,1); } it.node->first_child=0; it.node->last_child=0; // std::cout << "exit" << std::endl; } template template iter tree::erase(iter it) { tree_node *cur=it.node; assert(cur!=head); iter ret=it; ret.skip_children(); ++ret; erase_children(it); if(cur->prev_sibling==0) { cur->parent->first_child=cur->next_sibling; } else { cur->prev_sibling->next_sibling=cur->next_sibling; } if(cur->next_sibling==0) { cur->parent->last_child=cur->prev_sibling; } else { cur->next_sibling->prev_sibling=cur->prev_sibling; } kp::destructor(&cur->data); alloc_.deallocate(cur,1); return ret; } template typename tree::pre_order_iterator tree::begin() const { return pre_order_iterator(head->next_sibling); } template typename tree::pre_order_iterator tree::end() const { return pre_order_iterator(feet); } template typename tree::breadth_first_queued_iterator tree::begin_breadth_first() const { return breadth_first_queued_iterator(head->next_sibling); } template typename tree::breadth_first_queued_iterator tree::end_breadth_first() const { return breadth_first_queued_iterator(); } template typename tree::post_order_iterator tree::begin_post() const { tree_node *tmp=head->next_sibling; if(tmp!=feet) { while(tmp->first_child) tmp=tmp->first_child; } return post_order_iterator(tmp); } template typename tree::post_order_iterator tree::end_post() const { return post_order_iterator(feet); } template typename tree::fixed_depth_iterator tree::begin_fixed(const iterator_base& pos, unsigned int dp) const { tree_node *tmp=pos.node; unsigned int curdepth=0; while(curdepthfirst_child==0) { if(tmp->next_sibling==0) { // try to walk up and then right again do { tmp=tmp->parent; if(tmp==0) throw std::range_error("tree: begin_fixed out of range"); --curdepth; } while(tmp->next_sibling==0); } tmp=tmp->next_sibling; } tmp=tmp->first_child; ++curdepth; } return tmp; } template typename tree::fixed_depth_iterator tree::end_fixed(const iterator_base& pos, unsigned int dp) const { assert(1==0); // FIXME: not correct yet: use is_valid() as a temporary workaround tree_node *tmp=pos.node; unsigned int curdepth=1; while(curdepthfirst_child==0) { tmp=tmp->next_sibling; if(tmp==0) throw std::range_error("tree: end_fixed out of range"); } tmp=tmp->first_child; ++curdepth; } return tmp; } template typename tree::sibling_iterator tree::begin(const iterator_base& pos) const { assert(pos.node!=0); if(pos.node->first_child==0) { return end(pos); } return pos.node->first_child; } template typename tree::sibling_iterator tree::end(const iterator_base& pos) const { sibling_iterator ret(0); ret.parent_=pos.node; return ret; } template typename tree::leaf_iterator tree::begin_leaf() const { tree_node *tmp=head->next_sibling; if(tmp!=feet) { while(tmp->first_child) tmp=tmp->first_child; } return leaf_iterator(tmp); } template typename tree::leaf_iterator tree::end_leaf() const { return leaf_iterator(feet); } template template iter tree::parent(iter position) { assert(position.node!=0); return iter(position.node->parent); } template template iter tree::previous_sibling(iter position) const { assert(position.node!=0); iter ret(position); ret.node=position.node->prev_sibling; return ret; } template template iter tree::next_sibling(iter position) const { assert(position.node!=0); iter ret(position); ret.node=position.node->next_sibling; return ret; } template template iter tree::next_at_same_depth(iter position) const { assert(position.node!=0); iter ret(position); if(position.node->next_sibling) { ret.node=position.node->next_sibling; } else { int relative_depth=0; upper: do { ret.node=ret.node->parent; if(ret.node==0) return ret; --relative_depth; } while(ret.node->next_sibling==0); lower: ret.node=ret.node->next_sibling; while(ret.node->first_child==0) { if(ret.node->next_sibling==0) goto upper; ret.node=ret.node->next_sibling; if(ret.node==0) return ret; } while(relative_depth<0 && ret.node->first_child!=0) { ret.node=ret.node->first_child; ++relative_depth; } if(relative_depth<0) { if(ret.node->next_sibling==0) goto upper; else goto lower; } } return ret; } template template iter tree::append_child(iter position) { assert(position.node!=head); assert(position.node); tree_node *tmp=alloc_.allocate(1,0); kp::constructor(&tmp->data); tmp->first_child=0; tmp->last_child=0; tmp->parent=position.node; if(position.node->last_child!=0) { position.node->last_child->next_sibling=tmp; } else { position.node->first_child=tmp; } tmp->prev_sibling=position.node->last_child; position.node->last_child=tmp; tmp->next_sibling=0; return tmp; } template template iter tree::prepend_child(iter position) { assert(position.node!=head); assert(position.node); tree_node *tmp=alloc_.allocate(1,0); kp::constructor(&tmp->data); tmp->first_child=0; tmp->last_child=0; tmp->parent=position.node; if(position.node->first_child!=0) { position.node->first_child->prev_sibling=tmp; } else { position.node->last_child=tmp; } tmp->next_sibling=position.node->first_child; position.node->prev_child=tmp; tmp->prev_sibling=0; return tmp; } template template iter tree::append_child(iter position, const T& x) { // If your program fails here you probably used 'append_child' to add the top // node to an empty tree. From version 1.45 the top element should be added // using 'insert'. See the documentation for further information, and sorry about // the API change. assert(position.node!=head); assert(position.node); tree_node* tmp = alloc_.allocate(1,0); kp::constructor(&tmp->data, x); tmp->first_child=0; tmp->last_child=0; tmp->parent=position.node; if(position.node->last_child!=0) { position.node->last_child->next_sibling=tmp; } else { position.node->first_child=tmp; } tmp->prev_sibling=position.node->last_child; position.node->last_child=tmp; tmp->next_sibling=0; return tmp; } template template iter tree::prepend_child(iter position, const T& x) { assert(position.node!=head); assert(position.node); tree_node* tmp = alloc_.allocate(1,0); kp::constructor(&tmp->data, x); tmp->first_child=0; tmp->last_child=0; tmp->parent=position.node; if(position.node->first_child!=0) { position.node->first_child->prev_sibling=tmp; } else { position.node->last_child=tmp; } tmp->next_sibling=position.node->first_child; position.node->first_child=tmp; tmp->prev_sibling=0; return tmp; } template template iter tree::append_child(iter position, iter other) { assert(position.node!=head); assert(position.node); sibling_iterator aargh=append_child(position, value_type()); return replace(aargh, other); } template template iter tree::prepend_child(iter position, iter other) { assert(position.node!=head); assert(position.node); sibling_iterator aargh=prepend_child(position, value_type()); return replace(aargh, other); } template template iter tree::append_children(iter position, sibling_iterator from, sibling_iterator to) { assert(position.node!=head); assert(position.node); iter ret=from; while(from!=to) { insert_subtree(position.end(), from); ++from; } return ret; } template template iter tree::prepend_children(iter position, sibling_iterator from, sibling_iterator to) { assert(position.node!=head); assert(position.node); iter ret=from; while(from!=to) { insert_subtree(position.begin(), from); ++from; } return ret; } template typename tree::pre_order_iterator tree::set_head(const T& x) { assert(head->next_sibling==feet); return insert(iterator(feet), x); } template template iter tree::insert(iter position, const T& x) { if(position.node==0) { position.node=feet; // Backward compatibility: when calling insert on a null node, // insert before the feet. } tree_node* tmp = alloc_.allocate(1,0); kp::constructor(&tmp->data, x); tmp->first_child=0; tmp->last_child=0; tmp->parent=position.node->parent; tmp->next_sibling=position.node; tmp->prev_sibling=position.node->prev_sibling; position.node->prev_sibling=tmp; if(tmp->prev_sibling==0) { if(tmp->parent) // when inserting nodes at the head, there is no parent tmp->parent->first_child=tmp; } else tmp->prev_sibling->next_sibling=tmp; return tmp; } template typename tree::sibling_iterator tree::insert(sibling_iterator position, const T& x) { tree_node* tmp = alloc_.allocate(1,0); kp::constructor(&tmp->data, x); tmp->first_child=0; tmp->last_child=0; tmp->next_sibling=position.node; if(position.node==0) { // iterator points to end of a subtree tmp->parent=position.parent_; tmp->prev_sibling=position.range_last(); tmp->parent->last_child=tmp; } else { tmp->parent=position.node->parent; tmp->prev_sibling=position.node->prev_sibling; position.node->prev_sibling=tmp; } if(tmp->prev_sibling==0) { if(tmp->parent) // when inserting nodes at the head, there is no parent tmp->parent->first_child=tmp; } else tmp->prev_sibling->next_sibling=tmp; return tmp; } template template iter tree::insert_after(iter position, const T& x) { tree_node* tmp = alloc_.allocate(1,0); kp::constructor(&tmp->data, x); tmp->first_child=0; tmp->last_child=0; tmp->parent=position.node->parent; tmp->prev_sibling=position.node; tmp->next_sibling=position.node->next_sibling; position.node->next_sibling=tmp; if(tmp->next_sibling==0) { if(tmp->parent) // when inserting nodes at the head, there is no parent tmp->parent->last_child=tmp; } else { tmp->next_sibling->prev_sibling=tmp; } return tmp; } template template iter tree::insert_subtree(iter position, const iterator_base& subtree) { // insert dummy iter it=insert(position, value_type()); // replace dummy with subtree return replace(it, subtree); } template template iter tree::insert_subtree_after(iter position, const iterator_base& subtree) { // insert dummy iter it=insert_after(position, value_type()); // replace dummy with subtree return replace(it, subtree); } // template // template // iter tree::insert_subtree(sibling_iterator position, iter subtree) // { // // insert dummy // iter it(insert(position, value_type())); // // replace dummy with subtree // return replace(it, subtree); // } template template iter tree::replace(iter position, const T& x) { kp::destructor(&position.node->data); kp::constructor(&position.node->data, x); return position; } template template iter tree::replace(iter position, const iterator_base& from) { assert(position.node!=head); tree_node *current_from=from.node; tree_node *start_from=from.node; tree_node *current_to =position.node; // replace the node at position with head of the replacement tree at from // std::cout << "warning!" << position.node << std::endl; erase_children(position); // std::cout << "no warning!" << std::endl; tree_node* tmp = alloc_.allocate(1,0); kp::constructor(&tmp->data, (*from)); tmp->first_child=0; tmp->last_child=0; if(current_to->prev_sibling==0) { if(current_to->parent!=0) current_to->parent->first_child=tmp; } else { current_to->prev_sibling->next_sibling=tmp; } tmp->prev_sibling=current_to->prev_sibling; if(current_to->next_sibling==0) { if(current_to->parent!=0) current_to->parent->last_child=tmp; } else { current_to->next_sibling->prev_sibling=tmp; } tmp->next_sibling=current_to->next_sibling; tmp->parent=current_to->parent; kp::destructor(¤t_to->data); alloc_.deallocate(current_to,1); current_to=tmp; // only at this stage can we fix 'last' tree_node *last=from.node->next_sibling; pre_order_iterator toit=tmp; // copy all children do { assert(current_from!=0); if(current_from->first_child != 0) { current_from=current_from->first_child; toit=append_child(toit, current_from->data); } else { while(current_from->next_sibling==0 && current_from!=start_from) { current_from=current_from->parent; toit=parent(toit); assert(current_from!=0); } current_from=current_from->next_sibling; if(current_from!=last) { toit=append_child(parent(toit), current_from->data); } } } while(current_from!=last); return current_to; } template typename tree::sibling_iterator tree::replace( sibling_iterator orig_begin, sibling_iterator orig_end, sibling_iterator new_begin, sibling_iterator new_end) { tree_node *orig_first=orig_begin.node; tree_node *new_first=new_begin.node; tree_node *orig_last=orig_first; while((++orig_begin)!=orig_end) orig_last=orig_last->next_sibling; tree_node *new_last=new_first; while((++new_begin)!=new_end) new_last=new_last->next_sibling; // insert all siblings in new_first..new_last before orig_first bool first=true; pre_order_iterator ret; while(1==1) { pre_order_iterator tt=insert_subtree(pre_order_iterator(orig_first), pre_order_iterator(new_first)); if(first) { ret=tt; first=false; } if(new_first==new_last) break; new_first=new_first->next_sibling; } // erase old range of siblings bool last=false; tree_node *next=orig_first; while(1==1) { if(next==orig_last) last=true; next=next->next_sibling; erase((pre_order_iterator)orig_first); if(last) break; orig_first=next; } return ret; } template template iter tree::flatten(iter position) { if(position.node->first_child==0) return position; tree_node *tmp=position.node->first_child; while(tmp) { tmp->parent=position.node->parent; tmp=tmp->next_sibling; } if(position.node->next_sibling) { position.node->last_child->next_sibling=position.node->next_sibling; position.node->next_sibling->prev_sibling=position.node->last_child; } else { position.node->parent->last_child=position.node->last_child; } position.node->next_sibling=position.node->first_child; position.node->next_sibling->prev_sibling=position.node; position.node->first_child=0; position.node->last_child=0; return position; } template template iter tree::reparent(iter position, sibling_iterator begin, sibling_iterator end) { tree_node *first=begin.node; tree_node *last=first; assert(first!=position.node); if(begin==end) return begin; // determine last node while((++begin)!=end) { last=last->next_sibling; } // move subtree if(first->prev_sibling==0) { first->parent->first_child=last->next_sibling; } else { first->prev_sibling->next_sibling=last->next_sibling; } if(last->next_sibling==0) { last->parent->last_child=first->prev_sibling; } else { last->next_sibling->prev_sibling=first->prev_sibling; } if(position.node->first_child==0) { position.node->first_child=first; position.node->last_child=last; first->prev_sibling=0; } else { position.node->last_child->next_sibling=first; first->prev_sibling=position.node->last_child; position.node->last_child=last; } last->next_sibling=0; tree_node *pos=first; while(1==1) { pos->parent=position.node; if(pos==last) break; pos=pos->next_sibling; } return first; } template template iter tree::reparent(iter position, iter from) { if(from.node->first_child==0) return position; return reparent(position, from.node->first_child, end(from)); } template template iter tree::wrap(iter position, const T& x) { assert(position.node!=0); sibling_iterator fr=position, to=position; ++to; iter ret = insert(position, x); reparent(ret, fr, to); return ret; } template template iter tree::move_after(iter target, iter source) { tree_node *dst=target.node; tree_node *src=source.node; assert(dst); assert(src); if(dst==src) return source; if(dst->next_sibling) if(dst->next_sibling==src) // already in the right spot return source; // take src out of the tree if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; else src->parent->first_child=src->next_sibling; if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; else src->parent->last_child=src->prev_sibling; // connect it to the new point if(dst->next_sibling!=0) dst->next_sibling->prev_sibling=src; else dst->parent->last_child=src; src->next_sibling=dst->next_sibling; dst->next_sibling=src; src->prev_sibling=dst; src->parent=dst->parent; return src; } template template iter tree::move_before(iter target, iter source) { tree_node *dst=target.node; tree_node *src=source.node; assert(dst); assert(src); if(dst==src) return source; if(dst->prev_sibling) if(dst->prev_sibling==src) // already in the right spot return source; // take src out of the tree if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; else src->parent->first_child=src->next_sibling; if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; else src->parent->last_child=src->prev_sibling; // connect it to the new point if(dst->prev_sibling!=0) dst->prev_sibling->next_sibling=src; else dst->parent->first_child=src; src->prev_sibling=dst->prev_sibling; dst->prev_sibling=src; src->next_sibling=dst; src->parent=dst->parent; return src; } // specialisation for sibling_iterators template typename tree::sibling_iterator tree::move_before(sibling_iterator target, sibling_iterator source) { tree_node *dst=target.node; tree_node *src=source.node; tree_node *dst_prev_sibling; if(dst==0) { // must then be an end iterator dst_prev_sibling=target.parent_->last_child; assert(dst_prev_sibling); } else dst_prev_sibling=dst->prev_sibling; assert(src); if(dst==src) return source; if(dst_prev_sibling) if(dst_prev_sibling==src) // already in the right spot return source; // take src out of the tree if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; else src->parent->first_child=src->next_sibling; if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; else src->parent->last_child=src->prev_sibling; // connect it to the new point if(dst_prev_sibling!=0) dst_prev_sibling->next_sibling=src; else target.parent_->first_child=src; src->prev_sibling=dst_prev_sibling; if(dst) { dst->prev_sibling=src; src->parent=dst->parent; } src->next_sibling=dst; return src; } template template iter tree::move_ontop(iter target, iter source) { tree_node *dst=target.node; tree_node *src=source.node; assert(dst); assert(src); if(dst==src) return source; // remember connection points tree_node *b_prev_sibling=dst->prev_sibling; tree_node *b_next_sibling=dst->next_sibling; tree_node *b_parent=dst->parent; // remove target erase(target); // take src out of the tree if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; else src->parent->first_child=src->next_sibling; if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; else src->parent->last_child=src->prev_sibling; // connect it to the new point if(b_prev_sibling!=0) b_prev_sibling->next_sibling=src; else b_parent->first_child=src; if(b_next_sibling!=0) b_next_sibling->prev_sibling=src; else b_parent->last_child=src; src->prev_sibling=b_prev_sibling; src->next_sibling=b_next_sibling; src->parent=b_parent; return src; } template void tree::merge(sibling_iterator to1, sibling_iterator to2, sibling_iterator from1, sibling_iterator from2, bool duplicate_leaves) { sibling_iterator fnd; while(from1!=from2) { if((fnd=std::find(to1, to2, (*from1))) != to2) { // element found if(from1.begin()==from1.end()) { // full depth reached if(duplicate_leaves) append_child(parent(to1), (*from1)); } else { // descend further merge(fnd.begin(), fnd.end(), from1.begin(), from1.end(), duplicate_leaves); } } else { // element missing insert_subtree(to2, from1); } ++from1; } } template void tree::sort(sibling_iterator from, sibling_iterator to, bool deep) { std::less comp; sort(from, to, comp, deep); } template template void tree::sort(sibling_iterator from, sibling_iterator to, StrictWeakOrdering comp, bool deep) { if(from==to) return; // make list of sorted nodes // CHECK: if multiset stores equivalent nodes in the order in which they // are inserted, then this routine should be called 'stable_sort'. std::multiset > nodes(comp); sibling_iterator it=from, it2=to; while(it != to) { nodes.insert(it.node); ++it; } // reassemble --it2; // prev and next are the nodes before and after the sorted range tree_node *prev=from.node->prev_sibling; tree_node *next=it2.node->next_sibling; typename std::multiset >::iterator nit=nodes.begin(), eit=nodes.end(); if(prev==0) { if((*nit)->parent!=0) // to catch "sorting the head" situations, when there is no parent (*nit)->parent->first_child=(*nit); } else prev->next_sibling=(*nit); --eit; while(nit!=eit) { (*nit)->prev_sibling=prev; if(prev) prev->next_sibling=(*nit); prev=(*nit); ++nit; } // prev now points to the last-but-one node in the sorted range if(prev) prev->next_sibling=(*eit); // eit points to the last node in the sorted range. (*eit)->next_sibling=next; (*eit)->prev_sibling=prev; // missed in the loop above if(next==0) { if((*eit)->parent!=0) // to catch "sorting the head" situations, when there is no parent (*eit)->parent->last_child=(*eit); } else next->prev_sibling=(*eit); if(deep) { // sort the children of each node too sibling_iterator bcs(*nodes.begin()); sibling_iterator ecs(*eit); ++ecs; while(bcs!=ecs) { sort(begin(bcs), end(bcs), comp, deep); ++bcs; } } } template template bool tree::equal(const iter& one_, const iter& two, const iter& three_) const { std::equal_to comp; return equal(one_, two, three_, comp); } template template bool tree::equal_subtree(const iter& one_, const iter& two_) const { std::equal_to comp; return equal_subtree(one_, two_, comp); } template template bool tree::equal(const iter& one_, const iter& two, const iter& three_, BinaryPredicate fun) const { pre_order_iterator one(one_), three(three_); // if(one==two && is_valid(three) && three.number_of_children()!=0) // return false; while(one!=two && is_valid(three)) { if(!fun(*one,*three)) return false; if(one.number_of_children()!=three.number_of_children()) return false; ++one; ++three; } return true; } template template bool tree::equal_subtree(const iter& one_, const iter& two_, BinaryPredicate fun) const { pre_order_iterator one(one_), two(two_); if(!fun(*one,*two)) return false; if(number_of_children(one)!=number_of_children(two)) return false; return equal(begin(one),end(one),begin(two),fun); } template tree tree::subtree(sibling_iterator from, sibling_iterator to) const { tree tmp; tmp.set_head(value_type()); tmp.replace(tmp.begin(), tmp.end(), from, to); return tmp; } template void tree::subtree(tree& tmp, sibling_iterator from, sibling_iterator to) const { tmp.set_head(value_type()); tmp.replace(tmp.begin(), tmp.end(), from, to); } template int tree::size() const { int i=0; pre_order_iterator it=begin(), eit=end(); while(it!=eit) { ++i; ++it; } return i; } template int tree::size(const iterator_base& top) const { int i=0; pre_order_iterator it=top, eit=top; eit.skip_children(); ++eit; while(it!=eit) { ++i; ++it; } return i; } template bool tree::empty() const { pre_order_iterator it=begin(), eit=end(); return (it==eit); } template int tree::depth(const iterator_base& it) const { tree_node* pos=it.node; assert(pos!=0); int ret=0; while(pos->parent!=0) { pos=pos->parent; ++ret; } return ret; } template int tree::max_depth() const { return max_depth(begin()); } template int tree::max_depth(const iterator_base& pos) const { tree_node *tmp=pos.node; int curdepth=0, maxdepth=0; while(true) { // try to walk the bottom of the tree while(tmp->first_child==0) { if(tmp==pos.node) return maxdepth; if(tmp->next_sibling==0) { // try to walk up and then right again do { tmp=tmp->parent; if(tmp==0) return maxdepth; --curdepth; } while(tmp->next_sibling==0); } if(tmp==pos.node) return maxdepth; tmp=tmp->next_sibling; } tmp=tmp->first_child; ++curdepth; maxdepth=std::max(curdepth, maxdepth); } } template unsigned int tree::number_of_children(const iterator_base& it) { tree_node *pos=it.node->first_child; if(pos==0) return 0; unsigned int ret=1; // while(pos!=it.node->last_child) { // ++ret; // pos=pos->next_sibling; // } while((pos=pos->next_sibling)) ++ret; return ret; } template unsigned int tree::number_of_siblings(const iterator_base& it) const { tree_node *pos=it.node; unsigned int ret=0; // count forward while(pos->next_sibling && pos->next_sibling!=head && pos->next_sibling!=feet) { ++ret; pos=pos->next_sibling; } // count backward pos=it.node; while(pos->prev_sibling && pos->prev_sibling!=head && pos->prev_sibling!=feet) { ++ret; pos=pos->prev_sibling; } return ret; } template void tree::swap(sibling_iterator it) { tree_node *nxt=it.node->next_sibling; if(nxt) { if(it.node->prev_sibling) it.node->prev_sibling->next_sibling=nxt; else it.node->parent->first_child=nxt; nxt->prev_sibling=it.node->prev_sibling; tree_node *nxtnxt=nxt->next_sibling; if(nxtnxt) nxtnxt->prev_sibling=it.node; else it.node->parent->last_child=it.node; nxt->next_sibling=it.node; it.node->prev_sibling=nxt; it.node->next_sibling=nxtnxt; } } template void tree::swap(iterator one, iterator two) { // if one and two are adjacent siblings, use the sibling swap if(one.node->next_sibling==two.node) swap(one); else if(two.node->next_sibling==one.node) swap(two); else { tree_node *nxt1=one.node->next_sibling; tree_node *nxt2=two.node->next_sibling; tree_node *pre1=one.node->prev_sibling; tree_node *pre2=two.node->prev_sibling; tree_node *par1=one.node->parent; tree_node *par2=two.node->parent; // reconnect one.node->parent=par2; one.node->next_sibling=nxt2; if(nxt2) nxt2->prev_sibling=one.node; else par2->last_child=one.node; one.node->prev_sibling=pre2; if(pre2) pre2->next_sibling=one.node; else par2->first_child=one.node; two.node->parent=par1; two.node->next_sibling=nxt1; if(nxt1) nxt1->prev_sibling=two.node; else par1->last_child=two.node; two.node->prev_sibling=pre1; if(pre1) pre1->next_sibling=two.node; else par1->first_child=two.node; } } // template // tree::iterator tree::find_subtree( // sibling_iterator subfrom, sibling_iterator subto, iterator from, iterator to, // BinaryPredicate fun) const // { // assert(1==0); // this routine is not finished yet. // while(from!=to) { // if(fun(*subfrom, *from)) { // // } // } // return to; // } template bool tree::is_in_subtree(const iterator_base& it, const iterator_base& begin, const iterator_base& end) const { // FIXME: this should be optimised. pre_order_iterator tmp=begin; while(tmp!=end) { if(tmp==it) return true; ++tmp; } return false; } template bool tree::is_valid(const iterator_base& it) const { if(it.node==0 || it.node==feet || it.node==head) return false; else return true; } template unsigned int tree::index(sibling_iterator it) const { unsigned int ind=0; if(it.node->parent==0) { while(it.node->prev_sibling!=head) { it.node=it.node->prev_sibling; ++ind; } } else { while(it.node->prev_sibling!=0) { it.node=it.node->prev_sibling; ++ind; } } return ind; } template typename tree::sibling_iterator tree::child(const iterator_base& it, unsigned int num) const { tree_node *tmp=it.node->first_child; while(num--) { assert(tmp!=0); tmp=tmp->next_sibling; } return tmp; } // Iterator base template tree::iterator_base::iterator_base() : node(0), skip_current_children_(false) { } template tree::iterator_base::iterator_base(tree_node *tn) : node(tn), skip_current_children_(false) { } template T& tree::iterator_base::operator*() const { return node->data; } template T* tree::iterator_base::operator->() const { return &(node->data); } template bool tree::post_order_iterator::operator!=(const post_order_iterator& other) const { if(other.node!=this->node) return true; else return false; } template bool tree::post_order_iterator::operator==(const post_order_iterator& other) const { if(other.node==this->node) return true; else return false; } template bool tree::pre_order_iterator::operator!=(const pre_order_iterator& other) const { if(other.node!=this->node) return true; else return false; } template bool tree::pre_order_iterator::operator==(const pre_order_iterator& other) const { if(other.node==this->node) return true; else return false; } template bool tree::sibling_iterator::operator!=(const sibling_iterator& other) const { if(other.node!=this->node) return true; else return false; } template bool tree::sibling_iterator::operator==(const sibling_iterator& other) const { if(other.node==this->node) return true; else return false; } template bool tree::leaf_iterator::operator!=(const leaf_iterator& other) const { if(other.node!=this->node) return true; else return false; } template bool tree::leaf_iterator::operator==(const leaf_iterator& other) const { if(other.node==this->node) return true; else return false; } template typename tree::sibling_iterator tree::iterator_base::begin() const { if(node->first_child==0) return end(); sibling_iterator ret(node->first_child); ret.parent_=this->node; return ret; } template typename tree::sibling_iterator tree::iterator_base::end() const { sibling_iterator ret(0); ret.parent_=node; return ret; } template void tree::iterator_base::skip_children() { skip_current_children_=true; } template unsigned int tree::iterator_base::number_of_children() const { tree_node *pos=node->first_child; if(pos==0) return 0; unsigned int ret=1; while(pos!=node->last_child) { ++ret; pos=pos->next_sibling; } return ret; } // Pre-order iterator template tree::pre_order_iterator::pre_order_iterator() : iterator_base(0) { } template tree::pre_order_iterator::pre_order_iterator(tree_node *tn) : iterator_base(tn) { } template tree::pre_order_iterator::pre_order_iterator(const iterator_base &other) : iterator_base(other.node) { } template tree::pre_order_iterator::pre_order_iterator(const sibling_iterator& other) : iterator_base(other.node) { if(this->node==0) { if(other.range_last()!=0) this->node=other.range_last(); else this->node=other.parent_; this->skip_children(); ++(*this); } } template typename tree::pre_order_iterator& tree::pre_order_iterator::operator++() { assert(this->node!=0); if(!this->skip_current_children_ && this->node->first_child != 0) { this->node=this->node->first_child; } else { this->skip_current_children_=false; while(this->node->next_sibling==0) { this->node=this->node->parent; if(this->node==0) return *this; } this->node=this->node->next_sibling; } return *this; } template typename tree::pre_order_iterator& tree::pre_order_iterator::operator--() { assert(this->node!=0); if(this->node->prev_sibling) { this->node=this->node->prev_sibling; while(this->node->last_child) this->node=this->node->last_child; } else { this->node=this->node->parent; if(this->node==0) return *this; } return *this; } template typename tree::pre_order_iterator tree::pre_order_iterator::operator++(int n) { pre_order_iterator copy = *this; ++(*this); return copy; } template typename tree::pre_order_iterator tree::pre_order_iterator::operator--(int n) { pre_order_iterator copy = *this; --(*this); return copy; } template typename tree::pre_order_iterator& tree::pre_order_iterator::operator+=(unsigned int num) { while(num>0) { ++(*this); --num; } return (*this); } template typename tree::pre_order_iterator& tree::pre_order_iterator::operator-=(unsigned int num) { while(num>0) { --(*this); --num; } return (*this); } // Post-order iterator template tree::post_order_iterator::post_order_iterator() : iterator_base(0) { } template tree::post_order_iterator::post_order_iterator(tree_node *tn) : iterator_base(tn) { } template tree::post_order_iterator::post_order_iterator(const iterator_base &other) : iterator_base(other.node) { } template tree::post_order_iterator::post_order_iterator(const sibling_iterator& other) : iterator_base(other.node) { if(this->node==0) { if(other.range_last()!=0) this->node=other.range_last(); else this->node=other.parent_; this->skip_children(); ++(*this); } } template typename tree::post_order_iterator& tree::post_order_iterator::operator++() { assert(this->node!=0); if(this->node->next_sibling==0) { this->node=this->node->parent; this->skip_current_children_=false; } else { this->node=this->node->next_sibling; if(this->skip_current_children_) { this->skip_current_children_=false; } else { while(this->node->first_child) this->node=this->node->first_child; } } return *this; } template typename tree::post_order_iterator& tree::post_order_iterator::operator--() { assert(this->node!=0); if(this->skip_current_children_ || this->node->last_child==0) { this->skip_current_children_=false; while(this->node->prev_sibling==0) this->node=this->node->parent; this->node=this->node->prev_sibling; } else { this->node=this->node->last_child; } return *this; } template typename tree::post_order_iterator tree::post_order_iterator::operator++(int) { post_order_iterator copy = *this; ++(*this); return copy; } template typename tree::post_order_iterator tree::post_order_iterator::operator--(int) { post_order_iterator copy = *this; --(*this); return copy; } template typename tree::post_order_iterator& tree::post_order_iterator::operator+=(unsigned int num) { while(num>0) { ++(*this); --num; } return (*this); } template typename tree::post_order_iterator& tree::post_order_iterator::operator-=(unsigned int num) { while(num>0) { --(*this); --num; } return (*this); } template void tree::post_order_iterator::descend_all() { assert(this->node!=0); while(this->node->first_child) this->node=this->node->first_child; } // Breadth-first iterator template tree::breadth_first_queued_iterator::breadth_first_queued_iterator() : iterator_base() { } template tree::breadth_first_queued_iterator::breadth_first_queued_iterator(tree_node *tn) : iterator_base(tn) { traversal_queue.push(tn); } template tree::breadth_first_queued_iterator::breadth_first_queued_iterator(const iterator_base& other) : iterator_base(other.node) { traversal_queue.push(other.node); } template bool tree::breadth_first_queued_iterator::operator!=(const breadth_first_queued_iterator& other) const { if(other.node!=this->node) return true; else return false; } template bool tree::breadth_first_queued_iterator::operator==(const breadth_first_queued_iterator& other) const { if(other.node==this->node) return true; else return false; } template typename tree::breadth_first_queued_iterator& tree::breadth_first_queued_iterator::operator++() { assert(this->node!=0); // Add child nodes and pop current node sibling_iterator sib=this->begin(); while(sib!=this->end()) { traversal_queue.push(sib.node); ++sib; } traversal_queue.pop(); if(traversal_queue.size()>0) this->node=traversal_queue.front(); else this->node=0; return (*this); } template typename tree::breadth_first_queued_iterator tree::breadth_first_queued_iterator::operator++(int n) { breadth_first_queued_iterator copy = *this; ++(*this); return copy; } template typename tree::breadth_first_queued_iterator& tree::breadth_first_queued_iterator::operator+=(unsigned int num) { while(num>0) { ++(*this); --num; } return (*this); } // Fixed depth iterator template tree::fixed_depth_iterator::fixed_depth_iterator() : iterator_base() { set_first_parent_(); } template tree::fixed_depth_iterator::fixed_depth_iterator(tree_node *tn) : iterator_base(tn) { set_first_parent_(); } template tree::fixed_depth_iterator::fixed_depth_iterator(const iterator_base& other) : iterator_base(other.node) { set_first_parent_(); } template tree::fixed_depth_iterator::fixed_depth_iterator(const sibling_iterator& other) : iterator_base(other.node), first_parent_(other.parent_) { find_leftmost_parent_(); } template tree::fixed_depth_iterator::fixed_depth_iterator(const fixed_depth_iterator& other) : iterator_base(other.node), first_parent_(other.first_parent_) { } template bool tree::fixed_depth_iterator::operator==(const fixed_depth_iterator& other) const { if(other.node==this->node && other.first_parent_==first_parent_) return true; else return false; } template bool tree::fixed_depth_iterator::operator!=(const fixed_depth_iterator& other) const { if(other.node!=this->node || other.first_parent_!=first_parent_) return true; else return false; } template void tree::fixed_depth_iterator::set_first_parent_() { return; // FIXME: we do not use first_parent_ yet, and it actually needs some serious reworking if // it is ever to work at the 'head' level. first_parent_=0; if(this->node==0) return; if(this->node->parent!=0) first_parent_=this->node->parent; if(first_parent_) find_leftmost_parent_(); } template void tree::fixed_depth_iterator::find_leftmost_parent_() { return; // FIXME: see 'set_first_parent()' tree_node *tmppar=first_parent_; while(tmppar->prev_sibling) { tmppar=tmppar->prev_sibling; if(tmppar->first_child) first_parent_=tmppar; } } template typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator++() { assert(this->node!=0); if(this->node->next_sibling) { this->node=this->node->next_sibling; } else { int relative_depth=0; upper: do { this->node=this->node->parent; if(this->node==0) return *this; --relative_depth; } while(this->node->next_sibling==0); lower: this->node=this->node->next_sibling; while(this->node->first_child==0) { if(this->node->next_sibling==0) goto upper; this->node=this->node->next_sibling; if(this->node==0) return *this; } while(relative_depth<0 && this->node->first_child!=0) { this->node=this->node->first_child; ++relative_depth; } if(relative_depth<0) { if(this->node->next_sibling==0) goto upper; else goto lower; } } return *this; // if(this->node->next_sibling!=0) { // this->node=this->node->next_sibling; // assert(this->node!=0); // if(this->node->parent==0 && this->node->next_sibling==0) // feet element // this->node=0; // } // else { // tree_node *par=this->node->parent; // do { // par=par->next_sibling; // if(par==0) { // FIXME: need to keep track of this! // this->node=0; // return *this; // } // } while(par->first_child==0); // this->node=par->first_child; // } return *this; } template typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator--() { assert(this->node!=0); if(this->node->prev_sibling!=0) { this->node=this->node->prev_sibling; assert(this->node!=0); if(this->node->parent==0 && this->node->prev_sibling==0) // head element this->node=0; } else { tree_node *par=this->node->parent; do { par=par->prev_sibling; if(par==0) { // FIXME: need to keep track of this! this->node=0; return *this; } } while(par->last_child==0); this->node=par->last_child; } return *this; } template typename tree::fixed_depth_iterator tree::fixed_depth_iterator::operator++(int) { fixed_depth_iterator copy = *this; ++(*this); return copy; } template typename tree::fixed_depth_iterator tree::fixed_depth_iterator::operator--(int) { fixed_depth_iterator copy = *this; --(*this); return copy; } template typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator-=(unsigned int num) { while(num>0) { --(*this); --(num); } return (*this); } template typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator+=(unsigned int num) { while(num>0) { ++(*this); --(num); } return *this; } // FIXME: add the other members of fixed_depth_iterator. // Sibling iterator template tree::sibling_iterator::sibling_iterator() : iterator_base() { set_parent_(); } template tree::sibling_iterator::sibling_iterator(tree_node *tn) : iterator_base(tn) { set_parent_(); } template tree::sibling_iterator::sibling_iterator(const iterator_base& other) : iterator_base(other.node) { set_parent_(); } template tree::sibling_iterator::sibling_iterator(const sibling_iterator& other) : iterator_base(other), parent_(other.parent_) { } template void tree::sibling_iterator::set_parent_() { parent_=0; if(this->node==0) return; if(this->node->parent!=0) parent_=this->node->parent; } template typename tree::sibling_iterator& tree::sibling_iterator::operator++() { if(this->node) this->node=this->node->next_sibling; return *this; } template typename tree::sibling_iterator& tree::sibling_iterator::operator--() { if(this->node) this->node=this->node->prev_sibling; else { assert(parent_); this->node=parent_->last_child; } return *this; } template typename tree::sibling_iterator tree::sibling_iterator::operator++(int) { sibling_iterator copy = *this; ++(*this); return copy; } template typename tree::sibling_iterator tree::sibling_iterator::operator--(int) { sibling_iterator copy = *this; --(*this); return copy; } template typename tree::sibling_iterator& tree::sibling_iterator::operator+=(unsigned int num) { while(num>0) { ++(*this); --num; } return (*this); } template typename tree::sibling_iterator& tree::sibling_iterator::operator-=(unsigned int num) { while(num>0) { --(*this); --num; } return (*this); } template typename tree::tree_node *tree::sibling_iterator::range_first() const { tree_node *tmp=parent_->first_child; return tmp; } template typename tree::tree_node *tree::sibling_iterator::range_last() const { return parent_->last_child; } // Leaf iterator template tree::leaf_iterator::leaf_iterator() : iterator_base(0) { } template tree::leaf_iterator::leaf_iterator(tree_node *tn) : iterator_base(tn) { } template tree::leaf_iterator::leaf_iterator(const iterator_base &other) : iterator_base(other.node) { } template tree::leaf_iterator::leaf_iterator(const sibling_iterator& other) : iterator_base(other.node) { if(this->node==0) { if(other.range_last()!=0) this->node=other.range_last(); else this->node=other.parent_; ++(*this); } } template typename tree::leaf_iterator& tree::leaf_iterator::operator++() { assert(this->node!=0); while(this->node->next_sibling==0) { if (this->node->parent==0) return *this; this->node=this->node->parent; } this->node=this->node->next_sibling; while(this->node->first_child) this->node=this->node->first_child; return *this; } template typename tree::leaf_iterator& tree::leaf_iterator::operator--() { assert(this->node!=0); while (this->node->prev_sibling==0) { if (this->node->parent==0) return *this; this->node=this->node->parent; } this->node=this->node->prev_sibling; while(this->node->last_child) this->node=this->node->last_child; return *this; } template typename tree::leaf_iterator tree::leaf_iterator::operator++(int) { leaf_iterator copy = *this; ++(*this); return copy; } template typename tree::leaf_iterator tree::leaf_iterator::operator--(int) { leaf_iterator copy = *this; --(*this); return copy; } template typename tree::leaf_iterator& tree::leaf_iterator::operator+=(unsigned int num) { while(num>0) { ++(*this); --num; } return (*this); } template typename tree::leaf_iterator& tree::leaf_iterator::operator-=(unsigned int num) { while(num>0) { --(*this); --num; } return (*this); } #endif // Local variables: // default-tab-width: 3 // End: liborigin-20080225.orig/opj2dat.cpp0000640000175000017500000000672010762260627016601 0ustar fboudrafboudra/*************************************************************************** File : opj2dat.cpp -------------------------------------------------------------------- Copyright : (C) 2008 Stefan Gerlach Email (use @ for *) : stefan.gerlach*uni-konstanz.de Description : Origin project converter ***************************************************************************/ /*************************************************************************** * * * 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 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include #ifndef WIN32 #include #endif #include #include #include #include #include "OPJFile.h" int main(int argc, char *argv[]) { if(argc != 2) { printf("Usage : ./opj2dat \n"); return -1; } printf("opj2dat %s, Copyright (C) 2008 Stefan Gerlach\n",LIBORIGIN_VERSION_STRING); if(!strcmp(argv[1],"-v")) return 0; OPJFile opj(argv[1]); int status = opj.Parse(); printf("Parsing status = %d\n",status); printf("OPJ PROJECT \"%s\" VERSION = %.2f\n",argv[1],opj.Version()); printf("NUMBER OF SPREADSHEETS = %d\n",opj.numSpreads()); for (int s=0;s2.0e-300) fprintf(out,"%g ",*v); } } fprintf(out,"\n"); } } } liborigin-20080225.orig/lib-arch.sh0000750000175000017500000000011710762260627016543 0ustar fboudrafboudra#!/bin/bash if [ `arch` == "x86_64" ]; then echo "lib64" else echo "lib" fi liborigin-20080225.orig/COPYING0000640000175000017500000004313110762260627015562 0ustar fboudrafboudra GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. liborigin-20080225.orig/FORMAT0000640000175000017500000000347310762260627015447 0ustar fboudrafboudraOrigin 7.5 column value display ############################### Numeric, Text&Numeric: Decimal:1000 = 0 Scientific:1E3 = 1 Engeneering:1k = 2 Decimal:1,000 = 3 Time: hh:mm = 0 hh = 1 hh:mm:ss = 2 hh:mm:ss.zz = 3 hh ap = 4 hh:mm ap = 5 mm:ss = 6 mm:ss.zz = 7 hhmm = 8 hhmmss = 9 hh:mm:ss.zzz = 10 Date: dd/MM/yyyy = -128 dd/MM/yyyy HH:mm = -119 dd/MM/yyyy HH:mm:ss = -118 dd.MM.yyyy = 0 y. = 1 (year abbreviation - for instance, '.' in russian) MMM d = 2 M/d = 3 d = 4 ddd = 5 F = 6 (first letter of day of week) yyyy = 7 yy = 8 dd.MM.yyyy hh:mm = 9 dd.MM.yyyy hh:mm:ss = 10 yyMMdd = 11 yyMMdd hh:mm = 12 yyMMdd hh:mm:ss = 13 yyMMdd hhmm = 14 yyMMdd hhmmss = 15 MMM = 16 J = 17 (first letter of month) Q1 = 18 (quartal) M-d-yyyy (Custom1) = 19 hh:mm:ss.zzzz (Custom2) = 20 Month: MMM = 0 MMMM = 1 J = 2 (first letter of month) Day of Week: ddd = 0 dddd = 1 F = 2 (first letter of day of week) Fill Area Patterns none = 0 /// = 1 / / = 2 / = 3 \\\ = 4 \ \ = 5 \ = 6 xxx = 7 x x = 8 x = 9 --- = 10 - - = 11 - = 12 ||| = 13 | | = 14 | = 15 +++ = 16 + + = 17 + = 18 liborigin-20080225.orig/Makefile.DARWIN0000640000175000017500000000066010762260627017152 0ustar fboudrafboudraVERSION = 0.0.4 all : liborigin.dylib opj2dat liborigin.dylib : OPJFile.cpp OPJFile.h g++ -dynamiclib -multiply_defined suppress -current_version $(VERSION) -compatibility_version $(VERSION) -headerpad_max_install_names -install_name @PREFIX@/lib/liborigin.0.dylib -fPIC OPJFile.cpp -o liborigin.0.0.dylib opj2dat: opj2dat.cpp OPJFile.cpp g++ -o opj2dat opj2dat.cpp -L. -lorigin.0.0 clean : rm -f *~ *.o opj2dat liborigin.so liborigin-20080225.orig/Makefile0000777000175000017500000000000010762260627020524 2Makefile.LINUXustar fboudrafboudraliborigin-20080225.orig/OPJFile.cpp0000640000175000017500000023374610762260627016500 0ustar fboudrafboudra/*************************************************************************** File : OPJFile.cpp -------------------------------------------------------------------- Copyright : (C) 2005-2008 Stefan Gerlach (C) 2007-2008 by Alex Kargovsky, Ion Vasilief Email (use @ for *) : stefan.gerlach*uni-konstanz.de, kargovsky*yumr.phys.msu.su, ion_vasilief*yahoo.fr Description : Origin project import class ***************************************************************************/ /*************************************************************************** * * * 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 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include #include #include #include #include #include //required for std::swap #include "OPJFile.h" const char* colTypeNames[] = {"X", "Y", "Z", "XErr", "YErr", "Label", "None"}; #define MAX_LEVEL 20 #define ERROR_MSG "Please send the OPJ file and the opjfile.log to the author of liborigin!\n" #define SwapBytes(x) ByteSwap((unsigned char *) &x,sizeof(x)) int strcmp_i(const char *s1, const char *s2) { //compare two strings ignoring case #ifdef _WINDOWS return stricmp(s1,s2); #else return strcasecmp(s1,s2); #endif } void OPJFile::ByteSwap(unsigned char * b, int n) { register int i = 0; register int j = n-1; while (i OPJFile::findDataByIndex(int index) const { vector str; for(unsigned int spread=0;spread= 2766 && version <= 2769) // 7.5 return ParseFormatNew(); else return ParseFormatOld(); } int OPJFile::ParseFormatOld() { int i; FILE *f, *debug; if((f=fopen(filename,"rb")) == NULL ) { printf("Could not open %s!\n",filename); return -1; } if((debug=fopen("opjfile.log","w")) == NULL ) { printf("Could not open log file!\n"); return -1; } ////////////////////////////// check version from header /////////////////////////////// char vers[5]; vers[4]=0; // get version fseek(f,0x7,SEEK_SET); fread(&vers,4,1,f); version = atoi(vers); fprintf(debug," [version = %d]\n",version); // translate version if(version >= 130 && version <= 140) // 4.1 version=410; else if(version == 210) // 5.0 version=500; else if(version == 2625) // 6.0 version=600; else if(version == 2627) // 6.0 SR1 version=601; else if(version == 2630 ) // 6.0 SR4 version=604; else if(version == 2635 ) // 6.1 version=610; else if(version == 2656) // 7.0 version=700; else if(version == 2672) // 7.0 SR3 version=703; else { fprintf(debug,"Found unknown project version %d\n",version); fprintf(debug,"Please contact the author of opj2dat\n"); } fprintf(debug,"Found project version %.2f\n",version/100.0); unsigned char c=0; // tmp char fprintf(debug,"HEADER :\n"); for(i=0;i<0x16;i++) { // skip header + 5 Bytes ("27") fread(&c,1,1,f); fprintf(debug,"%.2X ",c); if(!((i+1)%16)) fprintf(debug,"\n"); } fprintf(debug,"\n"); do{ fread(&c,1,1,f); } while (c != '\n'); fprintf(debug," [file header @ 0x%X]\n", (unsigned int) ftell(f)); /////////////////// find column /////////////////////////////////////////////////////////// if(version>410) for(i=0;i<5;i++) // skip "0" fread(&c,1,1,f); int col_found; fread(&col_found,4,1,f); if(IsBigEndian()) SwapBytes(col_found); fread(&c,1,1,f); // skip '\n' fprintf(debug," [column found = %d/0x%X @ 0x%X]\n",col_found,col_found,(unsigned int) ftell(f)); int current_col=1, nr=0, nbytes=0; double a; char name[25], valuesize; while(col_found > 0 && col_found < 0x84) { // should be 0x72, 0x73 or 0x83 //////////////////////////////// COLUMN HEADER ///////////////////////////////////////////// fprintf(debug,"COLUMN HEADER :\n"); for(i=0;i < 0x3D;i++) { // skip 0x3C chars to value size fread(&c,1,1,f); //if(i>21 && i<27) { fprintf(debug,"%.2X ",c); if(!((i+1)%16)) fprintf(debug,"\n"); //} } fprintf(debug,"\n"); fread(&valuesize,1,1,f); fprintf(debug," [valuesize = %d @ 0x%X]\n",valuesize,(unsigned int) ftell(f)-1); if(valuesize <= 0) { fprintf(debug," WARNING : found strange valuesize of %d\n",valuesize); valuesize=10; } fprintf(debug,"SKIP :\n"); for(i=0;i<0x1A;i++) { // skip to name fread(&c,1,1,f); fprintf(debug,"%.2X ",c); if(!((i+1)%16)) fprintf(debug,"\n"); } fprintf(debug,"\n"); // read name fprintf(debug," [Spreadsheet @ 0x%X]\n",(unsigned int) ftell(f)); fflush(debug); fread(&name,25,1,f); //char* sname = new char[26]; char sname[26]; sprintf(sname,"%s",strtok(name,"_")); // spreadsheet name char* cname = strtok(NULL,"_"); // column name while(char* tmpstr = strtok(NULL,"_")) { // get multiple-"_" title correct strcat(sname,"_"); strcat(sname,cname); strcpy(cname,tmpstr); } int spread=0; if(SPREADSHEET.size() == 0 || compareSpreadnames(sname) == -1) { fprintf(debug,"NEW SPREADSHEET\n"); current_col=1; SPREADSHEET.push_back(spreadSheet(sname)); spread=SPREADSHEET.size()-1; SPREADSHEET.back().maxRows=0; } else { spread=compareSpreadnames(sname); current_col=SPREADSHEET[spread].column.size(); if(!current_col) current_col=1; current_col++; } fprintf(debug,"SPREADSHEET = %s COLUMN %d NAME = %s (@0x%X)\n", sname, current_col, cname, (unsigned int) ftell(f)); fflush(debug); if(cname == 0) { fprintf(debug,"NO COLUMN NAME FOUND! Must be a matrix or function.\n"); ////////////////////////////// READ MATRIX or FUNCTION //////////////////////////////////// fprintf(debug,"Reading MATRIX.\n"); fflush(debug); fprintf(debug," [position @ 0x%X]\n",(unsigned int) ftell(f)); // TODO fprintf(debug," SIGNATURE : "); for(i=0;i<2;i++) { // skip header fread(&c,1,1,f); fprintf(debug,"%.2X ",c); } fflush(debug); do{ // skip until '\n' fread(&c,1,1,f); // fprintf(debug,"%.2X ",c); } while (c != '\n'); fprintf(debug,"\n"); fflush(debug); // read size int size; fread(&size,4,1,f); fread(&c,1,1,f); // skip '\n' // TODO : use entry size : double, float, ... size /= 8; fprintf(debug," SIZE = %d\n",size); fflush(debug); // catch exception if(size>10000) size=1000; fprintf(debug,"VALUES :\n"); SPREADSHEET[SPREADSHEET.size()-1].maxRows=1; double value=0; for(i=0;i0) fprintf(debug,"WARNING: data section could not be read correct\n"); nr = nbytes / valuesize; fprintf(debug," [number of rows = %d (%d Bytes) @ 0x%X]\n",nr,nbytes,(unsigned int) ftell(f)); fflush(debug); SPREADSHEET[spread].maxRows 16) { // skip 0 0 fread(&c,1,1,f); fread(&c,1,1,f); } fread(&col_found,4,1,f); if(IsBigEndian()) SwapBytes(col_found); fread(&c,1,1,f); // skip '\n' fprintf(debug," [column found = %d/0x%X (@ 0x%X)]\n",col_found,col_found,(unsigned int) ftell(f)-5); fflush(debug); } ////////////////////// HEADER SECTION ////////////////////////////////////// // TODO : use new method ('\n') int POS = ftell(f)-11; fprintf(debug,"\nHEADER SECTION\n"); fprintf(debug," nr_spreads = %d\n",SPREADSHEET.size()); fprintf(debug," [position @ 0x%X]\n",POS); fflush(debug); ///////////////////// SPREADSHEET INFOS //////////////////////////////////// int LAYER=0; int COL_JUMP = 0x1ED; for(unsigned int i=0; i < SPREADSHEET.size(); i++) { fprintf(debug," reading Spreadsheet %d/%zd properties\n",i+1,SPREADSHEET.size()); fflush(debug); if(i > 0) { if (version == 700 ) POS += 0x2530 + SPREADSHEET[i-1].column.size()*COL_JUMP; else if (version == 610 ) POS += 0x25A4 + SPREADSHEET[i-1].column.size()*COL_JUMP; else if (version == 604 ) POS += 0x25A0 + SPREADSHEET[i-1].column.size()*COL_JUMP; else if (version == 601 ) POS += 0x2560 + SPREADSHEET[i-1].column.size()*COL_JUMP; // ? else if (version == 600 ) POS += 0x2560 + SPREADSHEET[i-1].column.size()*COL_JUMP; else if (version == 500 ) POS += 0x92C + SPREADSHEET[i-1].column.size()*COL_JUMP; else if (version == 410 ) POS += 0x7FB + SPREADSHEET[i-1].column.size()*COL_JUMP; } fprintf(debug," reading Header\n"); fflush(debug); // HEADER // check header int ORIGIN = 0x55; if(version == 500) ORIGIN = 0x58; fseek(f,POS + ORIGIN,SEEK_SET); // check for 'O'RIGIN char c; fread(&c,1,1,f); int jump=0; if( c == 'O') fprintf(debug," \"ORIGIN\" found ! (@ 0x%X)\n",POS+ORIGIN); while( c != 'O' && jump < MAX_LEVEL) { // no inf loop fprintf(debug," TRY %d \"O\"RIGIN not found ! : %c (@ 0x%X)",jump+1,c,POS+ORIGIN); fprintf(debug," POS=0x%X | ORIGIN = 0x%X\n",POS,ORIGIN); fflush(debug); POS+=0x1F2; fseek(f,POS + ORIGIN,SEEK_SET); fread(&c,1,1,f); jump++; } int spread=i; if(jump == MAX_LEVEL){ fprintf(debug," Spreadsheet SECTION not found ! (@ 0x%X)\n",POS-10*0x1F2+0x55); // setColName(spread); return -5; } fprintf(debug," [Spreadsheet SECTION (@ 0x%X)]\n",POS); fflush(debug); // check spreadsheet name fseek(f,POS + 0x12,SEEK_SET); fread(&name,25,1,f); spread=compareSpreadnames(name); if(spread == -1) spread=i; fprintf(debug," SPREADSHEET %d NAME : %s (@ 0x%X) has %d columns\n", spread+1,name,POS + 0x12,SPREADSHEET[spread].column.size()); fflush(debug); int ATYPE=0; LAYER = POS; if (version == 700) ATYPE = 0x2E4; else if (version == 610) ATYPE = 0x358; else if (version == 604) ATYPE = 0x354; else if (version == 601) ATYPE = 0x500; // ? else if (version == 600) ATYPE = 0x314; else if (version == 500) { COL_JUMP=0x5D; ATYPE = 0x300; } else if (version == 410) { COL_JUMP = 0x58; ATYPE = 0x229; } fflush(debug); /////////////// COLUMN Types /////////////////////////////////////////// fprintf(debug," Spreadsheet has %d columns\n",SPREADSHEET[spread].column.size()); for (unsigned int j=0;j= 130 && version <= 140) // 4.1 version=410; else if(version == 210) // 5.0 version=500; else if(version == 2625) // 6.0 version=600; else if(version == 2627) // 6.0 SR1 version=601; else if(version == 2630 ) // 6.0 SR4 version=604; else if(version == 2635 ) // 6.1 version=610; else if(version == 2656) // 7.0 version=700; else if(version == 2672) // 7.0 SR3 version=703; else if(version >= 2766 && version <= 2769) // 7.5 version=750; else { fprintf(debug,"Found unknown project version %d\n",version); fprintf(debug,"Please contact the author of opj2dat\n"); } fprintf(debug,"Found project version %.2f\n",version/100.0); unsigned char c=0; // tmp char fprintf(debug,"HEADER :\n"); for(i=0;i<0x16;i++) { // skip header + 5 Bytes ("27") fread(&c,1,1,f); fprintf(debug,"%.2X ",c); if(!((i+1)%16)) fprintf(debug,"\n"); } fprintf(debug,"\n"); do{ fread(&c,1,1,f); } while (c != '\n'); fprintf(debug," [file header @ 0x%X]\n", (unsigned int) ftell(f)); /////////////////// find column /////////////////////////////////////////////////////////// if(version>410) for(i=0;i<5;i++) // skip "0" fread(&c,1,1,f); int col_found; fread(&col_found,4,1,f); if(IsBigEndian()) SwapBytes(col_found); fread(&c,1,1,f); // skip '\n' fprintf(debug," [column found = %d/0x%X @ 0x%X]\n",col_found,col_found,(unsigned int) ftell(f)); int colpos=ftell(f); int current_col=1, nr=0, nbytes=0; double a; char name[25], valuesize; while(col_found > 0 && col_found < 0x84) { // should be 0x72, 0x73 or 0x83 //////////////////////////////// COLUMN HEADER ///////////////////////////////////////////// short data_type; char data_type_u; int oldpos=ftell(f); fseek(f,oldpos+0x16,SEEK_SET); fread(&data_type,2,1,f); if(IsBigEndian()) SwapBytes(data_type); fseek(f,oldpos+0x3F,SEEK_SET); fread(&data_type_u,1,1,f); fseek(f,oldpos,SEEK_SET); fprintf(debug,"COLUMN HEADER :\n"); for(i=0;i < 0x3D;i++) { // skip 0x3C chars to value size fread(&c,1,1,f); //if(i>21 && i<27) { fprintf(debug,"%.2X ",c); if(!((i+1)%16)) fprintf(debug,"\n"); //} } fprintf(debug,"\n"); fread(&valuesize,1,1,f); fprintf(debug," [valuesize = %d @ 0x%X]\n",valuesize,(unsigned int) ftell(f)-1); if(valuesize <= 0) { fprintf(debug," WARNING : found strange valuesize of %d\n",valuesize); valuesize=10; } fprintf(debug,"SKIP :\n"); for(i=0;i<0x1A;i++) { // skip to name fread(&c,1,1,f); fprintf(debug,"%.2X ",c); if(!((i+1)%16)) fprintf(debug,"\n"); } fprintf(debug,"\n"); // read name fprintf(debug," [Spreadsheet @ 0x%X]\n",(unsigned int) ftell(f)); fflush(debug); fread(&name,25,1,f); //char* sname = new char[26]; char sname[26]; sprintf(sname,"%s",strtok(name,"_")); // spreadsheet name char* cname = strtok(NULL,"_"); // column name while(char* tmpstr = strtok(NULL,"_")) { // get multiple-"_" title correct strcat(sname,"_"); strcat(sname,cname); strcpy(cname,tmpstr); } int spread=0; if(cname == 0) { fprintf(debug,"NO COLUMN NAME FOUND! Must be a matrix or function.\n"); ////////////////////////////// READ MATRIX or FUNCTION //////////////////////////////////// fprintf(debug," [position @ 0x%X]\n",(unsigned int) ftell(f)); // TODO short signature; fread(&signature,2,1,f); if(IsBigEndian()) SwapBytes(signature); fprintf(debug," SIGNATURE : "); fprintf(debug,"%.2X ",signature); fflush(debug); do{ // skip until '\n' fread(&c,1,1,f); // fprintf(debug,"%.2X ",c); } while (c != '\n'); fprintf(debug,"\n"); fflush(debug); // read size int size; fread(&size,4,1,f); if(IsBigEndian()) SwapBytes(size); fread(&c,1,1,f); // skip '\n' // TODO : use entry size : double, float, ... size /= valuesize; fprintf(debug," SIZE = %d\n",size); fflush(debug); // catch exception /*if(size>10000) size=1000;*/ switch(signature) { case 0x50CA: case 0x70CA: case 0x50F2: case 0x50E2: fprintf(debug,"NEW MATRIX\n"); MATRIX.push_back(matrix(sname, dataIndex)); dataIndex++; fprintf(debug,"VALUES :\n"); switch(data_type) { case 0x6001://double for(i=0;i1) { SPREADSHEET[spread].bMultisheet=true; fprintf(debug,"SPREADSHEET \"%s\" IS MULTISHEET \n", sname); } dataIndex++; ////////////////////////////// SIZE of column ///////////////////////////////////////////// do{ // skip until '\n' fread(&c,1,1,f); } while (c != '\n'); fread(&nbytes,4,1,f); if(IsBigEndian()) SwapBytes(nbytes); if(fmod(nbytes,(double)valuesize)>0) fprintf(debug,"WARNING: data section could not be read correct\n"); nr = nbytes / valuesize; fprintf(debug," [number of rows = %d (%d Bytes) @ 0x%X]\n",nr,nbytes,(unsigned int) ftell(f)); fflush(debug); SPREADSHEET[spread].maxRows0) { // skip 0 0 fread(&c,1,1,f); fread(&c,1,1,f); }*/ fprintf(debug," [data @ 0x%X]\n",(unsigned int) ftell(f)); fflush(debug); for (i=0;i0||cname==0) fseek(f,1,SEEK_CUR); int tailsize; fread(&tailsize,4,1,f); if(IsBigEndian()) SwapBytes(tailsize); fseek(f,1+tailsize+(tailsize>0?1:0),SEEK_CUR); //skip tail //fseek(f,5+((nbytes>0||cname==0)?1:0),SEEK_CUR); fread(&col_found,4,1,f); if(IsBigEndian()) SwapBytes(col_found); fseek(f,1,SEEK_CUR); // skip '\n' fprintf(debug," [column found = %d/0x%X (@ 0x%X)]\n",col_found,col_found,(unsigned int) ftell(f)-5); colpos=ftell(f); fflush(debug); } //////////////////////////////////////////////////////////////////////////// for(unsigned int i=0; i1) { stmp = new char[labellen]; stmp[labellen-1]='\0'; fread(stmp,labellen-1,1,f); NOTE.back().label=stmp; delete stmp; fseek(f,1,SEEK_CUR); } stmp = new char[size-labellen+1]; fread(stmp,size-labellen,1,f); NOTE.back().text=stmp; fprintf(debug,"NOTE %d NAME: %s\n", NOTE.size(), NOTE.back().name.c_str()); fprintf(debug,"NOTE %d LABEL: %s\n", NOTE.size(), NOTE.back().label.c_str()); fprintf(debug,"NOTE %d TEXT:\n%s\n", NOTE.size(), NOTE.back().text.c_str()); delete stmp; fseek(f,1,SEEK_CUR); } } fseek(f,1+4*5+0x10+1,SEEK_CUR); try { readProjectTree(f, debug); } catch(...) {} fprintf(debug,"Done parsing\n"); fclose(debug); return 0; } void OPJFile::readSpreadInfo(FILE *f, FILE *debug) { int POS=ftell(f); int headersize; fread(&headersize,4,1,f); if(IsBigEndian()) SwapBytes(headersize); POS+=5; fprintf(debug," [Spreadsheet SECTION (@ 0x%X)]\n",POS); fflush(debug); // check spreadsheet name char name[25]; fseek(f,POS + 0x2,SEEK_SET); fread(&name,25,1,f); int spread=compareSpreadnames(name); SPREADSHEET[spread].name=name; readWindowProperties(SPREADSHEET[spread], f, debug, POS, headersize); SPREADSHEET[spread].bLoose=false; char c = 0; int LAYER = POS; { // LAYER section LAYER += headersize + 0x1 + 0x5/* length of block = 0x12D + '\n'*/ + 0x12D + 0x1; //now structure is next : section_header_size=0x6F(4 bytes) + '\n' + section_header(0x6F bytes) + section_body_1_size(4 bytes) + '\n' + section_body_1 + section_body_2_size(maybe=0)(4 bytes) + '\n' + section_body_2 + '\n' //possible sections: column formulas, __WIPR, __WIOTN, __LayerInfoStorage etc //section name(column name in formula case) starts with 0x46 position while(1) { int sec_size; //section_header_size=0x6F(4 bytes) + '\n' LAYER+=0x5; //section_header fseek(f,LAYER+0x46,SEEK_SET); char sec_name[42]; sec_name[41]='\0'; fread(&sec_name,41,1,f); fprintf(debug," DEBUG SECTION NAME: %s (@ 0x%X)\n", sec_name, LAYER+0x46); fflush(debug); //section_body_1_size LAYER+=0x6F+0x1; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_1 LAYER+=0x5; fseek(f,LAYER,SEEK_SET); //check if it is a formula int col_index=compareColumnnames(spread,sec_name); if(col_index!=-1) { char *stmp=new char[sec_size+1]; stmp[sec_size]='\0'; fread(stmp,sec_size,1,f); SPREADSHEET[spread].column[col_index].command=stmp; delete stmp; } //section_body_2_size LAYER+=sec_size+0x1; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_2 LAYER+=0x5; //close section 00 00 00 00 0A LAYER+=sec_size+(sec_size>0?0x1:0)+0x5; if(0==strcmp(sec_name,"__LayerInfoStorage")) break; } LAYER+=0x5; } fflush(debug); /////////////// COLUMN Types /////////////////////////////////////////// fprintf(debug," Spreadsheet has %d columns\n",SPREADSHEET[spread].column.size()); while(1) { LAYER+=0x5; fseek(f,LAYER+0x12, SEEK_SET); fread(&name,12,1,f); fseek(f,LAYER+0x11, SEEK_SET); fread(&c,1,1,f); short width=0; fseek(f,LAYER+0x4A, SEEK_SET); fread(&width,2,1,f); if(IsBigEndian()) SwapBytes(width); int col_index=compareColumnnames(spread,name); if(col_index!=-1) { ColumnType type; switch(c) { case 3: type = X; break; case 0: type = Y; break; case 5: type = Z; break; case 6: type = XErr; break; case 2: type = YErr; break; case 4: type = Label; break; default: type = NONE; break; } SPREADSHEET[spread].column[col_index].type=type; width/=0xA; if(width==0) width=8; SPREADSHEET[spread].column[col_index].width=width; fseek(f,LAYER+0x1E, SEEK_SET); unsigned char c1,c2; fread(&c1,1,1,f); fread(&c2,1,1,f); switch(c1) { case 0x00: // Numeric - Dec1000 case 0x09: // Text&Numeric - Dec1000 case 0x10: // Numeric - Scientific case 0x19: // Text&Numeric - Scientific case 0x20: // Numeric - Engeneering case 0x29: // Text&Numeric - Engeneering case 0x30: // Numeric - Dec1,000 case 0x39: // Text&Numeric - Dec1,000 SPREADSHEET[spread].column[col_index].value_type=(c1%0x10==0x9)?6:0; SPREADSHEET[spread].column[col_index].value_type_specification=c1/0x10; if(c2>=0x80) { SPREADSHEET[spread].column[col_index].significant_digits=c2-0x80; SPREADSHEET[spread].column[col_index].numeric_display_type=2; } else if(c2>0) { SPREADSHEET[spread].column[col_index].decimal_places=c2-0x03; SPREADSHEET[spread].column[col_index].numeric_display_type=1; } break; case 0x02: // Time SPREADSHEET[spread].column[col_index].value_type=3; SPREADSHEET[spread].column[col_index].value_type_specification=c2-0x80; break; case 0x03: // Date SPREADSHEET[spread].column[col_index].value_type=2; SPREADSHEET[spread].column[col_index].value_type_specification=c2-0x80; break; case 0x31: // Text SPREADSHEET[spread].column[col_index].value_type=1; break; case 0x4: // Month case 0x34: SPREADSHEET[spread].column[col_index].value_type=4; SPREADSHEET[spread].column[col_index].value_type_specification=c2; break; case 0x5: // Day case 0x35: SPREADSHEET[spread].column[col_index].value_type=5; SPREADSHEET[spread].column[col_index].value_type_specification=c2; break; default: // Text SPREADSHEET[spread].column[col_index].value_type=1; break; } fprintf(debug," COLUMN \"%s\" type = %s(%d) (@ 0x%X)\n", SPREADSHEET[spread].column[col_index].name.c_str(),colTypeNames[type],c,LAYER+0x11); fflush(debug); } LAYER+=0x1E7+0x1; fseek(f,LAYER,SEEK_SET); int comm_size=0; fread(&comm_size,4,1,f); if(IsBigEndian()) SwapBytes(comm_size); LAYER+=0x5; if(comm_size>0) { char* comment=new char[comm_size+1]; comment[comm_size]='\0'; fseek(f,LAYER,SEEK_SET); fread(comment,comm_size,1,f); if(col_index!=-1) SPREADSHEET[spread].column[col_index].comment=comment; LAYER+=comm_size+0x1; delete comment; } fseek(f,LAYER,SEEK_SET); int ntmp; fread(&ntmp,4,1,f); if(IsBigEndian()) SwapBytes(ntmp); if(ntmp!=0x1E7) break; } fprintf(debug," Done with spreadsheet %d\n",spread); fflush(debug); POS = LAYER+0x5*0x6+0x1ED*0x12; fseek(f,POS,SEEK_SET); } void OPJFile::readExcelInfo(FILE *f, FILE *debug) { int POS=ftell(f); int headersize; fread(&headersize,4,1,f); if(IsBigEndian()) SwapBytes(headersize); POS+=5; fprintf(debug," [EXCEL SECTION (@ 0x%X)]\n",POS); fflush(debug); // check spreadsheet name char name[25]; fseek(f,POS + 0x2,SEEK_SET); fread(&name,25,1,f); int iexcel=compareExcelnames(name); EXCEL[iexcel].name=name; readWindowProperties(EXCEL[iexcel], f, debug, POS, headersize); EXCEL[iexcel].bLoose=false; char c = 0; int LAYER = POS; LAYER += headersize + 0x1; int sec_size; int isheet=0; while(1)// multisheet loop { // LAYER section LAYER += 0x5/* length of block = 0x12D + '\n'*/ + 0x12D + 0x1; //now structure is next : section_header_size=0x6F(4 bytes) + '\n' + section_header(0x6F bytes) + section_body_1_size(4 bytes) + '\n' + section_body_1 + section_body_2_size(maybe=0)(4 bytes) + '\n' + section_body_2 + '\n' //possible sections: column formulas, __WIPR, __WIOTN, __LayerInfoStorage etc //section name(column name in formula case) starts with 0x46 position while(1) { //section_header_size=0x6F(4 bytes) + '\n' LAYER+=0x5; //section_header fseek(f,LAYER+0x46,SEEK_SET); char sec_name[42]; sec_name[41]='\0'; fread(&sec_name,41,1,f); fprintf(debug," DEBUG SECTION NAME: %s (@ 0x%X)\n", sec_name, LAYER+0x46); fflush(debug); //section_body_1_size LAYER+=0x6F+0x1; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_1 LAYER+=0x5; fseek(f,LAYER,SEEK_SET); //check if it is a formula int col_index=compareExcelColumnnames(iexcel, isheet, sec_name); if(col_index!=-1) { char *stmp=new char[sec_size+1]; stmp[sec_size]='\0'; fread(stmp,sec_size,1,f); EXCEL[iexcel].sheet[isheet].column[col_index].command=stmp; delete stmp; } //section_body_2_size LAYER+=sec_size+0x1; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_2 LAYER+=0x5; //close section 00 00 00 00 0A LAYER+=sec_size+(sec_size>0?0x1:0)+0x5; if(0==strcmp(sec_name,"__LayerInfoStorage")) break; } LAYER+=0x5; fflush(debug); /////////////// COLUMN Types /////////////////////////////////////////// fprintf(debug," Excel sheet %d has %d columns\n",isheet,EXCEL[iexcel].sheet[isheet].column.size()); while(1) { LAYER+=0x5; fseek(f,LAYER+0x12, SEEK_SET); fread(&name,12,1,f); fseek(f,LAYER+0x11, SEEK_SET); fread(&c,1,1,f); short width=0; fseek(f,LAYER+0x4A, SEEK_SET); fread(&width,2,1,f); if(IsBigEndian()) SwapBytes(width); //char col_name[30]; //sprintf(col_name, "%s@%d", name, isheet); int col_index=compareExcelColumnnames(iexcel, isheet, name); if(col_index!=-1) { ColumnType type; switch(c) { case 3: type = X; break; case 0: type = Y; break; case 5: type = Z; break; case 6: type = XErr; break; case 2: type = YErr; break; case 4: type = Label; break; default: type = NONE; break; } EXCEL[iexcel].sheet[isheet].column[col_index].type=type; width/=0xA; if(width==0) width=8; EXCEL[iexcel].sheet[isheet].column[col_index].width=width; fseek(f,LAYER+0x1E, SEEK_SET); unsigned char c1,c2; fread(&c1,1,1,f); fread(&c2,1,1,f); switch(c1) { case 0x00: // Numeric - Dec1000 case 0x09: // Text&Numeric - Dec1000 case 0x10: // Numeric - Scientific case 0x19: // Text&Numeric - Scientific case 0x20: // Numeric - Engeneering case 0x29: // Text&Numeric - Engeneering case 0x30: // Numeric - Dec1,000 case 0x39: // Text&Numeric - Dec1,000 EXCEL[iexcel].sheet[isheet].column[col_index].value_type=(c1%0x10==0x9)?6:0; EXCEL[iexcel].sheet[isheet].column[col_index].value_type_specification=c1/0x10; if(c2>=0x80) { EXCEL[iexcel].sheet[isheet].column[col_index].significant_digits=c2-0x80; EXCEL[iexcel].sheet[isheet].column[col_index].numeric_display_type=2; } else if(c2>0) { EXCEL[iexcel].sheet[isheet].column[col_index].decimal_places=c2-0x03; EXCEL[iexcel].sheet[isheet].column[col_index].numeric_display_type=1; } break; case 0x02: // Time EXCEL[iexcel].sheet[isheet].column[col_index].value_type=3; EXCEL[iexcel].sheet[isheet].column[col_index].value_type_specification=c2-0x80; break; case 0x03: // Date EXCEL[iexcel].sheet[isheet].column[col_index].value_type=2; EXCEL[iexcel].sheet[isheet].column[col_index].value_type_specification=c2-0x80; break; case 0x31: // Text EXCEL[iexcel].sheet[isheet].column[col_index].value_type=1; break; case 0x4: // Month case 0x34: EXCEL[iexcel].sheet[isheet].column[col_index].value_type=4; EXCEL[iexcel].sheet[isheet].column[col_index].value_type_specification=c2; break; case 0x5: // Day case 0x35: EXCEL[iexcel].sheet[isheet].column[col_index].value_type=5; EXCEL[iexcel].sheet[isheet].column[col_index].value_type_specification=c2; break; default: // Text EXCEL[iexcel].sheet[isheet].column[col_index].value_type=1; break; } fprintf(debug," COLUMN \"%s\" type = %d(%d) (@ 0x%X)\n", EXCEL[iexcel].sheet[isheet].column[col_index].name.c_str(),type,c,LAYER+0x11); fflush(debug); } LAYER+=0x1E7+0x1; fseek(f,LAYER,SEEK_SET); int comm_size=0; fread(&comm_size,4,1,f); if(IsBigEndian()) SwapBytes(comm_size); LAYER+=0x5; if(comm_size>0) { char* comment=new char[comm_size+1]; comment[comm_size]='\0'; fseek(f,LAYER,SEEK_SET); fread(comment,comm_size,1,f); if(col_index!=-1) EXCEL[iexcel].sheet[isheet].column[col_index].comment=comment; LAYER+=comm_size+0x1; delete comment; } fseek(f,LAYER,SEEK_SET); int ntmp; fread(&ntmp,4,1,f); if(IsBigEndian()) SwapBytes(ntmp); if(ntmp!=0x1E7) break; } fprintf(debug," Done with excel %d\n", iexcel); fflush(debug); //POS = LAYER+0x5*0x6+0x1ED*0x12; LAYER+=0x5*0x5+0x1ED*0x12; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); if(sec_size==0) break; isheet++; } POS = LAYER+0x5; fseek(f,POS,SEEK_SET); } void OPJFile::readMatrixInfo(FILE *f, FILE *debug) { int POS=ftell(f); int headersize; fread(&headersize,4,1,f); if(IsBigEndian()) SwapBytes(headersize); POS+=5; fprintf(debug," [Matrix SECTION (@ 0x%X)]\n",POS); fflush(debug); // check spreadsheet name char name[25]; fseek(f,POS + 0x2,SEEK_SET); fread(&name,25,1,f); int idx=compareMatrixnames(name); MATRIX[idx].name=name; readWindowProperties(MATRIX[idx], f, debug, POS, headersize); unsigned char h = 0; fseek(f,POS+0x87,SEEK_SET); fread(&h,1,1,f); switch(h) { case 1: MATRIX[idx].view = matrix::ImageView; break; case 2: MATRIX[idx].header = matrix::XY; break; } int LAYER = POS; LAYER += headersize + 0x1; int sec_size; // LAYER section LAYER +=0x5; fseek(f,LAYER+0x2B,SEEK_SET); short w=0; fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); MATRIX[idx].nr_cols=w; fseek(f,LAYER+0x52,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); MATRIX[idx].nr_rows=w; LAYER +=0x12D + 0x1; //now structure is next : section_header_size=0x6F(4 bytes) + '\n' + section_header(0x6F bytes) + section_body_1_size(4 bytes) + '\n' + section_body_1 + section_body_2_size(maybe=0)(4 bytes) + '\n' + section_body_2 + '\n' //possible sections: column formulas, __WIPR, __WIOTN, __LayerInfoStorage //section name(column name in formula case) starts with 0x46 position while(1) { //section_header_size=0x6F(4 bytes) + '\n' LAYER+=0x5; //section_header fseek(f,LAYER+0x46,SEEK_SET); char sec_name[42]; sec_name[41]='\0'; fread(&sec_name,41,1,f); //section_body_1_size LAYER+=0x6F+0x1; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_1 LAYER+=0x5; //check if it is a formula if(0==strcmp(sec_name,"MV")) { fseek(f,LAYER,SEEK_SET); char *stmp=new char[sec_size+1]; stmp[sec_size]='\0'; fread(stmp,sec_size,1,f); MATRIX[idx].command=stmp; delete stmp; } //section_body_2_size LAYER+=sec_size+0x1; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_2 LAYER+=0x5; //close section 00 00 00 00 0A LAYER+=sec_size+(sec_size>0?0x1:0)+0x5; if(0==strcmp(sec_name,"__LayerInfoStorage")) break; } LAYER+=0x5; while(1) { LAYER+=0x5; short width=0; fseek(f,LAYER+0x2B, SEEK_SET); fread(&width,2,1,f); if(IsBigEndian()) SwapBytes(width); width=(width-55)/0xA; if(width==0) width=8; MATRIX[idx].width=width; fseek(f,LAYER+0x1E, SEEK_SET); unsigned char c1,c2; fread(&c1,1,1,f); fread(&c2,1,1,f); MATRIX[idx].value_type_specification=c1/0x10; if(c2>=0x80) { MATRIX[idx].significant_digits=c2-0x80; MATRIX[idx].numeric_display_type=2; } else if(c2>0) { MATRIX[idx].decimal_places=c2-0x03; MATRIX[idx].numeric_display_type=1; } LAYER+=0x1E7+0x1; fseek(f,LAYER,SEEK_SET); int comm_size=0; fread(&comm_size,4,1,f); if(IsBigEndian()) SwapBytes(comm_size); LAYER+=0x5; if(comm_size>0) { LAYER+=comm_size+0x1; } fseek(f,LAYER,SEEK_SET); int ntmp; fread(&ntmp,4,1,f); if(IsBigEndian()) SwapBytes(ntmp); if(ntmp!=0x1E7) break; } LAYER+=0x5*0x5+0x1ED*0x12; POS = LAYER+0x5; fseek(f,POS,SEEK_SET); } void OPJFile::readGraphInfo(FILE *f, FILE *debug) { int POS=ftell(f); int headersize; fread(&headersize,4,1,f); if(IsBigEndian()) SwapBytes(headersize); POS+=5; fprintf(debug," [Graph SECTION (@ 0x%X)]\n",POS); fflush(debug); char name[25]; fseek(f,POS + 0x2,SEEK_SET); fread(&name,25,1,f); GRAPH.push_back(graph(name)); readWindowProperties(GRAPH.back(), f, debug, POS, headersize); unsigned short graph_width; fseek(f,POS + 0x23,SEEK_SET); fread(&graph_width,2,1,f); if(IsBigEndian()) SwapBytes(graph_width); GRAPH.back().width = graph_width; unsigned short graph_height; fread(&graph_height,2,1,f); if(IsBigEndian()) SwapBytes(graph_height); GRAPH.back().height = graph_height; int LAYER = POS; LAYER += headersize + 0x1; int sec_size; while(1)// multilayer loop { GRAPH.back().layer.push_back(graphLayer()); // LAYER section LAYER +=0x5; double range=0.0; unsigned char m=0; fseek(f, LAYER+0xF, SEEK_SET); fread(&range,8,1,f); if(IsBigEndian()) SwapBytes(range); GRAPH.back().layer.back().xAxis.min=range; fread(&range,8,1,f); if(IsBigEndian()) SwapBytes(range); GRAPH.back().layer.back().xAxis.max=range; fread(&range,8,1,f); if(IsBigEndian()) SwapBytes(range); GRAPH.back().layer.back().xAxis.step=range; fseek(f, LAYER+0x2B, SEEK_SET); fread(&m,1,1,f); GRAPH.back().layer.back().xAxis.majorTicks=m; fseek(f, LAYER+0x37, SEEK_SET); fread(&m,1,1,f); GRAPH.back().layer.back().xAxis.minorTicks=m; fread(&m,1,1,f); GRAPH.back().layer.back().xAxis.scale=m; fseek(f, LAYER+0x3A, SEEK_SET); fread(&range,8,1,f); if(IsBigEndian()) SwapBytes(range); GRAPH.back().layer.back().yAxis.min=range; fread(&range,8,1,f); if(IsBigEndian()) SwapBytes(range); GRAPH.back().layer.back().yAxis.max=range; fread(&range,8,1,f); if(IsBigEndian()) SwapBytes(range); GRAPH.back().layer.back().yAxis.step=range; fseek(f, LAYER+0x56, SEEK_SET); fread(&m,1,1,f); GRAPH.back().layer.back().yAxis.majorTicks=m; fseek(f, LAYER+0x62, SEEK_SET); fread(&m,1,1,f); GRAPH.back().layer.back().yAxis.minorTicks=m; fread(&m,1,1,f); GRAPH.back().layer.back().yAxis.scale=m; rect r; fseek(f, LAYER+0x71, SEEK_SET); fread(&r,sizeof(rect),1,f); if(IsBigEndian()) SwapBytes(r); GRAPH.back().layer.back().clientRect=r; LAYER += 0x12D + 0x1; //now structure is next : section_header_size=0x6F(4 bytes) + '\n' + section_header(0x6F bytes) + section_body_1_size(4 bytes) + '\n' + section_body_1 + section_body_2_size(maybe=0)(4 bytes) + '\n' + section_body_2 + '\n' //possible sections: axes, legend, __BC02, _202, _231, _232, __LayerInfoStorage etc //section name starts with 0x46 position while(1) { //section_header_size=0x6F(4 bytes) + '\n' LAYER+=0x5; //section_header fseek(f,LAYER+0x46,SEEK_SET); char sec_name[42]; sec_name[41]='\0'; fread(&sec_name,41,1,f); fseek(f, LAYER+0x3, SEEK_SET); fread(&r,sizeof(rect),1,f); if(IsBigEndian()) SwapBytes(r); unsigned char attach=0; fseek(f,LAYER+0x28,SEEK_SET); fread(&attach,1,1,f); unsigned char border=0; fseek(f, LAYER+0x29, SEEK_SET); fread(&border,1,1,f); unsigned char color=0; fseek(f,LAYER+0x33,SEEK_SET); fread(&color,1,1,f); //section_body_1_size LAYER+=0x6F+0x1; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_1 LAYER+=0x5; int size=sec_size; unsigned char type=0; fseek(f,LAYER,SEEK_SET); fread(&type,1,1,f); //text properties short rotation=0; fseek(f,LAYER+2,SEEK_SET); fread(&rotation,2,1,f); if(IsBigEndian()) SwapBytes(rotation); unsigned char fontsize=0; fread(&fontsize,1,1,f); unsigned char tab=0; fseek(f,LAYER+0xA,SEEK_SET); fread(&tab,1,1,f); //line properties unsigned char line_style = 0; double width = 0.0; lineVertex begin, end; unsigned int w = 0; fseek(f,LAYER+0x12,SEEK_SET); fread(&line_style,1,1,f); fseek(f,LAYER+0x13,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); width = (double)w/500.0; fseek(f,LAYER+0x20,SEEK_SET); fread(&begin.x,8,1,f); if(IsBigEndian()) SwapBytes(begin.x); fread(&end.x,8,1,f); if(IsBigEndian()) SwapBytes(end.x); fseek(f,LAYER+0x40,SEEK_SET); fread(&begin.y,8,1,f); if(IsBigEndian()) SwapBytes(begin.y); fread(&end.y,8,1,f); if(IsBigEndian()) SwapBytes(end.y); fseek(f,LAYER+0x60,SEEK_SET); fread(&begin.shape_type,1,1,f); fseek(f,LAYER+0x64,SEEK_SET); fread(&w,4,1,f); if(IsBigEndian()) SwapBytes(w); begin.shape_width = (double)w/500.0; fread(&w,4,1,f); if(IsBigEndian()) SwapBytes(w); begin.shape_length = (double)w/500.0; fseek(f,LAYER+0x6C,SEEK_SET); fread(&end.shape_type,1,1,f); fseek(f,LAYER+0x70,SEEK_SET); fread(&w,4,1,f); if(IsBigEndian()) SwapBytes(w); end.shape_width = (double)w/500.0; fread(&w,4,1,f); if(IsBigEndian()) SwapBytes(w); end.shape_length = (double)w/500.0; // bitmap properties short bitmap_width = 0; fseek(f,LAYER+0x1,SEEK_SET); fread(&bitmap_width,2,1,f); if(IsBigEndian()) SwapBytes(bitmap_width); short bitmap_height = 0; fread(&bitmap_height,2,1,f); if(IsBigEndian()) SwapBytes(bitmap_height); double bitmap_left = 0.0; fseek(f,LAYER+0x13,SEEK_SET); fread(&bitmap_left,8,1,f); if(IsBigEndian()) SwapBytes(bitmap_left); double bitmap_top = 0.0; fseek(f,LAYER+0x1B,SEEK_SET); fread(&bitmap_top,8,1,f); if(IsBigEndian()) SwapBytes(bitmap_top); //section_body_2_size LAYER+=sec_size+0x1; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_2 LAYER+=0x5; //check if it is a axis or legend fseek(f,1,SEEK_CUR); char stmp[255]; if(0==strcmp(sec_name,"XB")) { stmp[sec_size]='\0'; fread(&stmp,sec_size,1,f); GRAPH.back().layer.back().xAxis.pos = Bottom; GRAPH.back().layer.back().xAxis.label = text(stmp, r, color, fontsize, rotation/10, tab, (border >= 0x80 ? border-0x80 : None), attach); } else if(0==strcmp(sec_name,"XT")) { stmp[sec_size]='\0'; fread(&stmp,sec_size,1,f); GRAPH.back().layer.back().xAxis.pos=Top; GRAPH.back().layer.back().xAxis.label = text(stmp, r, color, fontsize, rotation/10, tab, (border >= 0x80 ? border-0x80 : None), attach); } else if(0==strcmp(sec_name,"YL")) { stmp[sec_size]='\0'; fread(&stmp,sec_size,1,f); GRAPH.back().layer.back().yAxis.pos = Left; GRAPH.back().layer.back().yAxis.label = text(stmp, r, color, fontsize, rotation/10, tab, (border >= 0x80 ? border-0x80 : None), attach); } else if(0==strcmp(sec_name,"YR")) { stmp[sec_size]='\0'; fread(&stmp,sec_size,1,f); GRAPH.back().layer.back().yAxis.pos = Right; GRAPH.back().layer.back().yAxis.label = text(stmp, r, color, fontsize, rotation/10, tab, (border >= 0x80 ? border-0x80 : None), attach); } else if(0==strcmp(sec_name,"Legend")) { stmp[sec_size]='\0'; fread(&stmp,sec_size,1,f); GRAPH.back().layer.back().legend = text(stmp, r, color, fontsize, rotation/10, tab, (border >= 0x80 ? border-0x80 : None), attach); } else if(0==strcmp(sec_name,"__BCO2")) // histogram { double d; fseek(f,LAYER+0x10,SEEK_SET); fread(&d,8,1,f); if(IsBigEndian()) SwapBytes(d); GRAPH.back().layer.back().histogram_bin=d; fseek(f,LAYER+0x20,SEEK_SET); fread(&d,8,1,f); if(IsBigEndian()) SwapBytes(d); GRAPH.back().layer.back().histogram_end=d; fseek(f,LAYER+0x28,SEEK_SET); fread(&d,8,1,f); if(IsBigEndian()) SwapBytes(d); GRAPH.back().layer.back().histogram_begin=d; } else if(size==0x3E) // text { stmp[sec_size]='\0'; fread(&stmp,sec_size,1,f); GRAPH.back().layer.back().texts.push_back(text(stmp)); GRAPH.back().layer.back().texts.back().color=color; GRAPH.back().layer.back().texts.back().clientRect=r; GRAPH.back().layer.back().texts.back().tab=tab; GRAPH.back().layer.back().texts.back().fontsize=fontsize; GRAPH.back().layer.back().texts.back().rotation=rotation/10; GRAPH.back().layer.back().texts.back().attach=attach; if(border>=0x80) GRAPH.back().layer.back().texts.back().border_type=border-0x80; else GRAPH.back().layer.back().texts.back().border_type=None; } else if(size==0x78 && type==2) // line { GRAPH.back().layer.back().lines.push_back(line()); GRAPH.back().layer.back().lines.back().color=color; GRAPH.back().layer.back().lines.back().clientRect=r; GRAPH.back().layer.back().lines.back().attach=attach; GRAPH.back().layer.back().lines.back().width=width; GRAPH.back().layer.back().lines.back().line_style=line_style; GRAPH.back().layer.back().lines.back().begin=begin; GRAPH.back().layer.back().lines.back().end=end; } else if(size==0x28 && type==4) // bitmap { unsigned long filesize=sec_size+14; GRAPH.back().layer.back().bitmaps.push_back(bitmap()); GRAPH.back().layer.back().bitmaps.back().left=bitmap_left; GRAPH.back().layer.back().bitmaps.back().top=bitmap_top; GRAPH.back().layer.back().bitmaps.back().width= (GRAPH.back().layer.back().xAxis.max - GRAPH.back().layer.back().xAxis.min)*bitmap_width/10000; GRAPH.back().layer.back().bitmaps.back().height= (GRAPH.back().layer.back().yAxis.max - GRAPH.back().layer.back().yAxis.min)*bitmap_height/10000; GRAPH.back().layer.back().bitmaps.back().attach=attach; GRAPH.back().layer.back().bitmaps.back().size=filesize; GRAPH.back().layer.back().bitmaps.back().data=new unsigned char[filesize]; unsigned char *data=GRAPH.back().layer.back().bitmaps.back().data; //add Bitmap header memcpy(data, "BM", 2); data+=2; memcpy(data, &filesize, 4); data+=4; unsigned int d=0; memcpy(data, &d, 4); data+=4; d=0x36; memcpy(data, &d, 4); data+=4; fread(data,sec_size,1,f); } //close section 00 00 00 00 0A LAYER+=sec_size+(sec_size>0?0x1:0); //section_body_3_size fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_3 LAYER+=0x5; //close section 00 00 00 00 0A LAYER+=sec_size+(sec_size>0?0x1:0); if(0==strcmp(sec_name,"__LayerInfoStorage")) break; } LAYER+=0x5; unsigned char h; short w; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); if(sec_size==0x1E7)//check layer is not empty { while(1) { LAYER+=0x5; graphCurve curve; vector col; fseek(f,LAYER+0x4,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); col=findDataByIndex(w-1); short nColY = w; if(col.size()>0) { fprintf(debug," GRAPH %d layer %d curve %d Y : %s.%s\n",GRAPH.size(),GRAPH.back().layer.size(),GRAPH.back().layer.back().curve.size(),col[1].c_str(),col[0].c_str()); fflush(debug); curve.yColName=col[0]; curve.dataName=col[1]; } fseek(f,LAYER+0x23,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); col=findDataByIndex(w-1); if(col.size()>0) { fprintf(debug," GRAPH %d layer %d curve %d X : %s.%s\n",GRAPH.size(),GRAPH.back().layer.size(),GRAPH.back().layer.back().curve.size(),col[1].c_str(),col[0].c_str()); fflush(debug); curve.xColName=col[0]; if(curve.dataName!=col[1]) fprintf(debug," GRAPH %d X and Y from different tables\n",GRAPH.size()); } fseek(f,LAYER+0x4C,SEEK_SET); fread(&h,1,1,f); curve.type=h; fseek(f,LAYER+0x11,SEEK_SET); fread(&h,1,1,f); curve.line_connect=h; fseek(f,LAYER+0x12,SEEK_SET); fread(&h,1,1,f); curve.line_style=h; fseek(f,LAYER+0x15,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); curve.line_width=(double)w/500.0; fseek(f,LAYER+0x19,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); curve.symbol_size=(double)w/500.0; fseek(f,LAYER+0x1C,SEEK_SET); fread(&h,1,1,f); curve.fillarea=(h==2?true:false); fseek(f,LAYER+0x1E,SEEK_SET); fread(&h,1,1,f); curve.fillarea_type=h; //vector if(curve.type == FlowVector || curve.type == Vector) { fseek(f,LAYER+0x56,SEEK_SET); fread(&curve.vector.multiplier,4,1,f); if(IsBigEndian()) SwapBytes(curve.vector.multiplier); fseek(f,LAYER+0x5E,SEEK_SET); fread(&h,1,1,f); col=findDataByIndex(nColY - 1 + h - 0x64); if(col.size()>0) { curve.vector.endXColName = col[0]; } fseek(f,LAYER+0x62,SEEK_SET); fread(&h,1,1,f); col=findDataByIndex(nColY - 1 + h - 0x64); if(col.size()>0) { curve.vector.endYColName = col[0]; } fseek(f,LAYER+0x18,SEEK_SET); fread(&h,1,1,f); if(h >= 0x64) { col=findDataByIndex(nColY - 1 + h - 0x64); if(col.size()>0) curve.vector.angleColName = col[0]; } else if(h <= 0x08) { curve.vector.const_angle = 45*h; } fseek(f,LAYER+0x19,SEEK_SET); fread(&h,1,1,f); if(h >= 0x64) { col=findDataByIndex(nColY - 1 + h - 0x64); if(col.size()>0) curve.vector.magnitudeColName = col[0]; } else { curve.vector.const_magnitude = (int) curve.symbol_size; } fseek(f,LAYER+0x66,SEEK_SET); fread(&curve.vector.arrow_lenght,2,1,f); if(IsBigEndian()) SwapBytes(curve.vector.arrow_lenght); fread(&curve.vector.arrow_angle,1,1,f); fread(&h,1,1,f); curve.vector.arrow_closed = !(h&0x1); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); curve.vector.width=(double)w/500.0; fseek(f,LAYER+0x142,SEEK_SET); fread(&h,1,1,f); switch(h) { case 2: curve.vector.position = Midpoint; break; case 4: curve.vector.position = Head; break; default: curve.vector.position = Tail; break; } } //pie if(curve.type == Pie) { fseek(f,LAYER+0x92,SEEK_SET); fread(&h,1,1,f); curve.pie.format_percentages = (h&0x01); curve.pie.format_values = (h&0x02); curve.pie.position_associate = (h&0x08); curve.pie.clockwise_rotation = (h&0x20); curve.pie.format_categories = (h&0x80); fread(&h,1,1,f); curve.pie.format_automatic = h; fread(&curve.pie.distance,2,1,f); if(IsBigEndian()) SwapBytes(curve.pie.distance); fread(&curve.pie.view_angle,1,1,f); fseek(f,LAYER+0x98,SEEK_SET); fread(&curve.pie.thickness,1,1,f); fseek(f,LAYER+0x9A,SEEK_SET); fread(&curve.pie.rotation,2,1,f); if(IsBigEndian()) SwapBytes(curve.pie.rotation); fseek(f,LAYER+0x9E,SEEK_SET); fread(&curve.pie.displacement,2,1,f); if(IsBigEndian()) SwapBytes(curve.pie.displacement); fseek(f,LAYER+0xA0,SEEK_SET); fread(&curve.pie.radius,2,1,f); if(IsBigEndian()) SwapBytes(curve.pie.radius); fseek(f,LAYER+0xA2,SEEK_SET); fread(&curve.pie.horizontal_offset,2,1,f); if(IsBigEndian()) SwapBytes(curve.pie.horizontal_offset); fseek(f,LAYER+0xA6,SEEK_SET); fread(&curve.pie.displaced_sections,4,1,f); if(IsBigEndian()) SwapBytes(curve.pie.displaced_sections); } fseek(f,LAYER+0xC2,SEEK_SET); fread(&h,1,1,f); curve.fillarea_color=h; fseek(f,LAYER+0xC3,SEEK_SET); fread(&h,1,1,f); curve.fillarea_first_color=h; fseek(f,LAYER+0xCE,SEEK_SET); fread(&h,1,1,f); curve.fillarea_pattern=h; fseek(f,LAYER+0xCA,SEEK_SET); fread(&h,1,1,f); curve.fillarea_pattern_color=h; fseek(f,LAYER+0xC6,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); curve.fillarea_pattern_width=(double)w/500.0; fseek(f,LAYER+0xCF,SEEK_SET); fread(&h,1,1,f); curve.fillarea_pattern_border_style=h; fseek(f,LAYER+0xD2,SEEK_SET); fread(&h,1,1,f); curve.fillarea_pattern_border_color=h; fseek(f,LAYER+0xD0,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); curve.fillarea_pattern_border_width=(double)w/500.0; fseek(f,LAYER+0x16A,SEEK_SET); fread(&h,1,1,f); curve.line_color=h; fseek(f,LAYER+0x17,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); curve.symbol_type=w; fseek(f,LAYER+0x12E,SEEK_SET); fread(&h,1,1,f); curve.symbol_fill_color=h; fseek(f,LAYER+0x132,SEEK_SET); fread(&h,1,1,f); curve.symbol_color=h; curve.vector.color=h; fseek(f,LAYER+0x136,SEEK_SET); fread(&h,1,1,f); curve.symbol_thickness=(h==255?1:h); fseek(f,LAYER+0x137,SEEK_SET); fread(&h,1,1,f); curve.point_offset=h; GRAPH.back().layer.back().curve.push_back(curve); LAYER+=0x1E7+0x1; fseek(f,LAYER,SEEK_SET); int comm_size=0; fread(&comm_size,4,1,f); if(IsBigEndian()) SwapBytes(comm_size); LAYER+=0x5; if(comm_size>0) { LAYER+=comm_size+0x1; } fseek(f,LAYER,SEEK_SET); int ntmp; fread(&ntmp,4,1,f); if(IsBigEndian()) SwapBytes(ntmp); if(ntmp!=0x1E7) break; } } //LAYER+=0x5*0x5+0x1ED*0x12; //LAYER+=2*0x5; LAYER+=0x5; //read axis breaks while(1) { fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); if(sec_size == 0x2D) { LAYER+=0x5; fseek(f,LAYER+2,SEEK_SET); fread(&h,1,1,f); if(h==2) { GRAPH.back().layer.back().xAxisBreak.minor_ticks_before = GRAPH.back().layer.back().xAxis.minorTicks; GRAPH.back().layer.back().xAxisBreak.scale_increment_before = GRAPH.back().layer.back().xAxis.step; readGraphAxisBreakInfo(GRAPH.back().layer.back().xAxisBreak, f, LAYER); } else if(h==4) { GRAPH.back().layer.back().yAxisBreak.minor_ticks_before = GRAPH.back().layer.back().yAxis.minorTicks; GRAPH.back().layer.back().yAxisBreak.scale_increment_before = GRAPH.back().layer.back().yAxis.step; readGraphAxisBreakInfo(GRAPH.back().layer.back().yAxisBreak, f, LAYER); } LAYER+=0x2D + 0x1; } else break; } LAYER+=0x5; LAYER+=0x5; readGraphGridInfo(GRAPH.back().layer.back().xAxis.minorGrid, f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; readGraphGridInfo(GRAPH.back().layer.back().xAxis.majorGrid, f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; readGraphAxisTickLabelsInfo(GRAPH.back().layer.back().xAxis.tickAxis[0], f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; readGraphAxisFormatInfo(GRAPH.back().layer.back().xAxis.formatAxis[0], f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; readGraphAxisTickLabelsInfo(GRAPH.back().layer.back().xAxis.tickAxis[1], f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; readGraphAxisFormatInfo(GRAPH.back().layer.back().xAxis.formatAxis[1], f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; LAYER+=0x5; readGraphGridInfo(GRAPH.back().layer.back().yAxis.minorGrid, f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; readGraphGridInfo(GRAPH.back().layer.back().yAxis.majorGrid, f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; readGraphAxisTickLabelsInfo(GRAPH.back().layer.back().yAxis.tickAxis[0], f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; readGraphAxisFormatInfo(GRAPH.back().layer.back().yAxis.formatAxis[0], f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; readGraphAxisTickLabelsInfo(GRAPH.back().layer.back().yAxis.tickAxis[1], f, LAYER); LAYER+=0x1E7+1; LAYER+=0x5; readGraphAxisFormatInfo(GRAPH.back().layer.back().yAxis.formatAxis[1], f, LAYER); LAYER+=0x1E7+1; LAYER+=0x2*0x5+0x1ED*0x6; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); if(sec_size==0) break; } POS = LAYER+0x5; fseek(f,POS,SEEK_SET); } void OPJFile::skipObjectInfo(FILE *f, FILE *) { int POS=ftell(f); int headersize; fread(&headersize,4,1,f); if(IsBigEndian()) SwapBytes(headersize); POS+=5; int LAYER = POS; LAYER += headersize + 0x1; int sec_size; while(1)// multilayer loop { // LAYER section LAYER +=0x5/* length of block = 0x12D + '\n'*/ + 0x12D + 0x1; //now structure is next : section_header_size=0x6F(4 bytes) + '\n' + section_header(0x6F bytes) + section_body_1_size(4 bytes) + '\n' + section_body_1 + section_body_2_size(maybe=0)(4 bytes) + '\n' + section_body_2 + '\n' //possible sections: column formulas, __WIPR, __WIOTN, __LayerInfoStorage //section name(column name in formula case) starts with 0x46 position while(1) { //section_header_size=0x6F(4 bytes) + '\n' LAYER+=0x5; //section_header fseek(f,LAYER+0x46,SEEK_SET); char sec_name[42]; sec_name[41]='\0'; fread(&sec_name,41,1,f); //section_body_1_size LAYER+=0x6F+0x1; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_1 LAYER+=0x5; //section_body_2_size LAYER+=sec_size+0x1; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_2 LAYER+=0x5; //close section 00 00 00 00 0A LAYER+=sec_size+(sec_size>0?0x1:0); //section_body_3_size fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); //section_body_3 LAYER+=0x5; //close section 00 00 00 00 0A LAYER+=sec_size+(sec_size>0?0x1:0); if(0==strcmp(sec_name,"__LayerInfoStorage")) break; } LAYER+=0x5; while(1) { LAYER+=0x5; LAYER+=0x1E7+0x1; fseek(f,LAYER,SEEK_SET); int comm_size=0; fread(&comm_size,4,1,f); if(IsBigEndian()) SwapBytes(comm_size); LAYER+=0x5; if(comm_size>0) { LAYER+=comm_size+0x1; } fseek(f,LAYER,SEEK_SET); int ntmp; fread(&ntmp,4,1,f); if(IsBigEndian()) SwapBytes(ntmp); if(ntmp!=0x1E7) break; } LAYER+=0x5*0x5+0x1ED*0x12; fseek(f,LAYER,SEEK_SET); fread(&sec_size,4,1,f); if(IsBigEndian()) SwapBytes(sec_size); if(sec_size==0) break; } POS = LAYER+0x5; fseek(f,POS,SEEK_SET); } void OPJFile::readGraphGridInfo(graphGrid &grid, FILE *f, int pos) { unsigned char h; short w; fseek(f,pos+0x26,SEEK_SET); fread(&h,1,1,f); grid.hidden=(h==0); fseek(f,pos+0xF,SEEK_SET); fread(&h,1,1,f); grid.color=h; fseek(f,pos+0x12,SEEK_SET); fread(&h,1,1,f); grid.style=h; fseek(f,pos+0x15,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); grid.width=(double)w/500.0; } void OPJFile::readGraphAxisBreakInfo(graphAxisBreak &axis_break, FILE *f, int pos) { axis_break.show=true; fseek(f,pos+0x0B,SEEK_SET); fread(&axis_break.from,8,1,f); if(IsBigEndian()) SwapBytes(axis_break.from); fread(&axis_break.to,8,1,f); if(IsBigEndian()) SwapBytes(axis_break.to); fread(&axis_break.scale_increment_after,8,1,f); if(IsBigEndian()) SwapBytes(axis_break.scale_increment_after); double position=0.0; fread(&position,8,1,f); if(IsBigEndian()) SwapBytes(position); axis_break.position=(int)position; unsigned char h; fread(&h,1,1,f); axis_break.log10=(h==1); fread(&axis_break.minor_ticks_after,1,1,f); } void OPJFile::readGraphAxisFormatInfo(graphAxisFormat &format, FILE *f, int pos) { unsigned char h; short w; double p; fseek(f,pos+0x26,SEEK_SET); fread(&h,1,1,f); format.hidden=(h==0); fseek(f,pos+0xF,SEEK_SET); fread(&h,1,1,f); format.color=h; fseek(f,pos+0x4A,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); format.majorTickLength=(double)w/10.0; fseek(f,pos+0x15,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); format.thickness=(double)w/500.0; fseek(f,pos+0x25,SEEK_SET); fread(&h,1,1,f); format.minorTicksType=(h>>6); format.majorTicksType=((h>>4)&3); format.axisPosition=(h&0xF); switch(format.axisPosition) { case 1: fseek(f,pos+0x37,SEEK_SET); fread(&h,1,1,f); format.axisPositionValue=(double)h; break; case 2: fseek(f,pos+0x2F,SEEK_SET); fread(&p,8,1,f); if(IsBigEndian()) SwapBytes(p); format.axisPositionValue=p; break; } } void OPJFile::readGraphAxisTickLabelsInfo(graphAxisTick &tick, FILE *f, int pos) { unsigned char h; unsigned char h1; short w; fseek(f,pos+0x26,SEEK_SET); fread(&h,1,1,f); tick.hidden=(h==0); fseek(f,pos+0xF,SEEK_SET); fread(&h,1,1,f); tick.color=h; fseek(f,pos+0x13,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); tick.rotation=w/10; fseek(f,pos+0x15,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); tick.fontsize=w; fseek(f,pos+0x1A,SEEK_SET); fread(&h,1,1,f); tick.fontbold=(h&0x8); fseek(f,pos+0x23,SEEK_SET); fread(&w,2,1,f); if(IsBigEndian()) SwapBytes(w); fseek(f,pos+0x25,SEEK_SET); fread(&h,1,1,f); fread(&h1,1,1,f); tick.value_type=(h&0xF); vector col; switch(tick.value_type) { case 0: //Numeric /*switch((h>>4)) { case 0x9: tick.value_type_specification=1; break; case 0xA: tick.value_type_specification=2; break; case 0xB: tick.value_type_specification=3; break; default: tick.value_type_specification=0; }*/ if((h>>4)>7) { tick.value_type_specification=(h>>4)-8; tick.decimal_places=h1-0x40; } else { tick.value_type_specification=(h>>4); tick.decimal_places=-1; } break; case 2: // Time case 3: // Date case 4: // Month case 5: // Day case 6: // Column heading tick.value_type_specification=h1-0x40; break; case 1: // Text case 7: // Tick-indexed dataset case 10: // Categorical col=findDataByIndex(w-1); if(col.size()>0) { tick.colName=col[0]; tick.dataName=col[1]; } break; default: // Numeric Decimal 1.000 tick.value_type=Numeric; tick.value_type_specification=0; break; } } void OPJFile::readProjectTree(FILE *f, FILE *debug) { readProjectTreeFolder(f, debug, projectTree.begin()); fprintf(debug,"Origin project Tree\n"); tree::iterator sib2=projectTree.begin(projectTree.begin()); tree::iterator end2=projectTree.end(projectTree.begin()); while(sib2!=end2) { for(int i=0; i::iterator parent) { int POS=ftell(f); double creation_date, modification_date; POS+=5; fseek(f,POS+0x10,SEEK_SET); fread(&creation_date,8,1,f); if(IsBigEndian()) SwapBytes(creation_date); fread(&modification_date,8,1,f); if(IsBigEndian()) SwapBytes(modification_date); POS+=0x20+1+5; fseek(f,POS,SEEK_SET); int namesize; fread(&namesize,4,1,f); if(IsBigEndian()) SwapBytes(namesize); POS+=5; // read folder name char* name=new char[namesize+1]; name[namesize]='\0'; fseek(f,POS,SEEK_SET); fread(name,namesize,1,f); tree::iterator current_folder=projectTree.append_child(parent, projectNode(name, 1, creation_date, modification_date)); POS+=namesize+1+5+5; int objectcount; fseek(f,POS,SEEK_SET); fread(&objectcount,4,1,f); if(IsBigEndian()) SwapBytes(objectcount); POS+=5+5; for(int i=0; i 0xC3) { int labellen = 0; fseek(f,POS + 0xC3,SEEK_SET); fread(&c,1,1,f); while (c != '@') { fread(&c,1,1,f); labellen++; } if(labellen > 0) { char *label=new char[labellen+1]; label[labellen]='\0'; fseek(f,POS + 0xC3,SEEK_SET); fread(label,labellen,1,f); window.label=label; delete label; } else window.label=""; fprintf(debug," WINDOW %d LABEL: %s\n", objectIndex, window.label.c_str()); fflush(debug); } } bool OPJFile::IsBigEndian() { short word = 0x4321; if((*(char *)& word) != 0x21 ) return true; else return false; }